Sie sind auf Seite 1von 1205

Thinking in Java

Second Edition President, MindView, Inc.

Bruce Eckel

Comments from readers:


Much better than any other Java book I ve seen. Make that !by an order o"
#agnitude$... very co#%lete, with e&cellent right'to'the'%oint e&a#%les and intelligent, not du#bed'down, e&%lanations ... In contrast to #any other Java books I "ound it to be unusually #ature, consistent, intellectually honest, well'written and %recise. IM(), an ideal book "or studying Java. Anatoly Vorobey, Technion University, Haifa,

Israel
)ne o" the absolutely best %rogra##ing tutorials I ve seen "or any language. Joakim Ziegler, FIX sysop Thank you "or your wonder"ul, wonder"ul book on Java. r! "avin #illay, $egistrar, %ing &'(ar' VIII Hospital, )o*th Africa Thank you again "or your aweso#e book. I was really "loundering *being a non'+ %rogra##er,, but your book has brought #e u% to s%eed as "ast as I could read it. It s really cool to be able to understand the underlying %rinci%les and conce%ts "ro# the start, rather than having to try to build that conce%tual #odel through trial and error. (o%e"ully I will be able to attend your se#inar in the not'too'distant "uture. $an'all $! Ha(ley,

A*tomation Technician, &li +illy , -o!


The best co#%uter book writing I have seen. Tom Hollan' This is one o" the best books I ve read about a %rogra##ing languageThe best book ever written on Java. $avin'ra #ai, .racle

-orporation, )U/.) pro'*ct line


This is the best book on Java that I have ever "ound. /ou have done a great 0ob. /our de%th is a#a1ing. I will be %urchasing the book when it is %ublished. I have been learning Java since )ctober 23. I have read a "ew books, and consider yours a !M4ST 5E67.$ These %ast "ew #onths we have been "ocused on a %roduct written entirely in Java. /our book has hel%ed solidi"y to%ics I was shaky on and has e&%anded #y knowledge base. I have even used so#e o" your e&%lanations as in"or#ation in interviewing contractors to hel% our tea#. I have "ound how #uch Java knowledge they have by asking the# about things I have learned "ro# reading your book *e.g., the di""erence between arrays and Vectors,. /our

book is great. )teve 0ilkinson, )enior )taff )pecialist, 1-I

Telecomm*nications
8reat book. Best book on Java I have seen so "ar. Jeff )inclair,

)oft(are &ngineer, %estral -omp*ting


Thank you "or Thinking in Java. It s ti#e so#eone went beyond #ere language descri%tion to a thought"ul, %enetrating analytic tutorial that doesn t kowtow to The Manu"acturers. I ve read al#ost all the others9 only yours and Patrick :inston s have "ound a %lace in #y heart. I # already reco##ending it to custo#ers. Thanks again. $ichar' 2rooks,

Java -ons*ltant, )*n #rofessional )ervices,

allas

)ther books cover the :(6T o" Java *describing the synta& and the libraries, or the (): o" Java *%ractical %rogra##ing e&a#%les,. Thinking in Java is the only book I know that e&%lains the :(/ o" Java; why it was designed the way it was, why it works the way it does, why it so#eti#es doesn t work, why it s better than +<<, why it s not. 6lthough it also does a good 0ob o" teaching the what and how o" the language, Thinking in Java is de"initely the thinking %erson s choice in a Java book.

$obert )! )tephenson
Thanks "or writing a great book. The #ore I read it the better I like it. My students like it, too. -h*ck Iverson I 0ust want to co##end you "or your work on Thinking in Java. It is %eo%le like you that digni"y the "uture o" the Internet and I 0ust want to thank you "or your e""ort. It is very #uch a%%reciated. #atrick 2arrell,

/et(ork .fficer 1amco, 3AF 1fg! Inc!


Most o" the Java books out there are "ine "or a start, and #ost 0ust have beginning stu"" and a lot o" the sa#e e&a#%les. /ours is by "ar the best advanced thinking book I ve seen. Please %ublish it soon. ... I also bought Thinking in C++ 0ust because I was so i#%ressed with Thinking in Java.

"eorge +aframboise, +ight0or4 Technology -ons*lting, Inc!


I wrote to you earlier about #y "avorable i#%ressions regarding your Thinking in C++ *a book that stands %ro#inently on #y shel" here at work,. 6nd today I ve been able to delve into Java with your e'book in #y virtual hand, and I #ust say *in #y best +hevy +hase "ro# Modern Problems, !I like it.$ Very in"or#ative and e&%lanatory, without reading

like a dry te&tbook. /ou cover the #ost i#%ortant yet the least covered conce%ts o" Java develo%#ent= the whys. )ean 2ra'y /our e&a#%les are clear and easy to understand. /ou took care o" #any i#%ortant details o" Java that can t be "ound easily in the weak Java docu#entation. 6nd you don t waste the reader s ti#e with the basic "acts a %rogra##er already knows. %ai &ngert, Innovative )oft(are,

"ermany
I # a great "an o" your Thinking in C++ and have reco##ended it to associates. 6s I go through the electronic version o" your Java book, I # "inding that you ve retained the sa#e high level o" writing. Thank you.

#eter $! /e*(al'
VE5/ well'written Java book...I think you ve done a 85E6T 0ob on it. 6s the leader o" a +hicago'area Java s%ecial interest grou%, I ve "avorably #entioned your book and :eb site several ti#es at our recent #eetings. I would like to use Thinking in Java as the basis "or a %art o" each #onthly SI8 #eeting, in which we review and discuss each cha%ter in succession.

1ark &rtes
I really a%%reciate your work and your book is good. I reco##end it here to our users and Ph.7. students. H*g*es +eroy 55 Irisa6Inria $ennes

France, Hea' of )cientific -omp*ting an' In'*strial Tranfert


)>, I ve only read about ?@ %ages o" Thinking in Java, but I ve already "ound it to be the #ost clearly written and %resented %rogra##ing book I ve co#e across...and I # a writer, #ysel", so I a# %robably a little critical. I have Thinking in C++ on order and can t wait to crack it9I # "airly new to %rogra##ing and a# hitting learning curves head'on everywhere. So this is 0ust a Auick note to say thanks "or your e&cellent work. I had begun to burn a little low on enthusias# "ro# slogging through the #ucky, #urky %rose o" #ost co#%uter books9even ones that ca#e with glowing reco##endations. I "eel a whole lot better now.

"lenn 2ecker, &'*cational Theatre Association


Thank you "or #aking your wonder"ul book available. I have "ound it i##ensely use"ul in "inally understanding what I e&%erienced as con"using in Java and +<<. 5eading your book has been very satis"ying.

Feli4 2i7ao*i, T(in .aks In'*stries, +o*isa, Va!

I #ust congratulate you on an e&cellent book. I decided to have a look at

Thinking in Java based on #y e&%erience with Thinking in C++, and I was not disa%%ointed. Jaco van 'er 1er(e, )oft(are )pecialist, ataF*sion )ystems +t', )tellenbosch, )o*th Africa
This has to be one o" the best Java books I ve seen. &!F! #ritchar', )enior )oft(are &ngineer, -ambri'ge Animation )ystems +t'!, Unite' %ing'om /our book #akes all the other Java books I ve read or "li%%ed through see# doubly useless and insulting. 2rett g #orter, )enior

#rogrammer, Art , +ogic


I have been reading your book "or a week or two and co#%ared to the books I have read earlier on Java, your book see#s to have given #e a great start. I have reco##ended this book to a lot o" #y "riends and they have rated it e&cellent. Please acce%t #y congratulations "or co#ing out with an e&cellent book. $ama %rishna 2h*pathi, )oft(are

&ngineer, T-)I -orporation, )an Jose


Just wanted to say what a !brilliant$ %iece o" work your book is. I ve been using it as a #a0or re"erence "or in'house Java work. I "ind that the table o" contents is 0ust right "or Auickly locating the section that is reAuired. It s also nice to see a book that is not 0ust a rehash o" the 6PI nor treats the %rogra##er like a du##y. "rant )ayer, Java -omponents

"ro*p +ea'er, -ee'ata )ystems #ty +t', A*stralia


:ow. 6 readable, in'de%th Java book. There are a lot o" %oor *and ad#ittedly a cou%le o" good, Java books out there, but "ro# what I ve seen yours is de"initely one o" the best. John $oot, 0eb eveloper,

epartment of )ocial )ec*rity, +on'on


I ve B0ustB started Thinking in Java. I e&%ect it to be very good because I really liked Thinking in C++ *which I read as an e&%erienced +<< %rogra##er, trying to stay ahead o" the curve,. I # so#ewhat less e&%erienced in Java, but e&%ect to be very satis"ied. /ou are a wonder"ul author. %evin %! +e(is, Technologist, .b8ect)pace, Inc! I think it s a great book. I learned all I know about Java "ro# this book. Thank you "or #aking it available "or "ree over the Internet. I" you wouldn t have I d know nothing about Java at all. But the best thing is

that your book isn t a co##ercial brochure "or Java. It also shows the bad sides o" Java. /)4 have done a great 0ob here. Fre'erik Fi4, 2elgi*m I have been hooked to your books all the ti#e. 6 cou%le o" years ago, when I wanted to start with +<<, it was C++ Inside & Out which took #e around the "ascinating world o" +<<. It hel%ed #e in getting better o%%ortunities in li"e. Cow, in %ursuit o" #ore knowledge and when I wanted to learn Java, I bu#%ed into Thinking in Java9no doubts in #y #ind as to whether I need so#e other book. Just "antastic. It is #ore like rediscovering #ysel" as I get along with the book. It is 0ust a #onth since I started with Java, and heart"elt thanks to you, I a# understanding it better now. Anan' %*mar )!, )oft(are &ngineer,

-omp*tervision, In'ia
/our book stands out as an e&cellent general introduction. #eter $obinson, University of -ambri'ge -omp*ter +aboratory It s by "ar the best #aterial I have co#e across to hel% #e learn Java and I 0ust want you to know how lucky I "eel to have "ound it. T(6C>S. -h*ck

#eterson, #ro'*ct +ea'er, Internet #ro'*ct +ine, IVI) International


The book is great. It s the third book on Java I ve started and I # about two'thirds o" the way through it now. I %lan to "inish this one. I "ound out about it because it is used in so#e internal classes at Ducent Technologies and a "riend told #e the book was on the Cet. 8ood work. Jerry

/o(lin, 1T), +*cent Technologies


)" the si& or so Java books I ve accu#ulated to date, your Thinking in Java is by "ar the best and clearest. 1ichael Van 0aas, #h! !,

#resi'ent, T1$ Associates


I 0ust want to say thanks "or Thinking in Java. :hat a wonder"ul book you ve #ade here. Cot to #ention downloadable "or "ree. 6s a student I "ind your books invaluable *I have a co%y o" C++ Inside Out, another great book about +<<,, because they not only teach #e the how'to, but also the whys, which are o" course very i#%ortant in building a strong "oundation in languages such as +<< or Java. I have Auite a lot o" "riends here who love %rogra##ing 0ust as I do, and I ve told the# about your books. They think it s great. Thanks again. By the way, I # Indonesian

and I live in Java. $ay Fre'erick

8a8a'inata, )t*'ent at Trisakti

University, Jakarta
The #ere "act that you have #ade this work "ree over the Cet %uts #e into shock. I thought I d let you know how #uch I a%%reciate and res%ect what you re doing. )hane +e2o*thillier, -omp*ter &ngineering

st*'ent, University of Alberta, -ana'a


I have to tell you how #uch I look "orward to reading your #onthly colu#n. 6s a newbie to the world o" ob0ect oriented %rogra##ing, I a%%reciate the ti#e and thought"ulness that you give to even the #ost ele#entary to%ic. I have downloaded your book, but you can bet that I will %urchase the hard co%y when it is %ublished. Thanks "or all o" your hel%. an -ashmer, 2! -! Ziegler , -o! Just want to congratulate you on a 0ob well done. Eirst I stu#bled u%on the P7E version o" Thinking in Java. Even be"ore I "inished reading it, I ran to the store and "ound Thinking in C++. Cow, I have been in the co#%uter business "or over eight years, as a consultant, so"tware engineer, teacherFtrainer, and recently as sel"'e#%loyed, so I d like to think that I have seen enough *not !have seen it all,$ #ind you, but enough,. (owever, these books cause #y girl"riend to call #e a $geek.$ Cot that I have anything against the conce%t9it is 0ust that I thought this %hase was well beyond #e. But I "ind #ysel" truly en0oying both books, like no other co#%uter book I have touched or bought so "ar. E&cellent writing style, very nice introduction o" every new to%ic, and lots o" wisdo# in the books. :ell done. )imon "olan', simonse79smartt!

com, )imon )ays -ons*lting, Inc!


I #ust say that your Thinking in Java is great. That is e&actly the kind o" docu#entation I was looking "or. Es%ecially the sections about good and %oor so"tware design using Java. irk *ehr, +e4ikon Verlag,

2ertelsmann A", "ermany


Thank you "or writing two great books * Thinking in C++, Thinking in Java,. /ou have hel%ed #e i##ensely in #y %rogression to ob0ect oriented %rogra##ing. onal' +a(son, -+ &nterprises Thank you "or taking the ti#e to write a really hel%"ul book on Java. I" teaching #akes you understand so#ething, by now you #ust be %retty %leased with yoursel". ominic T*rner, "&A- )*pport

It s the best Java book I have ever read9and I read so#e. Jean6:ves 1&/"A/T, -hief )oft(are Architect /AT6):)T&1, #aris, France

Thinking in Java gives the best coverage and e&%lanation. Very easy to read, and I #ean the code "rag#ents as well. $on -han, #h! !, &4pert -hoice, Inc!, #ittsb*rgh #A
/our book is great. I have read lots o" %rogra##ing books and your book still adds insights to %rogra##ing in #y #ind. /ing8ian 0ang,

Information )ystem &ngineer, The Vang*ar' "ro*p Thinking in Java is an e&cellent and readable book. I reco##end it to all #y students. r! #a*l "orman, epartment of -omp*ter )cience, University of .tago, *ne'in, /e( Zealan'
/ou #ake it %ossible "or the %roverbial "ree lunch to e&ist, not 0ust a sou% kitchen ty%e o" lunch but a gour#et delight "or those who a%%reciate good so"tware and books about it. Jose )*riol, )cyla4 -orporation Thanks "or the o%%ortunity o" watching this book grow into a #aster%iece. IT IS T(E BEST book on the sub0ect that I ve read or browsed. Jeff +apchinsky, #rogrammer, /et $es*lts

Technologies
/our book is concise, accessible and a 0oy to read. %eith $itchie, Java

$esearch ,

evelopment Team, %+ "ro*p Inc! aniel &ng

It truly is the best book I ve read on Java.

The best book I have seen on Java. $ich Hoffarth, )enior Architect,

0est "ro*p
Thank you "or a wonder"ul book. I # having a lot o" "un going through the cha%ters. Fre' Trimble, Acti*m -orporation /ou have #astered the art o" slowly and success"ully #aking us gras% the details. /ou #ake learning VE5/ easy and satis"ying. Thank you "or a truly wonder"ul tutorial. $a8esh $a*, )oft(are -ons*ltant

Thinking in Java rocks the "ree world. 1iko .;)*llivan, #resi'ent, I'ocs Inc!

Abo*t Thinking in C++<


2est 2ook= 0inner of the >??@ )oft(are evelopment 1aga7ine Jolt A(ar'=

!This book is a tre#endous achieve#ent. /ou owe it to yoursel" to have a co%y on your shel". The cha%ter on iostrea#s is the #ost co#%rehensive and understandable treat#ent o" that sub0ect I ve seen to date.$

Al )tevens -ontrib*ting &'itor, Doctor Dobbs Journal

!Eckel s book is the only one to so clearly e&%lain how to rethink %rogra# construction "or ob0ect orientation. That the book is also an e&cellent tutorial on the ins and outs o" +<< is an added bonus.$

An're( 2instock &'itor, Unix Review


!Bruce continues to a#a1e #e with his insight into +<<, and Thinking in C++ is his best collection o" ideas yet. I" you want clear answers to di""icult Auestions about +<<, buy this outstanding book.$

"ary &ntsminger A*thor, The Tao of Objects


!Thinking in C++ %atiently and #ethodically e&%lores the issues o" when and how to use inlines, re"erences, o%erator overloading, inheritance, and dyna#ic ob0ects, as well as advanced to%ics such as the %ro%er use o" te#%lates, e&ce%tions and #ulti%le inheritance. The entire e""ort is woven in a "abric that includes Eckel s own %hiloso%hy o" ob0ect and %rogra# design. 6 #ust "or every +<< develo%er s bookshel", Thinking in C++ is the one +<< book you #ust have i" you re doing serious develo%#ent with +<<.$

$ichar' Hale )ha( -ontrib*ting &'itor, #- 1aga7ine

Thinking in Java
Second Edition

Bruce Eckel
President, MindView, Inc.

Prentice (all 4%%er Saddle 5iver, Cew Jersey @G?HI www.%h%tr.co#

Library of Congress Cataloging-in-Publication Data Eckel, Bruce. Thinking in Java / Bruce Eckel.-- n! e!. ". c#. $%B& '-()-' *)+)-, (. Java -Co#"uter "rogra# language. $. Title. /0*+.*).J)1E , ''' '',.()2)--!c ( ''-')*, C$P
Editorial/Production Su ervision! Cicholas 5adhuber "c#uisitions Editor! Paul Petralia Manu$acturing Manager! Maura 8oldstaub Marketing Manager! Bryan 8a#brel Cover %esign! 7aniel :ill'(arris Interior %esign! 7aniel :ill'(arris, www.will'harris.co#

J K@@@ by Bruce Eckel, President, MindView, Inc. Published by Prentice (all PT5 Prentice'(all, Inc. 4%%er Saddle 5iver, CJ @G?HI
The in"or#ation in this book is distributed on an !as is$ basis, without warranty. :hile every %recaution has been taken in the %re%aration o" this book, neither the author nor the %ublisher shall have any liability to any %erson or entitle with res%ect to any liability, loss or da#age caused or alleged to be caused directly or indirectly by instructions contained in this book or by the co#%uter so"tware or hardware %roducts described herein. 6ll rights reserved. Co %art o" this book #ay be re%roduced, in any "or# or by any #eans, without %er#ission in writing "ro# the %ublisher. Prentice'(all books are widely used by cor%orations and govern#ent agencies "or training, #arketing, and resale. The %ublisher o""ers discounts on this book when ordered in bulk Auantities. Eor #ore in"or#ation, contact the +or%orate Sales 7e%art#ent at I@@'LIK'L?M2, "a&= K@M'KL3'GM?M, e#ail=cor sales& renhall' com or write= +or%orate Sales 7e%art#ent, Prentice (all PT5, )ne Dake Street, 4%%er Saddle 5iver, Cew Jersey @G?HI. Java is a registered trade#ark o" Sun Microsyste#s, Inc. :indows 2H and :indows CT are trade#arks o" Microso"t +or%oration. 6ll other %roduct na#es and co#%any na#es #entioned herein are the %ro%erty o" their res%ective owners.

Printed in the 4nited States o" 6#erica M@ 2 I G 3 H ? L K M ISBC @'ML'@KGL3L'H


Prentice'(all International *4>, Di#ited, (ondon Prentice'(all o" 6ustralia Pty. Di#ited, S)dne) Prentice'(all +anada, Inc., Toronto Prentice'(all (is%anoa#ericana, S.6., Me*ico Prentice'(all o" India Private Di#ited, +e, %elhi Prentice'(all o" Ja%an, Inc., Tok)o Pearson Education 6sia Dtd., Singa ore Editora Prentice'(all do Brasil, Dtda., -io de Janeiro

Bruce Eckels Hands-On Java Seminar Multimedia CD Its like coming to the seminar! Available at www.BruceEckel.com

The .ands/On Java Seminar ca%tured on a Multi#edia +7.

)verhead slides and synchroni1ed audio voice narration "or all the lectures. Just %lay it to see and hear the lectures. +reated and narrated by Bruce Eckel. Based on the #aterial in this book.

7e#o lecture available at ,,,'0ruceEckel'com

7edication
To the %erson who, even now, is creating the ne&t great co#%uter language

Overview Whats Inside

Pre"ace.................................................................................... M Introduction........................................................................... 2 M= Introduction to )b0ects............................................................................. L@ K= Everything is an )b0ect......................................................................... M@3 L= +ontrolling Progra# Elow.............................................. ML2 ?= Initiali1ation N +leanu%........................................................................... M2I H= (iding the I#%le#entation........................................... KHK 3= 5eusing +lasses.............................................................. KIM G= Poly#or%his#................................................................ LKK I= Inter"aces N Inner +lasses............................................. L3K 2= (olding /our )b0ects....................................................................... ?KK M@= Error (andling with E&ce%tions................................................................... HHM MM= The Java IF) Syste#......................................................................... H2? MK= 5un'ti#e Ty%e Identi"ication....................................... 3IH ML= +reating :indows N 6%%lets............................................................................. GM3 M?= Multi%le Threads.......................................................... IH3 MH= 7istributed +o#%uting................................................. 2LG 6= Passing N 5eturning )b0ects....................................... M@HL B= The Java Cative Inter"ace *JCI,................................... MM@3

+= Java Progra##ing 8uidelines...................................... MMM2 7= 5esources..................................................................... MML3 Inde&................................................................................. MM?L


Bruce Eckel s (ands')n Java Se#inar Multi#edia +7 It s like co#ing to the se#inar. 6vailable at www.BruceEckel.co#............................................................MK

Pre"ace.................................................................................... M
Pre"ace to the Knd edition............................................................................ ?
Java K........................................................................................................................................... 3

The +7 5)M.................................................................................................. G

Introduction........................................................................... 2
PrereAuisites.................................................................................................. 2 Dearning Java............................................................................................... M@ 8oals.............................................................................................................. MM )nline docu#entation................................................................................ MK +ha%ters........................................................................................................ ML E&ercises....................................................................................................... M2 Multi#edia +7 5)M..................................................................................K@ Source code.................................................................................................. K@
+oding standards....................................................................................................................... KK

Java versions................................................................................................KL Se#inars and #entoring............................................................................K? Errors............................................................................................................ K? Cote on the cover design............................................................................ KH 6cknowledge#ents..................................................................................... K3
Internet contributors................................................................................................................. K2

M= Introduction to )b0ects............................................................................. L@
The %rogress o" abstraction....................................................................... LM 6n ob0ect has an inter"ace..........................................................................L? 6n ob0ect %rovides services........................................................................LG The hidden i#%le#entation...................................................................... LG 5eusing the i#%le#entation..................................................................... L2

Inheritance= reusing the inter"ace................................................................................... ?@


Is'a vs. is'like'a relationshi%s...................................................................................................?H

Interchangeable ob0ects with %oly#or%his#..................................................................................... ?G


6bstract base classes and inter"aces.......................................................................................... HM

)b0ect landsca%es and li"eti#es................................................................HK


+ollections and iterators............................................................................................................ H? The singly rooted hierarchy....................................................................................................... HG +ollection libraries and su%%ort "or easy collection use ...........................................................HI The housekee%ing dile##a= who should clean u%O .................................................................H2

E&ce%tion handling= dealing with errors..................................................3M Multithreading............................................................................................ 3K Persistence................................................................................................... 3? Java and the Internet................................................................................. 3?
:hat is the :ebO....................................................................................................................... 3H +lient'side %rogra##ing..........................................................................................................3G Server'side %rogra##ing.......................................................................................................... GH 6 se%arate arena= a%%lications..................................................................................................GH

6nalysis and design.....................................................................................G3


Phase @= Make a %lan................................................................................................................. G2 Phase M= :hat are we #akingO.................................................................................................I@ Phase K= (ow will we build itO..................................................................................................I? Phase L= Build the core.............................................................................................................. I2 Phase ?= Iterate the use cases.................................................................................................... I2 Phase H= Evolution..................................................................................................................... 2@ Plans %ay o""............................................................................................................................... 2K

E&tre#e %rogra##ing............................................................................... 2L
:rite tests "irst.......................................................................................................................... 2L Pair %rogra##ing.....................................................................................................................2H

:hy Java succeeds..................................................................................... 23


Syste#s are easier to e&%ress and understand........................................................................................................2G Ma&i#al leverage with libraries................................................................................................ 2G Error handling........................................................................................................................... 2G Progra##ing in the large.........................................................................................................2I

Strategies "or transition............................................................................. 2I


8uidelines.................................................................................................................................. 22

Manage#ent obstacles............................................................................................................ M@@

Java vs. +<<O............................................................................................. M@K Su##ary.................................................................................................... M@?

K= Everything is an )b0ect......................................................................... M@3


/ou #ani%ulate ob0ects with re"erences ......................................................................................... M@3 /ou #ust create all the ob0ects............................................................................................. M@I
:here storage lives.................................................................................................................. M@I S%ecial case= %ri#itive ty%es.................................................................................................... MM@ 6rrays in Java........................................................................................................................... MMK

/ou never need to destroy an ob0ect........................................................................................ MML


Sco%ing..................................................................................................................................... MML Sco%e o" ob0ects........................................................................................................................ MM?

+reating new data ty%es= class..........................................................................................MMH


Eields and #ethods..................................................................................................................MM3

Methods, argu#ents, and return values....................................................................................... MMI


The argu#ent list.....................................................................................................................MM2

Building a Java %rogra#...........................................................................MKM


Ca#e visibility.......................................................................................................................... MKM 4sing other co#%onents.......................................................................................................... MKK The static keyword................................................................................................................... MKL

/our "irst Java %rogra#........................................................................... MKH


+o#%iling and running............................................................................................................ MKG

+o##ents and e#bedded docu#entation........................................... MKI


+o##ent docu#entation........................................................................................................ MK2 Synta&....................................................................................................................................... ML@ E#bedded (TMD..................................................................................................................... MLM Psee= re"erring to other classes............................................................................................... MLK +lass docu#entation tags........................................................................................................ MLK Variable docu#entation tags................................................................................................... MLL Method docu#entation tags.................................................................................................... MLL 7ocu#entation e&a#%le.......................................................................................................... MLH

+oding style................................................................................................ ML3 Su##ary.................................................................................................... ML3 E&ercises..................................................................................................... MLG

L= +ontrolling Progra# Elow.............................................. ML2


4sing Java o%erators................................................................................ ML2
Precedence............................................................................................................................... M?@ 6ssign#ent.............................................................................................................................. M?@ Mathe#atical o%erators........................................................................................................... M?L 6uto incre#ent and decre#ent............................................................................................... M?3 5elational o%erators................................................................................................................M?I Dogical o%erators...................................................................................................................... MH@ Bitwise o%erators...................................................................................................................... MHL Shi"t o%erators.......................................................................................................................... MH? Ternary i"'else o%erator...........................................................................................................MH2 The co##a o%erator................................................................................................................ M3@ String o%erator <.....................................................................................................................M3@ +o##on %it"alls when using o%erators................................................................................... M3M +asting o%erators.....................................................................................................................M3M Java has no !si1eo"$ ................................................................................................................. M3H Precedence revisited................................................................................................................M33 6 co#%endiu# o" o%erators.................................................................................................... M33

E&ecution control...................................................................................... MGI


true and "alse............................................................................................................................ MGI i"'else........................................................................................................................................ MGI Iteration .................................................................................................................................. MI@ do'while.................................................................................................................................... MIM "or.............................................................................................................................................. MIM break and continue.................................................................................................................. MIL switch........................................................................................................................................ M2M

Su##ary.................................................................................................... M23 E&ercises..................................................................................................... M23

?= Initiali1ation N +leanu%........................................................................... M2I


8uaranteed initiali1ation with the constructor................................................................................. M2I Method overloading..................................................................................K@M
7istinguishing overloaded #ethods....................................................................................... K@L

)verloading with %ri#itives...................................................................................................K@? )verloading on return values.................................................................................................K@2 7e"ault constructors................................................................................................................ K@2 The this keyword......................................................................................................................KMM

+leanu%= "inali1ation and garbage collection...................................................................................... KMH


:hat is "inali1e* , "orO.............................................................................................................KM3 /ou #ust %er"or# cleanu%......................................................................................................KMG The death condition................................................................................................................. KKK (ow a garbage collector works...............................................................................................KKL

Me#ber initiali1ation............................................................................... KKG


S%eci"ying initiali1ation..........................................................................................................KK2 +onstructor initiali1ation........................................................................................................KLM

6rray initiali1ation.................................................................................... KL2


Multidi#ensional arrays......................................................................................................... K??

Su##ary.................................................................................................... K?I E&ercises.....................................................................................................K?2

H= (iding the I#%le#entation........................................... KHK


%ackage= the library unit.......................................................................... KHL
+reating uniAue %ackage na#es.............................................................................................KH3 6 custo# tool library............................................................................................................... K3@ 4sing i#%orts to change behavior..........................................................................................K3M Package caveat......................................................................................................................... K3?

Java access s%eci"iers............................................................................... K3?


!Eriendly$................................................................................................................................. K3H %ublic= inter"ace access............................................................................................................ K33 %rivate= you can t touch that................................................................................................... K3I %rotected= !sort o" "riendly$..................................................................................................... KG@

Inter"ace and i#%le#entation................................................................. KGM +lass access................................................................................................ KGL Su##ary.................................................................................................... KGG E&ercises..................................................................................................... KGI

3= 5eusing +lasses.............................................................. KIM


+o#%osition synta&.................................................................................. KIK Inheritance synta&.................................................................................... KI3
Initiali1ing the base class........................................................................................................ KI2

+o#bining co#%osition and inheritance.......................................................................................... K2M


8uaranteeing %ro%er cleanu%.................................................................................................K2L Ca#e hiding............................................................................................................................K2G

+hoosing co#%osition vs. inheritance........................................................................................... K2I %rotected.................................................................................................... L@@ Incre#ental develo%#ent........................................................................ L@M 4%casting................................................................................................... L@K
:hy !u%casting$O.................................................................................................................... L@L

The "inal keyword..................................................................................... L@H


Einal data................................................................................................................................. L@H Einal #ethods.......................................................................................................................... LM@ Einal classes.............................................................................................................................LMK Einal caution............................................................................................................................ LM?

Initiali1ation and class loading............................................................................................... LMH


Initiali1ation with inheritance................................................................................................. LM3

Su##ary..................................................................................................... LMG E&ercises..................................................................................................... LMI

G= Poly#or%his#................................................................ LKK
4%casting revisited................................................................................... LKL
Eorgetting the ob0ect ty%e.......................................................................................................LK?

The twist..................................................................................................... LK3


Method'call binding................................................................................................................ LKG Producing the right behavior..................................................................................................LKI E&tensibility............................................................................................................................. LLM

)verriding vs. overloading...................................................................... LLH Pit"all= !overriding$ %rivate #ethods..................................................... LLG 6bstract classes and #ethods.............................................................................................. LLI +onstructors and %oly#or%his#........................................................... L?K
)rder o" constructor calls........................................................................................................ L?L Inheritance and "inali1e* ,....................................................................................................... L?H Behavior o" %oly#or%hic #ethods inside constructors.................................................................................................................. L?2

7esigning with inheritance..................................................................... LHK

Pure inheritance vs. e&tension................................................................................................LH? 7owncasting and run'ti#e ty%e identi"ication.................................................................................................................... LH3

Su##ary.................................................................................................... LH2 E&ercises..................................................................................................... LH2

I= Inter"aces N Inner +lasses............................................. L3K


Inter"aces................................................................................................... L3L
!Multi%le inheritance$ in Java................................................................................................L3G E&tending an inter"ace with inheritance....................................................................................................................... LGM 8rou%ing constants.................................................................................................................LGK Initiali1ing "ields in inter"aces................................................................................................. LGH Cesting inter"aces.................................................................................................................... LG3

Inner classes.............................................................................................. LI@


Inner classes and u%casting....................................................................................................LIK Inner classes in #ethods and sco%es............................................................................................................ LI? 6nony#ous inner classes........................................................................................................ LIG The link to the outer class........................................................................................................ L2M static inner classes................................................................................................................... L2L 5e"erring to the outer class ob0ect..........................................................................................L23 5eaching outward "ro# a #ulti%ly'nested class....................................................................L2I Inheriting "ro# inner classes.................................................................................................. L22 +an inner classes be overriddenO...........................................................................................?@@ Inner class identi"iers.............................................................................................................. ?@K :hy inner classesO.................................................................................................................. ?@L Inner classes N control "ra#eworks.......................................................................................?@2

Su##ary.................................................................................................... ?MI E&ercises..................................................................................................... ?MI

2= (olding /our )b0ects....................................................................... ?KK


6rrays......................................................................................................... ?KK
6rrays are "irst'class ob0ects...................................................................................................?K? 5eturning an array.................................................................................................................. ?KI The 6rrays class....................................................................................................................... ?L@ Eilling an array........................................................................................................................ ??L +o%ying an array.....................................................................................................................???

+o#%aring arrays.................................................................................................................... ??3 6rray ele#ent co#%arisons....................................................................................................??G Sorting an array....................................................................................................................... ?H@ Searching a sorted array.......................................................................................................... ?HK 6rray su##ary........................................................................................................................ ?HH

Introduction to containers...................................................................... ?HH


Printing containers.................................................................................................................. ?HG Eilling containers..................................................................................................................... ?HI

+ontainer disadvantage= unknown ty%e............................................................................................ ?3H


So#eti#es it works anyway.................................................................................................... ?3I Making a ty%e'conscious 6rrayDist........................................................................................?G@

Iterators...................................................................................................... ?GK +ontainer ta&ono#y................................................................................. ?G3 +ollection "unctionality........................................................................... ?I@ Dist "unctionality.......................................................................................?I?
Making a stack "ro# a DinkedDist..........................................................................................?II Making a Aueue "ro# a DinkedDist......................................................................................... ?I2

Set "unctionality........................................................................................ ?2@


SortedSet.................................................................................................................................. ?2L

Ma% "unctionality..................................................................................... ?2?


SortedMa%............................................................................................................................... ?22 (ashing and hash codes.......................................................................................................... ?22 )verriding hash+ode* ,........................................................................................................... H@2

(olding re"erences.................................................................................... HML


The :eak(ashMa%.................................................................................................................. HM3

Iterators revisited...................................................................................... HMI +hoosing an i#%le#entation.................................................................. HM2


+hoosing between Dists........................................................................................................... HK@ +hoosing between Sets............................................................................................................ HK? +hoosing between Ma%s.......................................................................................................... HK3

Sorting and searching Dists..................................................................... HK2 4tilities........................................................................................................HLM


Making a +ollection or Ma% un#odi"iable.............................................................................HLK Synchroni1ing a +ollection or Ma%......................................................................................... HLL

4nsu%%orted o%erations.......................................................................... HLH Java M.@FM.M containers............................................................................. HLI


Vector N Enu#eration............................................................................................................HLI

(ashtable................................................................................................................................. H?@ Stack......................................................................................................................................... H?@ BitSet........................................................................................................................................ H?M

Su##ary.................................................................................................... H?L E&ercises.....................................................................................................H??

M@= Error (andling with E&ce%tions................................................................... HHM


Basic e&ce%tions........................................................................................ HHK
E&ce%tion argu#ents............................................................................................................... HH?

+atching an e&ce%tion.............................................................................. HHH


The try block............................................................................................................................. HHH E&ce%tion handlers.................................................................................................................. HH3

+reating your own e&ce%tions................................................................. HHG The e&ce%tion s%eci"ication..................................................................... H3K


+atching any e&ce%tion...........................................................................................................H3L 5ethrowing an e&ce%tion......................................................................................................... H33

Standard Java e&ce%tions........................................................................ HG@


The s%ecial case o" 5unti#eE&ce%tion....................................................................................HGM

Per"or#ing cleanu% with "inally..................................................................................................HGL


:hat s "inally "orO.................................................................................................................... HGH Pit"all= the lost e&ce%tion......................................................................................................... HGI

E&ce%tion restrictions.............................................................................. HG2 +onstructors.............................................................................................. HIL E&ce%tion #atching................................................................................. HII


E&ce%tion guidelines...............................................................................................................HI2

Su##ary.................................................................................................... H2@ E&ercises.................................................................................................... H2@

MM= The Java IF) Syste#......................................................................... H2?


The Eile class..............................................................................................H2H
6 directory lister......................................................................................................................H2H +hecking "or and creating directories....................................................................................3@@

In%ut and out%ut...................................................................................... 3@K


Ty%es o" In%utStrea#.............................................................................................................. 3@L Ty%es o" )ut%utStrea#........................................................................................................... 3@H

6dding attributes and use"ul inter"aces.................................................................................3@G


5eading "ro# an In%utStrea# with EilterIn%utStrea#........................................................................................................... 3@I :riting to an )ut%utStrea# with Eilter)ut%utStrea#......................................................................................................... 3M@

5eaders N :riters..................................................................................... 3MK


Sources and sinks o" data........................................................................................................3ML Modi"ying strea# behavior.....................................................................................................3M? 4nchanged +lasses..................................................................................................................3MH

)"" by itsel"= 5ando#6ccessEile.................................................................................... 3MH Ty%ical uses o" IF) strea#s..................................................................... 3MG
In%ut strea#s.......................................................................................................................... 3K@ )ut%ut strea#s........................................................................................................................ 3KK 6 bugO6 bugO........................................................................................................................... 3KH Pi%ed strea#s.......................................................................................................................... 3K3

Standard IF)............................................................................................. 3K3


5eading "ro# standard in%ut.................................................................................................. 3KG +hanging Syste#.out to a Print:riter...................................................................................3KI 5edirecting standard IF)........................................................................................................ 3KI

+o#%ression..............................................................................................3L@
Si#%le co#%ression with 8QIP............................................................................................... 3LM Multi"ile storage with Qi%........................................................................................................ 3LK Java 65chives *J65s,.............................................................................................................. 3LH

)b0ect seriali1ation................................................................................... 3LG


Einding the class...................................................................................................................... 3?K +ontrolling seriali1ation.......................................................................................................... 3?? 4sing %ersistence..................................................................................................................... 3HH

Tokeni1ing in%ut....................................................................................... 33?


Strea#Tokeni1er..................................................................................................................... 33? StringTokeni1er....................................................................................................................... 33I +hecking ca%itali1ation style...................................................................................................3GM

Su##ary.................................................................................................... 3IM E&ercises.................................................................................................... 3IK

MK= 5un'ti#e Ty%e Identi"ication....................................... 3IH


The need "or 5TTI.................................................................................... 3IH

The +lass ob0ect....................................................................................................................... 3II +hecking be"ore a cast.............................................................................................................32M

5TTI synta&................................................................................................ G@M 5e"lection= run'ti#e class in"or#ation...................................................................................... G@?


6 class #ethod e&tractor......................................................................................................... G@3

Su##ary..................................................................................................... GMM E&ercises..................................................................................................... GML

ML= +reating :indows N 6%%lets............................................................................. GM3


The basic a%%let......................................................................................... GM2
6%%let restrictions.................................................................................................................... GM2 6%%let advantages...................................................................................................................GK@ 6%%lication "ra#eworks........................................................................................................... GKM 5unning a%%lets inside a :eb browser..................................................................................GKL 4sing 6%%letviewer.................................................................................................................. GKH Testing a%%lets......................................................................................................................... GK3

5unning a%%lets "ro# the co##and line.............................................. GKG


6 dis%lay "ra#ework................................................................................................................ GK2 4sing the :indows E&%lorer..................................................................................................GLK

Making a button........................................................................................ GLL +a%turing an event.................................................................................... GLH Te&t areas................................................................................................... GLI +ontrolling layout..................................................................................... G?@
BorderDayout...........................................................................................................................G?M ElowDayout.............................................................................................................................. G?K 8ridDayout............................................................................................................................... G?L 8ridBagDayout......................................................................................................................... G?? 6bsolute %ositioning................................................................................................................ G?? Bo&Dayout................................................................................................................................ G?H The best a%%roachO.................................................................................................................. G?2

The Swing event #odel............................................................................ GH@


Event and listener ty%es........................................................................................................... GHM Tracking #ulti%le events......................................................................................................... GH2

6 catalog o" Swing co#%onents.............................................................. G3K


Buttons..................................................................................................................................... G3L Icons......................................................................................................................................... G33

Tool ti%s................................................................................................................................... G32 Te&t "ields................................................................................................................................. G32 Borders..................................................................................................................................... GGK JScrollPanes............................................................................................................................. GGL 6 #ini'editor............................................................................................................................ GGH +heck bo&es.............................................................................................................................. GGG 5adio buttons........................................................................................................................... GG2 +o#bo bo&es *dro%'down lists,.............................................................................................. GI@ Dist bo&es................................................................................................................................. GIK Tabbed %anes........................................................................................................................... GI? Message bo&es.........................................................................................................................GIH Menus...................................................................................................................................... GII Po%'u% #enus.......................................................................................................................... G2H 7rawing.................................................................................................................................... G2G 7ialog Bo&es............................................................................................................................ I@M Eile dialogs..............................................................................................................................I@3 (TMD on Swing co#%onents................................................................................................. I@I Sliders and %rogress bars........................................................................................................IM@ Trees......................................................................................................................................... IMM Tables....................................................................................................................................... IM? Selecting Dook N Eeel............................................................................................................... IMG The cli%board........................................................................................................................... IM2

Packaging an a%%let into a J65 "ile....................................................... IKL Progra##ing techniAues........................................................................ IK?


Binding events dyna#ically.................................................................................................... IK? Se%arating business logic "ro# 4I logic............................................................................................................................ IK3 6 canonical "or#..................................................................................................................... IL@

Visual %rogra##ing and Beans...................................................................................................IL@


:hat is a BeanO....................................................................................................................... ILK E&tracting BeanIn"o with the Intros%ector............................................................................................................... ILH 6 #ore so%histicated Bean...................................................................................................... I?K Packaging a Bean..................................................................................................................... I?G More co#%le& Bean su%%ort................................................................................................... I?2 More to Beans.......................................................................................................................... IH@

Su##ary....................................................................................................IH@

E&ercises..................................................................................................... IHM

M?= Multi%le Threads.......................................................... IH3


5es%onsive user inter"aces...................................................................... IHG
Inheriting "ro# Thread........................................................................................................... I3@ Threading "or a res%onsive inter"ace......................................................................................I3K +o#bining the thread with the #ain class.................................................................................................................. I3H Making #any threads.............................................................................................................I3I 7ae#on threads......................................................................................................................IGK

Sharing li#ited resources........................................................................ IG?


I#%ro%erly accessing resources..............................................................................................IG? (ow Java shares resources..................................................................................................... II@ JavaBeans revisited................................................................................................................. II3

Blocking ..................................................................................................... I2M


Beco#ing blocked...................................................................................................................I2K 7eadlock.................................................................................................................................. 2@H

Priorities..................................................................................................... 2M@
5eading and setting %riorities................................................................................................. 2M@ Thread grou%s.......................................................................................................................... 2MH

5unnable revisited.................................................................................... 2KH


Too #any threads.................................................................................................................... 2KI

Su##ary.................................................................................................... 2LK E&ercises.....................................................................................................2L?

MH= 7istributed +o#%uting................................................. 2LG


Cetwork %rogra##ing............................................................................ 2LI
Identi"ying a #achine.............................................................................................................2L2 Sockets..................................................................................................................................... 2?L Serving #ulti%le clients...........................................................................................................2HM 7atagra#s................................................................................................................................ 2HG 4sing 45Ds "ro# within an a%%let.........................................................................................2HI More to networking.................................................................................................................23M

Java 7atabase +onnectivity *J7B+,.......................................................23M


8etting the e&a#%le to work...................................................................................................23H 6 84I version o" the looku% %rogra#....................................................................................2G@ :hy the J7B+ 6PI see#s so co#%le&....................................................................................................................2GL 6 #ore so%histicated e&a#%le................................................................................................2G?

Servlets....................................................................................................... 2IL
The basic servlet...................................................................................................................... 2I? Servlets and #ultithreading...................................................................................................2I2 (andling sessions with servlets.............................................................................................. 22@ 5unning the servlet e&a#%les................................................................................................. 22H

Java Server Pages..................................................................................... 223


I#%licit ob0ects........................................................................................................................ 22I JSP directives .......................................................................................................................... 222 JSP scri%ting ele#ents.......................................................................................................... M@@@ E&tracting "ields and values..................................................................................................M@@L JSP %age attributes and sco%e..............................................................................................M@@? Mani%ulating sessions in JSP...............................................................................................M@@H +reating and #odi"ying cookies...........................................................................................M@@I JSP su##ary......................................................................................................................... M@@2

5MI *5e#ote Method Invocation,.......................................................M@M@


5e#ote inter"aces..................................................................................................................M@M@ I#%le#enting the re#ote inter"ace.......................................................................................M@MM +reating stubs and skeletons.................................................................................................M@MH 4sing the re#ote ob0ect......................................................................................................... M@M3

+)5B6...................................................................................................... M@MG
+)5B6 "unda#entals............................................................................................................ M@MI 6n e&a#%le............................................................................................................................ M@K@ Java 6%%lets and +)5B6...................................................................................................... M@K3 +)5B6 vs. 5MI.....................................................................................................................M@KG

Enter%rise JavaBeans............................................................................. M@KG


JavaBeans vs. EJBs...............................................................................................................M@K2 The EJB s%eci"ication............................................................................................................ M@K2 EJB co#%onents.................................................................................................................... M@L@ The %ieces o" an EJB co#%onent..........................................................................................M@LK EJB o%eration........................................................................................................................ M@LL Ty%es o" EJBs......................................................................................................................... M@L? 7evelo%ing an EJB................................................................................................................M@L3 EJB su##ary......................................................................................................................... M@?M

Jini= distributed services........................................................................M@?K


Jini in conte&t........................................................................................................................ M@?K :hat is JiniO.......................................................................................................................... M@?L (ow Jini works...................................................................................................................... M@?? The discovery %rocess............................................................................................................ M@??

The 0oin %rocess..................................................................................................................... M@?H The looku% %rocess................................................................................................................ M@?3 Se%aration o" inter"ace and i#%le#entation........................................................................M@?G 6bstracting distributed syste#s...........................................................................................M@?I

Su##ary.................................................................................................. M@?2 E&ercises...................................................................................................M@?2

6= Passing N 5eturning )b0ects....................................... M@HL


Passing re"erences around..................................................................... M@H?
6liasing..................................................................................................................................M@H?

Making local co%ies................................................................................. M@HG


Pass by value.......................................................................................................................... M@HI +loning ob0ects......................................................................................................................M@H2 6dding cloneability to a class................................................................................................ M@3@ Success"ul cloning.................................................................................................................. M@3L The e""ect o" )b0ect.clone* ,................................................................................................... M@3H +loning a co#%osed ob0ect.................................................................................................... M@3I 6 dee% co%y with 6rrayDist...................................................................................................M@G@ 7ee% co%y via seriali1ation.................................................................................................... M@GK 6dding cloneability "urther down a hierarchy.......................................................................................................M@GH :hy this strange designO....................................................................................................... M@G3

+ontrolling cloneability.......................................................................... M@GG


The co%y constructor............................................................................................................. M@IL

5ead'only classes....................................................................................M@II
+reating read'only classes..................................................................................................... M@2@ The drawback to i##utability..............................................................................................M@2M I##utable Strings................................................................................................................. M@2? The String and StringBu""er classes...............................................................................................................M@2G Strings are s%ecial..................................................................................................................MM@K

Su##ary.................................................................................................. MM@K E&ercises................................................................................................... MM@?

B= The Java Cative Inter"ace *JCI,................................... MM@3


+alling a native #ethod.......................................................................... MM@G
The header "ile generator= 0avah............................................................................................ MM@I Ca#e #angling and "unction signatures..............................................................................MM@2 I#%le#enting your 7DD......................................................................................................... MMM@

6ccessing JCI "unctions= the JCIEnv argu#ent.............................................................................. MMMM


6ccessing Java Strings............................................................................................................ MMMK

Passing and using Java ob0ects.............................................................. MMML JCI and Java e&ce%tions......................................................................... MMM3 JCI and threading.................................................................................... MMMG 4sing a %ree&isting code base.................................................................MMMG 6dditional in"or#ation........................................................................... MMMI

+= Java Progra##ing 8uidelines...................................... MMM2


7esign........................................................................................................ MMM2 Bruce Eckel s (ands')n Java Se#inar Multi#edia +7 It s like co#ing to the se#inar. 6vailable at www.BruceEckel.co#........................................................MMK3 I#%le#entation....................................................................................... MMKI

7= 5esources..................................................................... MML3
So"tware.................................................................................................... MML3 Books......................................................................................................... MML3
6nalysis N design................................................................................................................... MMLI Python..................................................................................................................................... MM?M My own list o" books .............................................................................................................. MM?M

Inde&................................................................................. MM?L

reface
RSTIJLTP5EE6+ETI@UI suggested to #y brother Todd, who is #aking the lea% "ro# hardware into %rogra##ing, that the ne&t big revolution will be in genetic engineering.
:e ll have #icrobes designed to #ake "ood, "uel, and %lastic; they ll clean u% %ollution and in general allow us to #aster the #ani%ulation o" the %hysical world "or a "raction o" what it costs now. I clai#ed that it would #ake the co#%uter revolution look s#all in co#%arison. RFSURF STIJLTP5EE6+ETIMU Then I reali1ed I was #aking a #istake co##on to science "iction writers= getting lost in the technology *which is o" course easy to do in science "iction,. 6n e&%erienced writer knows that the story is never about the things; it s about the %eo%le. 8enetics will have a very large i#%act on our lives, but I # not so sure it will dwar" the co#%uter revolution *which enables the genetic revolution,9or at least the in"or#ation revolution. In"or#ation is about talking to each other= yes, cars and shoes and es%ecially genetic cures are i#%ortant, but in the end those are 0ust tra%%ings. :hat truly #atters is how we relate to the world. 6nd so #uch o" that is about co##unication.RFSURFSTIJLTP5EE6+ETIKU This book is a case in %oint. 6 #a0ority o" "olks thought I was very bold or a little cra1y to %ut the entire thing u% on the :eb. !:hy would anyone buy itO$ they asked. I" I had been o" a #ore conservative nature I wouldn t have done it, but I really didn t want to write another co#%uter book in the sa#e old way. I didn t know what would ha%%en but it turned out to be the s#artest thing I ve ever done with a book.RFSURF STIJLTP5EE6+ETILU Eor one thing, %eo%le started sending in corrections. This has been an a#a1ing %rocess, because "olks have looked into every nook and cranny and caught both technical and gra##atical errors, and I ve been able to eli#inate bugs o" all sorts that I know would have otherwise sli%%ed through. Peo%le have been si#%ly terri"ic about this, very o"ten saying

!Cow, I don t #ean this in a critical way-$ and then giving #e a collection o" errors I # sure I never would have "ound. I "eel like this has been a kind o" grou% %rocess and it has really #ade the book into so#ething s%ecial.RFSURFSTIJLTP5EE6+ETI?U But then I started hearing !)>, "ine, it s nice you ve %ut u% an electronic version, but I want a %rinted and bound co%y "ro# a real %ublisher.$ I tried very hard to #ake it easy "or everyone to %rint it out in a nice looking "or#at but that didn t ste# the de#and "or the %ublished book. Most %eo%le don t want to read the entire book on screen, and hauling around a shea" o" %a%ers, no #atter how nicely %rinted, didn t a%%eal to the# either. *Plus, I think it s not so chea% in ter#s o" laser %rinter toner., It see#s that the co#%uter revolution won t %ut %ublishers out o" business, a"ter all. (owever, one student suggested this #ay beco#e a #odel "or "uture %ublishing= books will be %ublished on the :eb "irst, and only i" su""icient interest warrants it will the book be %ut on %a%er. +urrently, the great #a0ority o" all books are "inancial "ailures, and %erha%s this new a%%roach could #ake the %ublishing industry #ore %ro"itable.RFSURFSTIJLTP5EE6+ETIHU This book beca#e an enlightening e&%erience "or #e in another way. I originally a%%roached Java as !0ust another %rogra##ing language,$ which in #any senses it is. But as ti#e %assed and I studied it #ore dee%ly, I began to see that the "unda#ental intention o" this language is di""erent "ro# all the other languages I have seen.RFSURF STIJLTP5EE6+ETI3U Progra##ing is about #anaging co#%le&ity= the co#%le&ity o" the %roble# you want to solve, laid u%on the co#%le&ity o" the #achine in which it is solved. Because o" this co#%le&ity, #ost o" our %rogra##ing %ro0ects "ail. 6nd yet, o" all the %rogra##ing languages o" which I a# aware, none o" the# have gone all'out and decided that their #ain design goal would be to conAuer the co#%le&ity o" develo%ing and #aintaining %rogra#s @. )" course, #any language design decisions were #ade with co#%le&ity in #ind, but at so#e %oint there were always so#e other issues that were considered essential to be added into the #i&. Inevitably, those other issues are what cause %rogra##ers to eventually !hit the
@ I take this back on the Knd edition= I believe that the Python language co#es closest to

doing e&actly that. See www.Python.org.

Thinking in Java

,,,'0ruceEckel'com

wall$ with that language. Eor e&a#%le, +<< had to be backwards' co#%atible with + *to allow easy #igration "or + %rogra##ers,, as well as e""icient. Those are both very use"ul goals and account "or #uch o" the success o" +<<, but they also e&%ose e&tra co#%le&ity that %revents so#e %ro0ects "ro# being "inished *certainly, you can bla#e %rogra##ers and #anage#ent, but i" a language can hel% by catching your #istakes, why shouldn t itO,. 6s another e&a#%le, Visual Basic *VB, was tied to B6SI+, which wasn t really designed to be an e&tensible language, so all the e&tensions %iled u%on VB have %roduced so#e truly horrible and un#aintainable synta&. Perl is backwards'co#%atible with 6wk, Sed, 8re%, and other 4ni& tools it was #eant to re%lace, and as a result is o"ten accused o" %roducing !write'only code$ *that is, a"ter a "ew #onths you can t read it,. )n the other hand, +<<, VB, Perl, and other languages like S#alltalk had so#e o" their design e""orts "ocused on the issue o" co#%le&ity and as a result are re#arkably success"ul in solving certain ty%es o" %roble#s.RFSURFSTIJLTP5EE6+ETIGU :hat has i#%ressed #e #ost as I have co#e to understand Java is what see#s like an un"linching goal o" reducing co#%le&ity $or the rogrammer. 6s i" to say !we don t care about anything e&ce%t reducing the ti#e and di""iculty o" %roducing robust code.$ In the early days, this goal has resulted in code that doesn t run very "ast *although there have been #any %ro#ises #ade about how Auickly Java will so#eday run, but it has indeed %roduced a#a1ing reductions in develo%#ent ti#e; hal" or less o" the ti#e that it takes to create an eAuivalent +<< %rogra#. This result alone can save incredible a#ounts o" ti#e and #oney, but Java doesn t sto% there. It goes on to wra% all the co#%le& tasks that have beco#e i#%ortant, such as #ultithreading and network %rogra##ing, in language "eatures or libraries that can at ti#es #ake those tasks trivial. 6nd "inally, it tackles so#e really big co#%le&ity %roble#s= cross' %lat"or# %rogra#s, dyna#ic code changes, and even security, each o" which can "it on your co#%le&ity s%ectru# anywhere "ro# !i#%edi#ent$ to !show'sto%%er.$ So des%ite the %er"or#ance %roble#s we ve seen, the %ro#ise o" Java is tre#endous= it can #ake us signi"icantly #ore %roductive %rogra##ers.RFSURFSTIJLTP5EE6+ETIIU )ne o" the %laces I see the greatest i#%act "or this is on the :eb. Cetwork %rogra##ing has always been hard, and Java #akes it easy *and the Java language designers are working on #aking it even easier,. Cetwork

%rogra##ing is how we talk to each other #ore e""ectively and chea%er than we ever have with tele%hones *e#ail alone has revolutioni1ed #any businesses,. 6s we talk to each other #ore, a#a1ing things begin to ha%%en, %ossibly #ore a#a1ing even than the %ro#ise o" genetic engineering.RFSURFSTIJLTP5EE6+ETI2U In all ways9creating the %rogra#s, working in tea#s to create the %rogra#s, building user inter"aces so the %rogra#s can co##unicate with the user, running the %rogra#s on di""erent ty%es o" #achines, and easily writing %rogra#s that co##unicate across the Internet9Java increases the co##unication bandwidth bet,een eo le. I think that %erha%s the results o" the co##unication revolution will not be seen "ro# the e""ects o" #oving large Auantities o" bits around; we shall see the true revolution because we will all be able to talk to each other #ore easily= one'on'one, but also in grou%s and, as a %lanet. IVve heard it suggested that the ne&t revolution is the "or#ation o" a kind o" global #ind that results "ro# enough %eo%le and enough interconnectedness. Java #ay or #ay not be the tool that "o#ents that revolution, but at least the %ossibility has #ade #e "eel like IV# doing so#ething #eaning"ul by atte#%ting to teach the language.RFSURFSTIJLTP5EE6+ETIM@U

reface to the !nd edition


Peo%le have #ade #any, #any wonder"ul co##ents about the "irst edition o" this book, which has naturally been very %leasant "or #e. (owever, every now and then so#eone will have co#%laints, and "or so#e reason one co#%laint that co#es u% %eriodically is !the book is too big.$ In #y #ind it is "aint da#nation indeed i" !too #any %ages$ is your only co#%laint. *)ne is re#inded o" the E#%eror o" 6ustria s co#%laint about Mo1art s work= !Too #any notes.$ Cot that I a# in any way trying to co#%are #ysel" to Mo1art., In addition, I can only assu#e that such a co#%laint co#es "ro# so#eone who is yet to be acAuainted with the vastness o" the Java language itsel", and has not seen the rest o" the books on the sub0ect9"or e&a#%le, #y "avorite re"erence is +ay (orst#ann N 8ary +ornell s Core Java *Prentice'(all,, which grew so big it had to be

Thinking in Java

,,,'0ruceEckel'com

broken into two volu#es. 7es%ite this, one o" the things I have atte#%ted to do in this edition is tri# out the %ortions that have beco#e obsolete, or at least nonessential. I "eel co#"ortable doing this because the original #aterial re#ains on the :eb site and the +7 5)M that acco#%anies this book, in the "or# o" the "reely'downloadable "irst edition o" the book *at ,,,'0ruceEckel'com,. I" you want the old stu"", it s still there, and this is a wonder"ul relie" "or an author. Eor e&a#%le, you #ay notice that the original last cha%ter, !Pro0ects,$ is no longer here; two o" the %ro0ects have been integrated into other cha%ters, and the rest were no longer a%%ro%riate. 6lso, the !7esign Pattens$ cha%ter beca#e too big and has been #oved into a book o" its own *also downloadable at the :eb site,. So, by all rights the book should be thinner.RFSURF STIJLTP5EE6+ETIMMU But alas, it is not to be.RFSURFSTIJLTP5EE6+ETIMKU The biggest issue is the continuing develo%#ent o" the Java language itsel", and in %articular the e&%anding 6PIs that %ro#ise to %rovide standard inter"aces "or 0ust about everything you d like to do *and I won t be sur%rised to see the !JToaster$ 6PI eventually a%%ear,. +overing all these 6PIs is obviously beyond the sco%e o" this book and is a task relegated to other authors, but so#e issues cannot be ignored. The biggest o" these include server'side Java *%ri#arily Servlets N Java Server %ages, or JSPs,, which is truly an e&cellent solution to the :orld :ide :eb %roble#, wherein we ve discovered that the various :eb browser %lat"or#s are 0ust not consistent enough to su%%ort client'side %rogra##ing. In addition, there is the whole %roble# o" easily creating a%%lications to interact with databases, transactions, security, and the like, which is involved with Enter%rise Java Beans *EJBs,. These to%ics are wra%%ed into the cha%ter "or#erly called !Cetwork Progra##ing$ and now called !7istributed +o#%uting,$ a sub0ect that is beco#ing essential to everyone. /ou ll also "ind this cha%ter has been e&%anded to include an overview o" Jini *%ronounced !genie,$ and it isn t an acrony#, 0ust a na#e,, which is a cutting'edge technology that allows us to change the way we think about interconnected a%%lications. 6nd o" course the book has been changed to use the Swing 84I library throughout. 6gain, i" you want the old Java M.@FM.M stu"" you can get it "ro# the "reely' downloadable book at ,,,'0ruceEckel'com *it is also included on this

edition s new +7 5)M, bound into the book; #ore on that a little later,. RFSURFSTIJLTP5EE6+ETIMLU 6side "ro# additional s#all language "eatures added in Java K and corrections #ade throughout the book, the other #a0or change is in the collections cha%ter *2,, which now "ocuses on the Java K collections used throughout the book. I ve also i#%roved that cha%ter to #ore dee%ly go into so#e o" the i#%ortant issues o" collections, in %articular how a hash "unction works *so that you can know how to %ro%erly create one,. There have been other #ove#ents and changes, including a rewrite o" +ha%ter M, and re#oval o" so#e a%%endices and other #aterial that I consider no longer necessary "or the %rinted book, but those are the bulk o" the#. In general, I ve tried to go over everything, re#ove "ro# the K nd edition what is no longer necessary *but which still e&ists in the electronic "irst edition,, include changes, and i#%rove everything I could. 6s the language continues to change9albeit not Auite at the sa#e breakneck %ace as be"ore9there will no doubt be "urther editions o" this book.RF SURFSTIJLTP5EE6+ETIM?U Eor those o" you who still can t stand the si1e o" the book, I do a%ologi1e. Believe it or not, I have worked hard to kee% it s#all. 7es%ite the bulk, I "eel like there #ay be enough alternatives to satis"y you. Eor one thing, the book is available electronically *"ro# the :eb site, and also on the +7 5)M that acco#%anies this book,, so i" you carry your la%to% you can carry the book on that with no e&tra weight. I" you re really into sli##ing down, there are actually Pal# Pilot versions o" the book "loating around. *)ne %erson told #e he would read the book in bed on his Pal# with the backlighting on to kee% "ro# annoying his wi"e. I can only ho%e that it hel%s send hi# to slu#berland., I" you need it on %a%er, I know o" %eo%le who %rint a cha%ter at a ti#e and carry it in their brie"case to read on the train.RFSURFSTIJLTP5EE6+ETIMHU

"ava !
6t this writing, the release o" Sun s Java %evelo ment 6it *J7>, M.L is i##inent, and the %ro%osed changes "or J7> M.? have been %ublici1ed. 6lthough these version nu#bers are still in the !ones,$ the standard way to re"er to any version o" the language that is J7> M.K or greater is to call it !Java K.$ This indicates the very signi"icant changes between !old

Thinking in Java

,,,'0ruceEckel'com

Java$9which had #any warts that I co#%lained about in the "irst edition o" this book9and this #ore #odern and i#%roved version o" the language, which has "ar "ewer warts and #any additions and nice designs. RFSURFSTIJLTP5EE6+ETIM3U This book is written "or Java K. I have the great lu&ury o" getting rid o" all the old stu"" and writing to only the new, i#%roved language because the old in"or#ation still e&ists in the electronic M st edition on the :eb and on the +7 5)M *which is where you can go i" you re stuck using a %re'Java'K version o" the language,. 6lso, because anyone can "reely download the J7> "ro# 0ava.sun.co#, it #eans that by writing to Java K I # not i#%osing a "inancial hardshi% on so#eone by "orcing the# to u%grade.RF SURFSTIJLTP5EE6+ETIMGU There is a bit o" a catch, however. J7> M.L has so#e i#%rove#ents that I d really like to use, but the version o" Java that is currently being released "or Dinu& is J7> M.K.K. Dinu& *see www.Dinu&.org, is a very i#%ortant develo%#ent in con0unction with Java, because it is "ast beco#ing the #ost i#%ortant server %lat"or# out there9"ast, reliable, robust, secure, well'#aintained, and "ree, a true revolution in the history o" co#%uting *I don t think we ve ever seen all o" those "eatures in any tool be"ore,. 6nd Java has "ound a very i#%ortant niche in server'side %rogra##ing in the "or# o" Servlets, a technology that is a huge i#%rove#ent over the traditional +8I %rogra##ing *this is covered in the !7istributed Progra##ing$ cha%ter,.RFSURFSTIJLTP5EE6+ETIMIU So although I would like to only use the very newest "eatures, it s critical that everything co#%iles under Dinu&, and so when you un%ack the source code and co#%ile it under that )S *with the latest J7>, you ll discover that everything will co#%ile. (owever, you will "ind that I ve %ut notes about "eatures in J7> M.L here and there.RFSURF STIJLTP5EE6+ETIM2U

#he CD $OM
6nother bonus with this edition is the +7 5)M that is %ackaged in the back o" the book. I ve resisted %utting +7 5)Ms in the back o" #y books in the %ast because I "elt the e&tra charge "or a "ew >bytes o" source code

on this enor#ous +7 was not 0usti"ied, %re"erring instead to allow %eo%le to download such things "ro# #y :eb site. (owever, you ll soon see that this +7 5)M is di""erent.RFSURFSTIJLTP5EE6+ETIK@U The +7 does contain the source code "ro# the book, but it also contains the book in its entirety, in several electronic "or#ats. My "avorite o" these is the (TMD "or#at, because it is "ast and "ully inde&ed9you 0ust click on an entry in the inde& or table o" contents and you re i##ediately at that %ortion o" the book.RFSURFSTIJLTP5EE6+ETIKMU The bulk o" the L@@< Megabytes o" the +7, however, is a "ull #ulti#edia course called Thinking in C! 9oundations $or C++ & Java' I originally co##issioned +huck 6llison to create this se#inar'on'+7 5)M as a stand'alone %roduct, but decided to include it with the second editions o" both Thinking in C++ and Thinking in Java because o" the consistent e&%erience o" having %eo%le co#e to se#inars without an adeAuate background in +. The thinking a%%arently goes !I # a s#art %rogra##er and I don t ,ant to learn +, but rather +<< or Java, so I ll 0ust ski% + and go directly to +<<FJava.$ 6"ter arriving at the se#inar, it slowly dawns on "olks that the %rereAuisite o" understanding + synta& is there "or a very good reason. By including the +7 5)M with the book, we can ensure that everyone attends a se#inar with adeAuate %re%aration.RFSURF STIJLTP5EE6+ETIKKU The +7 also allows the book to a%%eal to a wider audience. Even though +ha%ter L *+ontrolling %rogra# "low, does cover the "unda#entals o" the %arts o" Java that co#e "ro# +, the +7 is a gentler introduction, and assu#es even less about the student s %rogra##ing background than does the book. It is #y ho%e that by including the +7 #ore %eo%le will be able to be brought into the "old o" Java %rogra##ing. RFSU

Thinking in Java

,,,'0ruceEckel'com

Introduction
RFSTIJLTICT5)TI@UDike any hu#an language, Java %rovides a way to e&%ress conce%ts. I" success"ul, this #ediu# o" e&%ression will be signi"icantly easier and #ore "le&ible than the alternatives as %roble#s grow larger and #ore co#%le&.
/ou can t look at Java as 0ust a collection o" "eatures9so#e o" the "eatures #ake no sense in isolation. /ou can use the su# o" the %arts only i" you are thinking about design, not si#%ly coding. 6nd to understand Java in this way, you #ust understand the %roble#s with it and with %rogra##ing in general. This book discusses %rogra##ing %roble#s, why they are %roble#s, and the a%%roach Java has taken to solve the#. Thus, the set o" "eatures I e&%lain in each cha%ter are based on the way I see a %articular ty%e o" %roble# being solved with the language. In this way I ho%e to #ove you, a little at a ti#e, to the %oint where the Java #indset beco#es your native tongue.RFSURFSTIJLTICT5)TIKLU Throughout, I ll be taking the attitude that you want to build a #odel in your head that allows you to develo% a dee% understanding o" the language; i" you encounter a %u11le you ll be able to "eed it to your #odel and deduce the answer.RFSURFSTIJLTICT5)TIK?U

rere%uisites
This book assu#es that you have so#e %rogra##ing "a#iliarity= you understand that a %rogra# is a collection o" state#ents, the idea o" a subroutineF"unctionF#acro, control state#ents such as !i"$ and loo%ing constructs such as !while,$ etc. (owever, you #ight have learned this in #any %laces, such as %rogra##ing with a #acro language or working with a tool like Perl. 6s long as you ve %rogra##ed to the %oint where you "eel co#"ortable with the basic ideas o" %rogra##ing, you ll be able to work through this book. )" course, the book will be easier "or the + %rogra##ers and #ore so "or the +<< %rogra##ers, but don t count

yoursel" out i" you re not e&%erienced with those languages *but co#e willing to work hard; also, the #ulti#edia +7 that acco#%anies this book will bring you u% to s%eed on the basic + synta& necessary to learn Java,. I ll be introducing the conce%ts o" ob0ect'oriented %rogra##ing *))P, and Java s basic control #echanis#s, so you ll be e&%osed to those, and the "irst e&ercises will involve the basic control'"low state#ents.RFSURF STIJLTICT5)TIKHU 6lthough re"erences will o"ten be #ade to + and +<< language "eatures, these are not intended to be insider co##ents, but instead to hel% all %rogra##ers %ut Java in %ers%ective with those languages, "ro# which, a"ter all, Java is descended. I will atte#%t to #ake these re"erences si#%le and to e&%lain anything that I think a non' +F+<< %rogra##er would not be "a#iliar with.RFSURFSTIJLTICT5)TIK3U

&earning "ava
6t about the sa#e ti#e that #y "irst book <sing C++ *)sborneFMc8raw' (ill, M2I2, ca#e out, I began teaching that language. Teaching %rogra##ing languages has beco#e #y %ro"ession; I ve seen nodding heads, blank "aces, and %u11led e&%ressions in audiences all over the world since M2I2. 6s I began giving in'house training with s#aller grou%s o" %eo%le, I discovered so#ething during the e&ercises. Even those %eo%le who were s#iling and nodding were con"used about #any issues. I "ound out, by chairing the +<< track at the So"tware 7evelo%#ent +on"erence "or a nu#ber o" years *and later the Java track,, that I and other s%eakers tended to give the ty%ical audience too #any to%ics too "ast. So eventually, through both variety in the audience level and the way that I %resented the #aterial, I would end u% losing so#e %ortion o" the audience. Maybe it s asking too #uch, but because I a# one o" those %eo%le resistant to traditional lecturing *and "or #ost %eo%le, I believe, such resistance results "ro# boredo#,, I wanted to try to kee% everyone u% to s%eed.RFSURFSTIJLTICT5)TIKGU Eor a ti#e, I was creating a nu#ber o" di""erent %resentations in "airly short order. Thus, I ended u% learning by e&%eri#ent and iteration *a techniAue that also works well in Java %rogra# design,. Eventually I develo%ed a course using everything I had learned "ro# #y teaching

1=

Thinking in Java

,,,'0ruceEckel'com

e&%erience9one that I would be ha%%y giving "or a long ti#e. It tackles the learning %roble# in discrete, easy'to'digest ste%s, and in a hands'on se#inar *the ideal learning situation, there are e&ercises "ollowing each o" the short lessons. I now give this course in %ublic Java se#inars, which you can "ind out about at ,,,'0ruceEckel'com. *The introductory se#inar is also available as a +7 5)M. In"or#ation is available at the sa#e :eb site.,RFSURFSTIJLTICT5)TIKIU The "eedback that I get "ro# each se#inar hel%s #e change and re"ocus the #aterial until I think it works well as a teaching #ediu#. But this book isn t 0ust se#inar notes9I tried to %ack as #uch in"or#ation as I could within these %ages, and structured it to draw you through onto the ne&t sub0ect. More than anything, the book is designed to serve the solitary reader who is struggling with a new %rogra##ing language.RF SURFSTIJLTICT5)TIK2U

'oals
Dike #y %revious book Thinking in C++, this book has co#e to be structured around the %rocess o" teaching the language. In %articular, #y #otivation is to create so#ething that %rovides #e with a way to teach the language in #y own se#inars. :hen I think o" a cha%ter in the book, I think in ter#s o" what #akes a good lesson during a se#inar. My goal is to get bite'si1ed %ieces that can be taught in a reasonable a#ount o" ti#e, "ollowed by e&ercises that are "easible to acco#%lish in a classroo# situation.RFSURFSTIJLTICT5)TIL@U My goals in this book are to=RFSURFSTIJLTICT5)TILMU

()

Present the #aterial one si#%le ste% at a ti#e so that you can easily digest each conce%t be"ore #oving on. RFSURF STIJLTICT5)TILKU 4se e&a#%les that are as si#%le and short as %ossible. This so#eti#es %revents #e "ro# tackling !real world$ %roble#s, but I ve "ound that beginners are usually ha%%ier when they can understand every detail o" an e&a#%le rather than being i#%ressed by the sco%e o" the %roble# it solves. 6lso, there s a severe li#it to the a#ount o" code that can be absorbed in a classroo# situation.

!)

11

Eor this I will no doubt receive criticis# "or using !toy e&a#%les,$ but I # willing to acce%t that in "avor o" %roducing so#ething %edagogically use"ul. RFSURFSTIJLTICT5)TILLU

*)

+are"ully seAuence the %resentation o" "eatures so that you aren t seeing so#ething that you haven t been e&%osed to. )" course, this isn t always %ossible; in those situations, a brie" introductory descri%tion is given. RFSURFSTIJLTICT5)TIL?U 8ive you what I think is i#%ortant "or you to understand about the language, rather than everything I know. I believe there is an in"or#ation i#%ortance hierarchy, and that there are so#e "acts that 2H %ercent o" %rogra##ers will never need to know and that 0ust con"use %eo%le and adds to their %erce%tion o" the co#%le&ity o" the language. To take an e&a#%le "ro# +, i" you #e#ori1e the o%erator %recedence table *I never did,, you can write clever code. But i" you need to think about it, it will also con"use the readerF #aintainer o" that code. So "orget about %recedence, and use %arentheses when things aren t clear. RFSURF STIJLTICT5)TILHU >ee% each section "ocused enough so that the lecture ti#e9and the ti#e between e&ercise %eriods9is s#all. Cot only does this kee% the audience s #inds #ore active and involved during a hands'on se#inar, but it gives the reader a greater sense o" acco#%lish#ent. RFSURFSTIJLTICT5)TIL3U Provide you with a solid "oundation so that you can understand the issues well enough to #ove on to #ore di""icult coursework and books. RFSURFSTIJLTICT5)TILGU

+)

,)

-)

Online documentation
The Java language and libraries "ro# Sun Microsyste#s *a "ree download, co#e with docu#entation in electronic "or#, readable using a :eb browser, and virtually every third %arty i#%le#entation o" Java has this or an eAuivalent docu#entation syste#. 6l#ost all the books %ublished on Java have du%licated this docu#entation. So you either already have it or you can download it, and unless necessary, this book

12

Thinking in Java

,,,'0ruceEckel'com

will not re%eat that docu#entation because it s usually #uch "aster i" you "ind the class descri%tions with your :eb browser than i" you look the# u% in a book *and the on'line docu#entation is %robably #ore u%'to' date,. This book will %rovide e&tra descri%tions o" the classes only when it s necessary to su%%le#ent the docu#entation so you can understand a %articular e&a#%le.RFSURFSTIJLTICT5)TILIU

Cha.ters
This book was designed with one thing in #ind= the way %eo%le learn the Java language. Se#inar audience "eedback hel%ed #e understand the di""icult %arts that needed illu#ination. In the areas where I got a#bitious and included too #any "eatures all at once, I ca#e to know9 through the %rocess o" %resenting the #aterial9that i" you include a lot o" new "eatures, you need to e&%lain the# all, and this easily co#%ounds the student s con"usion. 6s a result, I ve taken a great deal o" trouble to introduce the "eatures as "ew at a ti#e as %ossible.RFSURF STIJLTICT5)TIL2U The goal, then, is "or each cha%ter to teach a single "eature, or a s#all grou% o" associated "eatures, without relying on additional "eatures. That way you can digest each %iece in the conte&t o" your current knowledge be"ore #oving on.RFSURFSTIJLTICT5)TI?@U (ere is a brie" descri%tion o" the cha%ters contained in the book, which corres%ond to lectures and e&ercise %eriods in #y hands'on se#inars.RF SURFSTIJLTICT5)TI?MU

+ha%ter M=

Introduction to Objects
This cha%ter is an overview o" what ob0ect'oriented %rogra##ing is all about, including the answer to the basic Auestion !:hat s an ob0ectO$, inter"ace vs. i#%le#entation, abstraction and enca%sulation, #essages and "unctions, inheritance and co#%osition, and the all'i#%ortant %oly#or%his#. /ou ll also get an overview o" issues o" ob0ect creation such as constructors, where the ob0ects live, where to %ut the# once they re created, and the #agical garbage collector that cleans u% the ob0ects that are no longer needed.

13

)ther issues will be introduced, including error handling with e&ce%tions, #ultithreading "or res%onsive user inter"aces, and networking and the Internet. /ou ll learn what #akes Java s%ecial, why it s been so success"ul, and about ob0ect'oriented analysis and design.

+ha%ter K=

ver!thing is an Object
This cha%ter #oves you to the %oint where you can write your "irst Java %rogra#, so it #ust give an overview o" the essentials, including the conce%t o" a re$erence to an ob0ect; how to create an ob0ect; an introduction to %ri#itive ty%es and arrays; sco%ing and the way ob0ects are destroyed by the garbage collector; how everything in Java is a new data ty%e *class, and how to create your own classes; "unctions, argu#ents, and return values; na#e visibility and using co#%onents "ro# other libraries; the static keyword; and co##ents and e#bedded docu#entation.RFSURF STIJLTICT5)TI?KU

+ha%ter L=

Controlling "rogra# $low


This cha%ter begins with all o" the o%erators that co#e to Java "ro# + and +<<. In addition, you ll discover co##on o%erator %it"alls, casting, %ro#otion, and %recedence. This is "ollowed by the basic control'"low and selection o%erations that you get with virtually any %rogra##ing language= choice with i"'else; loo%ing with "or and while; Auitting a loo% with break and continue as well as Java s labeled break and labeled continue *which account "or the !#issing goto$ in Java,; and selection using switch. 6lthough #uch o" this #aterial has co##on threads with + and +<< code, there are so#e di""erences. In addition, all the e&a#%les will be "ull Java e&a#%les so you ll get #ore co#"ortable with what Java looks like. RFSURFSTIJLTICT5)TI?LU

+ha%ter ?=

Initiali%ation & Cleanu'


This cha%ter begins by introducing the constructor, which guarantees %ro%er initiali1ation. The de"inition o" the constructor leads into the conce%t o" "unction overloading *since you #ight want several constructors,. This is "ollowed

14

Thinking in Java

,,,'0ruceEckel'com

by a discussion o" the %rocess o" cleanu%, which is not always as si#%le as it see#s. Cor#ally, you 0ust dro% an ob0ect when you re done with it and the garbage collector eventually co#es along and releases the #e#ory. This %ortion e&%lores the garbage collector and so#e o" its idiosyncrasies. The cha%ter concludes with a closer look at how things are initiali1ed= auto#atic #e#ber initiali1ation, s%eci"ying #e#ber initiali1ation, the order o" initiali1ation, static initiali1ation and array initiali1ation. RFSURF STIJLTICT5)TI??U

+ha%ter H=

(iding the I#'le#entation


This cha%ter covers the way that code is %ackaged together, and why so#e %arts o" a library are e&%osed while other %arts are hidden. It begins by looking at the package and import keywords, which %er"or# "ile'level %ackaging and allow you to build libraries o" classes. It then e&a#ines sub0ect o" directory %aths and "ile na#es. The re#ainder o" the cha%ter looks at the p*blic, private, and protecte' keywords, the conce%t o" !"riendly$ access, and what the di""erent levels o" access control #ean when used in various conte&ts. RFSURF STIJLTICT5)TI?HU

+ha%ter 3=

Reusing Classes
The conce%t o" inheritance is standard in virtually all ))P languages. It s a way to take an e&isting class and add to its "unctionality *as well as change it, the sub0ect o" +ha%ter G,. Inheritance is o"ten a way to reuse code by leaving the !base class$ the sa#e, and 0ust %atching things here and there to %roduce what you want. (owever, inheritance isn t the only way to #ake new classes "ro# e&isting ones. /ou can also e#bed an ob0ect inside your new class with com osition. In this cha%ter you ll learn about these two ways to reuse code in Java, and how to a%%ly the#. RFSURFSTIJLTICT5)TI?3U

+ha%ter G=

"ol!#or'his#
)n your own, you #ight take nine #onths to discover and understand %oly#or%his#, a cornerstone o" ))P. Through s#all, si#%le e&a#%les you ll see how to create a "a#ily o"

15

ty%es with inheritance and #ani%ulate ob0ects in that "a#ily through their co##on base class. Java s %oly#or%his# allows you to treat all ob0ects in this "a#ily generically, which #eans the bulk o" your code doesn t rely on s%eci"ic ty%e in"or#ation. This #akes your %rogra#s e&tensible, so building %rogra#s and code #aintenance is easier and chea%er.RFSURFSTIJLTICT5)TI?GU

+ha%ter I=

Interfaces & Inner Classes


Java %rovides a third way to set u% a reuse relationshi%, through the inter$ace, which is a %ure abstraction o" the inter"ace o" an ob0ect. The interface is #ore than 0ust an abstract class taken to the e&tre#e, since it allows you to %er"or# a variation on +<< s !#ulti%le inheritance,$ by creating a class that can be u%cast to #ore than one base ty%e. RFSURFSTIJLTICT5)TI?IU 6t "irst, inner classes look like a si#%le code hiding #echanis#= you %lace classes inside other classes. /ou ll learn, however, that the inner class does #ore than that9it knows about and can co##unicate with the surrounding class9and that the kind o" code you can write with inner classes is #ore elegant and clear, although it is a new conce%t to #ost and takes so#e ti#e to beco#e co#"ortable with design using inner classes.RFSURFSTIJLTICT5)TI?2U

+ha%ter 2=

(olding !our Objects


It s a "airly si#%le %rogra# that has only a "i&ed Auantity o" ob0ects with known li"eti#es. In general, your %rogra#s will always be creating new ob0ects at a variety o" ti#es that will be known only while the %rogra# is running. In addition, you won t know until run'ti#e the Auantity or even the e&act ty%e o" the ob0ects you need. To solve the general %rogra##ing %roble#, you need to create any nu#ber o" ob0ects, anyti#e, anywhere. This cha%ter e&%lores in de%th the container library that Java K su%%lies to hold ob0ects while you re working with the#= the si#%le arrays and #ore so%histicated containers *data structures, such as Array+ist and Hash1ap.RFSURFSTIJLTICT5)TIH@U

17

Thinking in Java

,,,'0ruceEckel'com

+ha%ter M@=

rror (andling with xce'tions


The basic %hiloso%hy o" Java is that badly'"or#ed code will not be run. 6s #uch as %ossible, the co#%iler catches %roble#s, but so#eti#es the %roble#s9either %rogra##er error or a natural error condition that occurs as %art o" the nor#al e&ecution o" the %rogra#9can be detected and dealt with only at run'ti#e. Java has e*ce tion handling to deal with any %roble#s that arise while the %rogra# is running. This cha%ter e&a#ines how the keywords try, catch, thro(, thro(s, and finally work in Java; when you should throw e&ce%tions and what to do when you catch the#. In addition, you ll see Java s standard e&ce%tions, how to create your own, what ha%%ens with e&ce%tions in constructors, and how e&ce%tion handlers are located. RFSURFSTIJLTICT5)TIHMU

+ha%ter MM=

The Java I)O *!ste#


Theoretically, you can divide any %rogra# into three %arts= in%ut, %rocess, and out%ut. This i#%lies that IF) *in%utF out%ut, is an i#%ortant %art o" the eAuation. In this cha%ter you ll learn about the di""erent classes that Java %rovides "or reading and writing "iles, blocks o" #e#ory, and the console. The distinction between !old$ IF) and !new$ Java IF) will be shown. In addition, this cha%ter e&a#ines the %rocess o" taking an ob0ect, !strea#ing$ it *so that it can be %laced on disk or sent across a network, and reconstructing it, which is handled "or you with Java s ob>ect seriali?ation. 6lso, Java s co#%ression libraries, which are used in the Java 65chive "ile "or#at *J65,, are e&a#ined.RFSURFSTIJLTICT5)TIHKU

+ha%ter MK=

Run+Ti#e T!'e Identification


Java run'ti#e ty%e identi"ication *5TTI, lets you "ind the e&act ty%e o" an ob0ect when you have a re"erence to only the base ty%e. Cor#ally, you ll want to intentionally ignore the e&act ty%e o" an ob0ect and let Java s dyna#ic binding #echanis# *%oly#or%his#, i#%le#ent the correct behavior "or that ty%e. But occasionally it is very hel%"ul to know the e&act ty%e o" an ob0ect "or which you have only a base re"erence. )"ten this in"or#ation allows you to %er"or# a s%ecial'case o%eration #ore e""iciently. This cha%ter e&%lains

18

what 5TTI is "or, how to use it, and how to get rid o" it when it doesn t belong there. In addition, this cha%ter introduces the Java re$lection #echanis#.RFSURFSTIJLTICT5)TIHLU

+ha%ter ML=

Creating ,indows and -''lets


Java co#es with the !Swing$ 84I library, which is a set o" classes that handle windowing in a %ortable "ashion. These windowed %rogra#s can either be a%%lets or stand'alone a%%lications. This cha%ter is an introduction to Swing and the creation o" :orld :ide :eb a%%lets. The i#%ortant !JavaBeans$ technology is introduced. This is "unda#ental "or the creation o" 5a%id'6%%lication 7evelo%#ent *567, %rogra#'building tools.RFSURFSTIJLTICT5)TIH?U

+ha%ter M?.

/ulti'le Threads
Java %rovides a built'in "acility to su%%ort #ulti%le concurrent subtasks, called threads, running within a single %rogra#. *4nless you have #ulti%le %rocessors on your #achine, this is only the a earance o" #ulti%le subtasks., 6lthough these can be used anywhere, threads are #ost a%%arent when trying to create a res%onsive user inter"ace so, "or e&a#%le, a user isn t %revented "ro# %ressing a button or entering data while so#e %rocessing is going on. This cha%ter looks at the synta& and se#antics o" #ultithreading in Java. RFSURFSTIJLTICT5)TIHHU

+ha%ter MH=

Distributed Co#'uting
6ll the Java "eatures and libraries see# to really co#e together when you start writing %rogra#s to work across networks. This cha%ter e&%lores co##unication across networks and the Internet, and the classes that Java %rovides to #ake this easier. It introduces the very i#%ortant conce%ts o" Servlets and JSPs *"or server'side %rogra##ing,, along ,ith Java %ata0ase Connectivit) *J7B+,, and -emote Method Invocation *5MI,. Einally, there s an introduction to the new technologies o" JI+I, JavaS aces, and Enter rise Java0eans *EJBs,.RFSURFSTIJLTICT5)TIH3U

1:

Thinking in Java

,,,'0ruceEckel'com

6%%endi& 6=

"assing & Returning Objects


Since the only way you talk to ob0ects in Java is through re"erences, the conce%ts o" %assing an ob0ect into a "unction and returning an ob0ect "ro# a "unction have so#e interesting conseAuences. This a%%endi& e&%lains what you need to know to #anage ob0ects when you re #oving in and out o" "unctions, and also shows the )tring class, which uses a di""erent a%%roach to the %roble#.RFSURF STIJLTICT5)TIHGU

6%%endi& B=

The Java 0ative Interface 1J0I2


6 totally %ortable Java %rogra# has serious drawbacks= s%eed and the inability to access %lat"or#'s%eci"ic services. :hen you know the %lat"or# that you re running on, it s %ossible to dra#atically s%eed u% certain o%erations by #aking the# native methods, which are "unctions that are written in another %rogra##ing language *currently, only +F+<< is su%%orted,. This a%%endi& gives you enough o" an introduction to this "eature that you should be able to create si#%le e&a#%les that inter"ace with non'Java code.RFSURF STIJLTICT5)TIHIU

-''endix C. Java "rogra##ing 3uidelines


This a%%endi& contains suggestions to hel% guide you while %er"or#ing low'level %rogra# design and writing code.RF SURFSTIJLTICT5)TIH2U

-''endix D. Reco##ended Reading


6 list o" so#e o" the Java books I ve "ound %articularly use"ul. RFSURFSTIJLTICT5)TI3@U

/0ercises
I ve discovered that si#%le e&ercises are e&ce%tionally use"ul to co#%lete a student s understanding during a se#inar, so you ll "ind a set at the end o" each cha%ter.RFSURFSTIJLTICT5)TI3MU Most e&ercises are designed to be easy enough that they can be "inished in a reasonable a#ount o" ti#e in a classroo# situation while the instructor

1;

observes, #aking sure that all the students are absorbing the #aterial. So#e e&ercises are #ore advanced to %revent boredo# "or e&%erienced students. The #a0ority are designed to be solved in a short ti#e and test and %olish your knowledge. So#e are #ore challenging, but none %resent #a0or challenges. *Presu#ably, you ll "ind those on your own9or #ore likely they ll "ind you,.RFSURFSTIJLTICT5)TI3KU Solutions to selected e&ercises can be "ound in the electronic docu#ent

The Thinking in Java "nnotated Solution @uide, available "or a s#all "ee
"ro# www.BruceEckel.co#.RFSURFSTIJLTICT5)TI3LU

Multimedia CD $OM
There are two #ulti#edia +7s associated with this book. The "irst is bound into the book itsel"= Thinking in C, described at the end o" the %re"ace, which %re%ares you "or the book by bringing you u% to s%eed on the necessary + synta& you need to be able to understand Java.RFSURF STIJLTICT5)TI3?U 6 second Multi#edia +7 5)M is available, which is based on the contents o" the book. This +7 5)M is a se%arate %roduct and contains the entire contents o" the week'long !(ands')n Java$ training se#inar. This is #ore than MH hours o" lectures that I have recorded, synchroni1ed with hundreds o" slides o" in"or#ation. Because the se#inar is based on this book, it is an ideal acco#%ani#ent.RFSURFSTIJLTICT5)TI3HU The +7 5)M contains all the lectures *with the i#%ortant e&ce%tion o" %ersonali1ed attention., "ro# the "ive'day "ull'i##ersion training se#inars. :e believe that it sets a new standard "or Auality.RFSURF STIJLTICT5)TI33U The (ands')n Java +7 5)M is available only by ordering directly "ro# the :eb site ,,,'0ruceEckel'com.RFSURFSTIJLTICT5)TI3GU

1ource code
6ll the source code "or this book is available as co%yrighted "reeware, distributed as a single %ackage, by visiting the :eb site ,,,'0ruceEckel'

2=

Thinking in Java

,,,'0ruceEckel'com

com. To #ake sure that you get the #ost current version, this is the
o""icial site "or distribution o" the code and the electronic version o" the book. /ou can "ind #irrored versions o" the electronic book and the code on other sites *so#e o" these sites are "ound at ,,,'0ruceEckel'com,, but you should check the o""icial site to ensure that the #irrored version is actually the #ost recent edition. /ou #ay distribute the code in classroo# and other educational situations.RFSURFSTIJLTICT5)TI3IU The %ri#ary goal o" the co%yright is to ensure that the source o" the code is %ro%erly cited, and to %revent you "ro# re%ublishing the code in %rint #edia without %er#ission. *6s long as the source is cited, using e&a#%les "ro# the book in #ost #edia is generally not a %roble#.,RFSURF STIJLTICT5)TI32U In each source code "ile you will "ind a re"erence to the "ollowing co%yright notice=RFSURFSTIJLTICT5)TIG@U
//34 3Co"y5ight.t6t Co"yright 7 ''' Bruce Eckel %ource co!e file fro# the n! e!ition of the book 8Thinking in Java.8 0ll rights reserve! E9CEPT as allo:e! by the follo:ing state#ents3 ;ou can freely use this file for your o:n :ork -"ersonal or co##ercial., inclu!ing #o!ifications an! !istribution in e6ecutable for# only. Per#ission is grante! to use this file in classroo# situations, inclu!ing its use in "resentation #aterials, as long as the book 8Thinking in Java8 is cite! as the source. E6ce"t in classroo# situations, you cannot co"y an! !istribute this co!e< instea!, the sole !istribution "oint is htt"3//:::.BruceEckel.co# -an! official #irror sites. :here it is freely available. ;ou cannot re#ove this co"yright an! notice. ;ou cannot !istribute #o!ifie! versions of the source co!e in this "ackage. ;ou cannot use this file in "rinte! #e!ia :ithout the e6"ress "er#ission of the author. Bruce Eckel #akes no re"resentation about the suitability of this soft:are for any "ur"ose. $t is "rovi!e! 8as is8 :ithout e6"ress or i#"lie!

21

:arranty of any kin!, inclu!ing any i#"lie! :arranty of #erchantability, fitness for a "articular "ur"ose or non-infringe#ent. The entire risk as to the =uality an! "erfor#ance of the soft:are is :ith you. Bruce Eckel an! the "ublisher shall not be liable for any !a#ages suffere! by you or any thir! "arty as a result of using or !istributing soft:are. $n no event :ill Bruce Eckel or the "ublisher be liable for any lost revenue, "rofit, or !ata, or for !irect, in!irect, s"ecial, conse=uential, inci!ental, or "unitive !a#ages, ho:ever cause! an! regar!less of the theory of liability, arising out of the use of or inability to use soft:are, even if Bruce Eckel an! the "ublisher have been a!vise! of the "ossibility of such !a#ages. %houl! the soft:are "rove !efective, you assu#e the cost of all necessary servicing, re"air, or correction. $f you think you2ve foun! an error, "lease sub#it the correction using the for# you :ill fin! at :::.BruceEckel.co#. -Please use the sa#e for# for non-co!e errors foun! in the book..

///3>
/ou #ay use the code in your %ro0ects and in the classroo# *including your %resentation #aterials, as long as the co%yright notice that a%%ears in each source "ile is retained.RFSURFSTIJLTICT5)TIGMU

Coding standards
In the te&t o" this book, identi"iers *"unction, variable, and class na#es, are set in bol'. Most keywords are also set in bold, e&ce%t "or those keywords that are used so #uch that the bolding can beco#e tedious, such as !class.$RFSURFSTIJLTICT5)TIGKU I use a %articular coding style "or the e&a#%les in this book. This style "ollows the style that Sun itsel" uses in virtually all o" the code you will "ind at its site *see >ava'sun'com/docs/codeconv/inde*'html,, and see#s to be su%%orted by #ost Java develo%#ent environ#ents. I" you ve read #y other works, you ll also notice that Sun s coding style coincides with

22

Thinking in Java

,,,'0ruceEckel'com

#ine9this %leases #e, although I had nothing to do with it. The sub0ect o" "or#atting style is good "or hours o" hot debate, so I ll 0ust say I # not trying to dictate correct style via #y e&a#%les; I have #y own #otivation "or using the style that I do. Because Java is a "ree'"or# %rogra##ing language, you can continue to use whatever style you re co#"ortable with. RFSURFSTIJLTICT5)TIGLU The %rogra#s in this book are "iles that are included by the word %rocessor in the te&t, directly "ro# co#%iled "iles. Thus, the code "iles %rinted in the book should all work without co#%iler errors. The errors that should cause co#%ile'ti#e error #essages are co##ented out with the co##ent 55= so they can be easily discovered and tested using auto#atic #eans. Errors discovered and re%orted to the author will a%%ear "irst in the distributed source code and later in u%dates o" the book *which will also a%%ear on the :eb site ,,,'0ruceEckel'com,.RF SURFSTIJLTICT5)TIG?U

"ava versions
I generally rely on the Sun i#%le#entation o" Java as a re"erence when deter#ining whether behavior is correct.RFSURFSTIJLTICT5)TIGHU )ver ti#e, Sun has released three #a0or versions o" Java= M.@, M.M and K *which is called version K even though the releases o" the J7> "ro# Sun continue to use the nu#bering sche#e o" M.K, M.L, M.?, etc.,. Version K see#s to "inally bring Java into the %ri#e ti#e, in %articular where user inter"ace tools are concerned. This book "ocuses on and is tested with Java K, although I do so#eti#es #ake concessions to earlier "eatures o" Java K so that the code will co#%ile under Dinu& *via the Dinu& J7> that was available at this writing,.RFSURFSTIJLTICT5)TIG3U I" you need to learn about earlier releases o" the language that are not covered in this edition, the "irst edition o" the book is "reely downloadable at ,,,'0ruceEckel'com and is also contained on the +7 that is bound in with this book.RFSURFSTIJLTICT5)TIGGU )ne thing you ll notice is that, when I do need to #ention earlier versions o" the language, I don t use the sub'revision nu#bers. In this book I will re"er to Java M.@, Java M.M, and Java K only, to guard against ty%ogra%hical

23

errors %roduced by "urther sub'revisioning o" these %roducts.RFSURF STIJLTICT5)TIGIU

1eminars and mentoring


My co#%any %rovides "ive'day, hands'on, %ublic and in'house training se#inars based on the #aterial in this book. Selected #aterial "ro# each cha%ter re%resents a lesson, which is "ollowed by a #onitored e&ercise %eriod so each student receives %ersonal attention. The audio lectures and slides "or the introductory se#inar are also ca%tured on +7 5)M to %rovide at least so#e o" the e&%erience o" the se#inar without the travel and e&%ense. Eor #ore in"or#ation, go to ,,,'0ruceEckel'com.RFSURF STIJLTICT5)TIG2U My co#%any also %rovides consulting, #entoring and walkthrough services to hel% guide your %ro0ect through its develo%#ent cycle9 es%ecially your co#%any s "irst Java %ro0ect. RFSURF STIJLTICT5)TII@U

/rrors
Co #atter how #any tricks a writer uses to detect errors, so#e always cree% in and these o"ten lea% o"" the %age "or a "resh reader. RFSURF STIJLTICT5)TIIMU There is an error sub#ission "or# linked "ro# the beginning o" each cha%ter in the (TMD version o" this book *and on the +7 5)M bound into the back o" this book, and downloadable "ro# ,,,'0ruceEckel' com, and also on the :eb site itsel", on the %age "or this book. I" you discover anything you believe to be an error, %lease use this "or# to sub#it the error along with your suggested correction. I" necessary, include the original source "ile and note any suggested #odi"ications. /our hel% is a%%reciated.RFSURFSTIJLTICT5)TIIKU

24

Thinking in Java

,,,'0ruceEckel'com

2ote on the cover design


The cover o" Thinking in Java is ins%ired by the 6#erican 6rts N +ra"ts Move#ent, which began near the turn o" the century and reached its 1enith between M2@@ and M2K@. It began in England as a reaction to both the #achine %roduction o" the Industrial 5evolution and the highly orna#ental style o" the Victorian era. 6rts N +ra"ts e#%hasi1ed s%are design, the "or#s o" nature as seen in the art nouveau #ove#ent, hand' cra"ting, and the i#%ortance o" the individual cra"ts%erson, and yet it did not eschew the use o" #odern tools. There are #any echoes with the situation we have today= the turn o" the century, the evolution "ro# the raw beginnings o" the co#%uter revolution to so#ething #ore re"ined and #eaning"ul to individual %ersons, and the e#%hasis on so"tware cra"ts#anshi% rather than 0ust #anu"acturing code. RFSURF STIJLTICT5)TIILU I see Java in this sa#e way= as an atte#%t to elevate the %rogra##er away "ro# an o%erating'syste# #echanic and toward being a !so"tware cra"ts#an.$RFSURFSTIJLTICT5)TII?U Both the author and the bookFcover designer *who have been "riends since childhood, "ind ins%iration in this #ove#ent, and both own "urniture, la#%s, and other %ieces that are either original or ins%ired by this %eriod. RFSURFSTIJLTICT5)TIIHU The other the#e in this cover suggests a collection bo& that a naturalist #ight use to dis%lay the insect s%eci#ens that he or she has %reserved. These insects are ob0ects, which are %laced within the bo& ob0ects. The bo& ob0ects are the#selves %laced within the !cover ob0ect,$ which illustrates the "unda#ental conce%t o" aggregation in ob0ect'oriented %rogra##ing. )" course, a %rogra##er cannot hel% but #ake the association with !bugs,$ and here the bugs have been ca%tured and %resu#ably killed in a s%eci#en 0ar, and "inally con"ined within a s#all dis%lay bo&, as i" to i#%ly Java s ability to "ind, dis%lay, and subdue bugs *which is truly one o" its #ost %ower"ul attributes,.RFSURF STIJLTICT5)TII3U

25

Acknowledgements
Eirst, thanks to associates who have worked with #e to give se#inars, %rovide consulting, and develo% teaching %ro0ects= 6ndrea Provaglio, 7ave Bartlett *who also contributed signi"icantly to +ha%ter MH,, Bill Venners, and Darry ) Brien. I a%%reciate your %atience as I continue to try to develo% the best #odel "or inde%endent "olks like us to work together. Thanks to 5ol" 6ndrW >laedtke *Swit1erland,; Martin Vlcek, Martin Byer, Vlada N Pavel Dahoda, Martin the Bear, and (anka *Prague,; and Marco +antu *Italy, "or hosting #e on #y "irst sel"' organi1ed Euro%ean se#inar tour.RFSURFSTIJLTICT5)TIIGU Thanks to the 7oyle Street +ohousing +o##unity "or %utting u% with #e "or the two years that it took #e to write the "irst edition o" this book *and "or %utting u% with #e at all,. Thanks very #uch to >evin and Sonda 7onovan "or subletting their great %lace in gorgeous +rested Butte, +olorado "or the su##er while I worked on the "irst edition o" the book. 6lso thanks to the "riendly residents o" +rested Butte and the 5ocky Mountain Biological Daboratory who #ake #e "eel so welco#e.RFSURF STIJLTICT5)TIIIU Thanks to +laudette Moore at Moore Diterary 6gency "or her tre#endous %atience and %erseverance in getting #e e&actly what I wanted.RFSURF STIJLTICT5)TII2U My "irst two books were %ublished with Je"" Pe%%er as editor at )sborneF Mc8raw'(ill. Je"" a%%eared at the right %lace and the right ti#e at Prentice'(all and has cleared the %ath and #ade all the right things ha%%en to #ake this a very %leasant %ublishing e&%erience. Thanks, Je""9 it #eans a lot to #e.RFSURFSTIJLTICT5)TI2@U I # es%ecially indebted to 8en >iyooka and his co#%any 7igiga#i, who graciously %rovided #y :eb server "or the "irst several years o" #y %resence on the :eb. This was an invaluable learning aid.RFSURF STIJLTICT5)TI2MU

27

Thinking in Java

,,,'0ruceEckel'com

Thanks to +ay (orst#ann *co'author o" Core Java, Prentice'(all, K@@@ A, 7 6rcy S#ith *Sy#antec,, and Paul Ty#a *co'author o" Java Primer Plus, The :aite 8rou%, M223,, "or hel%ing #e clari"y conce%ts in the language.RFSURFSTIJLTICT5)TI2KU Thanks to %eo%le who have s%oken in #y Java track at the So"tware 7evelo%#ent +on"erence, and students in #y se#inars, who ask the Auestions I need to hear in order to #ake the #aterial #ore clear.RFSURF STIJLTICT5)TI2LU S%ecial thanks to Darry and Tina ) Brien, who hel%ed turn #y se#inar into the original .ands/On Java +7 5)M. */ou can "ind out #ore at ,,,'0ruceEckel'com.,RFSURFSTIJLTICT5)TI2?U Dots o" %eo%le sent in corrections and I a# indebted to the# all, but %articular thanks go to *"or the "irst edition,= >evin 5aulerson *"ound tons o" great bugs,, Bob 5esendes *si#%ly incredible,, John Pinto, Joe 7ante, Joe Shar% *all three were "abulous,, 7avid +o#bs *#any gra##ar and clari"ication corrections,, 7r. 5obert Ste%henson, John +ook, Eranklin +hen, Qev 8riner, 7avid >arr, Deander 6. Stroschein, Steve +lark, +harles 6. Dee, 6ustin Maher, 7ennis P. 5oth, 5oAue )liveira, 7ouglas 7unn, 7e0an 5istic, Ceil 8alarneau, 7avid B. Malkovsky, Steve :ilkinson, and a host o" others. Pro". Ir. Marc Meurrens %ut in a great deal o" e""ort to %ublici1e and #ake the electronic version o" the "irst edition o" the book available in Euro%e.RFSURFSTIJLTICT5)TI2HU There have been a s%ate o" s#art technical %eo%le in #y li"e who have beco#e "riends and have also been both in"luential and unusual in that they do yoga and %ractice other "or#s o" s%iritual enhance#ent, which I "ind Auite ins%irational and instructional. They are >raig Brocksch#idt, 8en >iyooka, and 6ndrea Provaglio, *who hel%s in the understanding o" Java and %rogra##ing in general in Italy, and now in the 4nited States as an associate o" the MindView tea#,.RFSURFSTIJLTICT5)TI23U It s not that #uch o" a sur%rise to #e that understanding 7el%hi hel%ed #e understand Java, since there are #any conce%ts and language design decisions in co##on. My 7el%hi "riends %rovided assistance by hel%ing #e gain insight into that #arvelous %rogra##ing environ#ent. They are Marco +antu *another Italian9%erha%s being stee%ed in Datin gives one a%titude "or %rogra##ing languagesO,, Ceil 5ubenking *who used to do

28

the yogaFvegetarianFQen thing until he discovered co#%uters,, and o" course Qack 4rlocker, a long'ti#e %al who# I ve traveled the world with. RFSURFSTIJLTICT5)TI2GU My "riend 5ichard (ale Shaw s insights and su%%ort have been very hel%"ul *and >i# s, too,. 5ichard and I s%ent #any #onths giving se#inars together and trying to work out the %er"ect learning e&%erience "or the attendees. Thanks also to >o6nn Vikoren, Eric Eaurot, Marco Pardi, and the rest o" the cast and crew at MEI. Thanks es%ecially to Tara 6rrowood, who re'ins%ired #e about the %ossibilities o" con"erences.RF SURFSTIJLTICT5)TI2IU The book design, cover design, and cover %hoto were created by #y "riend 7aniel :ill'(arris, noted author and designer * ,,,'Bill/.arris'com,, who used to %lay with rub'on letters in 0unior high school while he awaited the invention o" co#%uters and deskto% %ublishing, and co#%lained o" #e #u#bling over #y algebra %roble#s. (owever, I %roduced the ca#era'ready %ages #ysel", so the ty%esetting errors are #ine. Microso"t X :ord 2G "or :indows was used to write the book and to create ca#era'ready %ages in 6dobe 6crobat; the book was created directly "ro# the 6crobat P7E "iles. *6s a tribute to the electronic age, I ha%%ened to be overseas both ti#es the "inal version o" the book was %roduced9the "irst edition was sent "ro# +a%etown, South 6"rica and the second edition was %osted "ro# Prague,. The body ty%e"ace is @eorgia and the headlines are in Cerdana. The cover ty%e"ace is ITC -ennie Mackintosh'RFSURFSTIJLTICT5)TI22U Thanks to the vendors who created the co#%ilers= Borland, the Blackdown grou% *"or Dinu&,, and o" course, Sun.RFSURF STIJLTICT5)TIM@@U 6 s%ecial thanks to all #y teachers and all #y students *who are #y teachers as well,. The #ost "un writing teacher was 8abrielle 5ico *author o" Briting the +atural Ba), Putna#, M2IL,. I ll always treasure the terri"ic week at Esalen.RFSURFSTIJLTICT5)TIM@MU The su%%orting cast o" "riends includes, but is not li#ited to= 6ndrew Binstock, Steve Sino"sky, J7 (ildebrandt, To# >e""er, Brian McElhinney, Brinkley Barr, Bill 8ates at Midnight Engineering Maga?ine, Darry +onstantine and Ducy Dockwood, 8reg Perry, 7an Putter#an, +hristi

2:

Thinking in Java

,,,'0ruceEckel'com

:est%hal, 8ene :ang, 7ave Mayer, 7avid Intersi#one, 6ndrea 5osen"ield, +laire Sawyers, #ore Italians *Daura Eallai, +orrado, Ilsa, and +ristina 8iusto11i,, +hris and Daura Strand, the 6l#Auists, Brad Jerbic, Marilyn +vitanic, the Mabrys, the (a"lingers, the Pollocks, Peter Vinci, the 5obbins Ea#ilies, the Moelter Ea#ilies *and the McMillans,, Michael :ilk, 7ave Stoner, Daurie 6da#s, the +ranstons, Darry Eogg, Mike and >aren SeAueira, 8ary Ents#inger and 6llison Brody, >evin 7onovan and Sonda Eastlack, +hester and Shannon 6ndersen, Joe Dordi, 7ave and Brenda Bartlett, 7avid Dee, the 5entschlers, the Sudeks, 7ick, Patty, and Dee Eckel, Dynn and Todd, and their "a#ilies. 6nd o" course, Mo# and 7ad.RFSURFSTIJLTICT5)TIM@KU

Internet contributors
Thanks to those who hel%ed #e rewrite the e&a#%les to use the Swing library, and "or other assistance= Jon Shvarts, Tho#as >irsch, 5ahi# 6datia, 5a0esh Jain, 5avi Manthena, Banu 5a0a#ani, Jens Brandt, Citin Shivara#, Malcol# 7avis, and everyone who e&%ressed su%%ort. This really hel%ed #e 0u#%'start the %ro0ect.RFSU

2;

(: Introduction to Ob3ects
RFSTIJLT+(6PTE5MTI@UThe genesis o" the co#%uter revolution was in a #achine. The genesis o" our %rogra##ing languages thus tends to look like that #achine.
But co#%uters are not so #uch #achines as they are #ind a#%li"ication tools *!bicycles "or the #ind,$ as Steve Jobs is "ond o" saying, and a di""erent kind o" e&%ressive #ediu#. 6s a result, the tools are beginning to look less like #achines and #ore like %arts o" our #inds, and also like other "or#s o" e&%ression such as writing, %ainting, scul%ture, ani#ation, and "il##aking. )b0ect'oriented %rogra##ing *))P, is %art o" this #ove#ent toward using the co#%uter as an e&%ressive #ediu#.RFSURF STIJLT+(6PTE5MTIMU This cha%ter will introduce you to the basic conce%ts o" ))P, including an overview o" develo%#ent #ethods. This cha%ter, and this book, assu#e that you have had e&%erience in a %rocedural %rogra##ing language, although not necessarily +. I" you think you need #ore %re%aration in %rogra##ing and the synta& o" + be"ore tackling this book, you should work through the Thinking in C! 9oundations $or C++ and Java training +7 5)M, bound in with this book and also available at ,,,'0ruceEckel' com. RFSURFSTIJLT+(6PTE5MTIKU This cha%ter is background and su%%le#entary #aterial. Many %eo%le do not "eel co#"ortable wading into ob0ect'oriented %rogra##ing without understanding the big %icture "irst. Thus, there are #any conce%ts that are introduced here to give you a solid overview o" ))P. (owever, #any other %eo%le don t get the big %icture conce%ts until they ve seen so#e o" the #echanics "irst; these %eo%le #ay beco#e bogged down and lost without so#e code to get their hands on. I" you re %art o" this latter grou% and are eager to get to the s%eci"ics o" the language, "eel "ree to 0u#% %ast

3=

this cha%ter9ski%%ing it at this %oint will not %revent you "ro# writing %rogra#s or learning the language. (owever, you will want to co#e back here eventually to "ill in your knowledge so you can understand why ob0ects are i#%ortant and how to design with the#.RFSURF STIJLT+(6PTE5MTILU

#he .rogress of abstraction


6ll %rogra##ing languages %rovide abstractions. It can be argued that the co#%le&ity o" the %roble#s you re able to solve is directly related to the kind and Auality o" abstraction. By !kind$ I #ean, !:hat is it that you are abstractingO$ 6sse#bly language is a s#all abstraction o" the underlying #achine. Many so'called !i#%erative$ languages that "ollowed *such as Eortran, B6SI+, and +, were abstractions o" asse#bly language. These languages are big i#%rove#ents over asse#bly language, but their %ri#ary abstraction still reAuires you to think in ter#s o" the structure o" the co#%uter rather than the structure o" the %roble# you are trying to solve. The %rogra##er #ust establish the association between the #achine #odel *in the !solution s%ace,$ which is the %lace where you re #odeling that %roble#, such as a co#%uter, and the #odel o" the %roble# that is actually being solved *in the !%roble# s%ace,$ which is the %lace where the %roble# e&ists,. The e""ort reAuired to %er"or# this #a%%ing, and the "act that it is e&trinsic to the %rogra##ing language, %roduces %rogra#s that are di""icult to write and e&%ensive to #aintain, and as a side e""ect created the entire !%rogra##ing #ethods$ industry. RFSURFSTIJLT+(6PTE5MTI?U The alternative to #odeling the #achine is to #odel the %roble# you re trying to solve. Early languages such as DISP and 6PD chose %articular views o" the world *!6ll %roble#s are ulti#ately lists$ or !6ll %roble#s are algorith#ic,$ res%ectively,. P5)D)8 casts all %roble#s into chains o" decisions. Danguages have been created "or constraint'based %rogra##ing and "or %rogra##ing e&clusively by #ani%ulating gra%hical sy#bols. *The latter %roved to be too restrictive., Each o" these a%%roaches is a good solution to the %articular class o" %roble# they re

Cha ter 1! Introduction to Ob>ects

31

designed to solve, but when you ste% outside o" that do#ain they beco#e awkward. RFSURFSTIJLT+(6PTE5MTIHU The ob0ect'oriented a%%roach goes a ste% "urther by %roviding tools "or the %rogra##er to re%resent ele#ents in the %roble# s%ace. This re%resentation is general enough that the %rogra##er is not constrained to any %articular ty%e o" %roble#. :e re"er to the ele#ents in the %roble# s%ace and their re%resentations in the solution s%ace as !ob0ects.$ *)" course, you will also need other ob0ects that don t have %roble#'s%ace analogs., The idea is that the %rogra# is allowed to ada%t itsel" to the lingo o" the %roble# by adding new ty%es o" ob0ects, so when you read the code describing the solution, you re reading words that also e&%ress the %roble#. This is a #ore "le&ible and %ower"ul language abstraction than what we ve had be"ore. Thus, ))P allows you to describe the %roble# in ter#s o" the %roble#, rather than in ter#s o" the co#%uter where the solution will run. There s still a connection back to the co#%uter, though. Each ob0ect looks Auite a bit like a little co#%uter; it has a state, and it has o%erations that you can ask it to %er"or#. (owever, this doesn t see# like such a bad analogy to ob0ects in the real world9they all have characteristics and behaviors. RFSURFSTIJLT+(6PTE5MTI3U So#e language designers have decided that ob0ect'oriented %rogra##ing by itsel" is not adeAuate to easily solve all %rogra##ing %roble#s, and advocate the co#bination o" various a%%roaches into multi aradigm %rogra##ing languages. @RFSURFSTIJLT+(6PTE5MTIGU 6lan >ay su##ari1ed "ive basic characteristics o" S#alltalk, the "irst success"ul ob0ect'oriented language and one o" the languages u%on which Java is based. These characteristics re%resent a %ure a%%roach to ob0ect' oriented %rogra##ing=RFSURFSTIJLT+(6PTE5MTIIU

4)

Everything is an object. Think o" an ob0ect as a "ancy


variable; it stores data, but you can !#ake reAuests$ to that ob0ect, asking it to %er"or# o%erations on itsel". In theory, you can take any conce%tual co#%onent in the %roble# you re trying to solve *dogs, buildings, services, etc., and re%resent it as an ob0ect in your %rogra#. RFSURFSTIJLT+(6PTE5MTI2U

@ See Multi aradigm Programming in (eda by Ti#othy Budd *6ddison':esley M22H,.

32

5)

A rogram is a bunch o! objects telling each other "hat to do by sending messages. To #ake a reAuest o" an
ob0ect, you !send a #essage$ to that ob0ect. More concretely, you can think o" a #essage as a reAuest to call a "unction that belongs to a %articular ob0ect. RFSURFSTIJLT+(6PTE5MTIM@U

6)

Each object has its o"n memory made u o! other objects. Put another way, you create a new kind o" ob0ect by
#aking a %ackage containing e&isting ob0ects. Thus, you can build co#%le&ity in a %rogra# while hiding it behind the si#%licity o" ob0ects. RFSURFSTIJLT+(6PTE5MTIMMU

(7)

Every object has a ty e. 4sing the %arlance, each ob0ect is an instance o" a class, in which !class$ is synony#ous with !ty%e.$ The
#ost i#%ortant distinguishing characteristic o" a class is !:hat #essages can you send to itO$ RFSURFSTIJLT+(6PTE5MTIMKU

(()

All objects o! a articular ty e can receive the same messages. This is actually a loaded state#ent, as you will see
later. Because an ob0ect o" ty%e !circle$ is also an ob0ect o" ty%e !sha%e,$ a circle is guaranteed to acce%t sha%e #essages. This #eans you can write code that talks to sha%es and auto#atically handle anything that "its the descri%tion o" a sha%e. This substitutabilit) is one o" the #ost %ower"ul conce%ts in ))P. RF SURFSTIJLT+(6PTE5MTIMLU

Booch o""ers an even #ore succinct descri%tion o" an ob0ect= "n ob>ect has stateD behavior and identit) This #eans that an ob0ect can have internal data *which gives it state,, #ethods *to %roduce behavior,, and each ob0ect can be uniAuely distinguished "ro# every other ob0ect Y to %ut this in a concrete sense, each ob0ect has a uniAue address in #e#ory@

@ This is actually a bit restrictive, since ob0ects can conceivably e&ist in di""erent #achines and address s%aces, and they can also be stored on disk. In these cases, the identity o" the ob0ect #ust be deter#ined by so#ething other than #e#ory address.

Cha ter 1! Introduction to Ob>ects

33

An ob3ect has an interface


6ristotle was %robably the "irst to begin a care"ul study o" the conce%t o" t) eE he s%oke o" !the class o" "ishes and the class o" birds.$ The idea that all ob0ects, while being uniAue, are also %art o" a class o" ob0ects that have characteristics and behaviors in co##on was used directly in the "irst ob0ect'oriented language, Si#ula'3G, with its "unda#ental keyword class that introduces a new ty%e into a %rogra#.RFSURF STIJLT+(6PTE5MTIM?U Si#ula, as its na#e i#%lies, was created "or develo%ing si#ulations such as the classic !bank teller %roble#.$ In this, you have a bunch o" tellers, custo#ers, accounts, transactions, and units o" #oney9a lot o" !ob0ects.$ )b0ects that are identical e&ce%t "or their state during a %rogra# s e&ecution are grou%ed together into !classes o" ob0ects$ and that s where the keyword class ca#e "ro#. +reating abstract data ty%es *classes, is a "unda#ental conce%t in ob0ect'oriented %rogra##ing. 6bstract data ty%es work al#ost e&actly like built'in ty%es= /ou can create variables o" a ty%e *called ob>ects or instances in ob0ect'oriented %arlance, and #ani%ulate those variables *called sending messages or re#uestsE you send a #essage and the ob0ect "igures out what to do with it,. The #e#bers *ele#ents, o" each class share so#e co##onality= every account has a balance, every teller can acce%t a de%osit, etc. 6t the sa#e ti#e, each #e#ber has its own state, each account has a di""erent balance, each teller has a na#e. Thus, the tellers, custo#ers, accounts, transactions, etc., can each be re%resented with a uniAue entity in the co#%uter %rogra#. This entity is the ob0ect, and each ob0ect belongs to a %articular class that de"ines its characteristics and behaviors.RFSURF STIJLT+(6PTE5MTIMHU So, although what we really do in ob0ect'oriented %rogra##ing is create new data ty%es, virtually all ob0ect'oriented %rogra##ing languages use the !class$ keyword. :hen you see the word !ty%e$ think !class$ and vice versa @.RFSURFSTIJLT+(6PTE5MTIM3U
@ So#e %eo%le #ake a distinction, stating that ty%e deter#ines the inter"ace while class is a %articular i#%le#entation o" that inter"ace.

34

Since a class describes a set o" ob0ects that have identical characteristics *data ele#ents, and behaviors *"unctionality,, a class is really a data ty%e because a "loating %oint nu#ber, "or e&a#%le, also has a set o" characteristics and behaviors. The di""erence is that a %rogra##er de"ines a class to "it a %roble# rather than being "orced to use an e&isting data ty%e that was designed to re%resent a unit o" storage in a #achine. /ou e&tend the %rogra##ing language by adding new data ty%es s%eci"ic to your needs. The %rogra##ing syste# welco#es the new classes and gives the# all the care and ty%e'checking that it gives to built'in ty%es.RF SURFSTIJLT+(6PTE5MTIMGU The ob0ect'oriented a%%roach is not li#ited to building si#ulations. :hether or not you agree that any %rogra# is a si#ulation o" the syste# you re designing, the use o" ))P techniAues can easily reduce a large set o" %roble#s to a si#%le solution.RFSURFSTIJLT+(6PTE5MTIMIU )nce a class is established, you can #ake as #any ob0ects o" that class as you like, and then #ani%ulate those ob0ects as i" they are the ele#ents that e&ist in the %roble# you are trying to solve. Indeed, one o" the challenges o" ob0ect'oriented %rogra##ing is to create a one'to'one #a%%ing between the ele#ents in the %roble# s%ace and ob0ects in the solution s%ace.RFSURFSTIJLT+(6PTE5MTIM2U But how do you get an ob0ect to do use"ul work "or youO There #ust be a way to #ake a reAuest o" the ob0ect so that it will do so#ething, such as co#%lete a transaction, draw so#ething on the screen, or turn on a switch. 6nd each ob0ect can satis"y only certain reAuests. The reAuests you can #ake o" an ob0ect are de"ined by its inter$aceD and the ty%e is what deter#ines the inter"ace. 6 si#%le e&a#%le #ight be a re%resentation o" a light bulb= RFSURFSTIJLT+(6PTE5MTIK@U

#:.e 2ame Interface

#ight on89 off89 brighten89 dim89

Cha ter 1! Introduction to Ob>ects

35

Light lt ? ne: Light-.< lt.on-.<


The inter"ace establishes ,hat reAuests you can #ake "or a %articular ob0ect. (owever, there #ust be code so#ewhere to satis"y that reAuest. This, along with the hidden data, co#%rises the im lementation. Ero# a %rocedural %rogra##ing stand%oint, it s not that co#%licated. 6 ty%e has a "unction associated with each %ossible reAuest, and when you #ake a %articular reAuest to an ob0ect, that "unction is called. This %rocess is usually su##ari1ed by saying that you !send a #essage$ *#ake a reAuest, to an ob0ect, and the ob0ect "igures out what to do with that #essage *it e&ecutes code,.RFSURFSTIJLT+(6PTE5MTIKMU (ere, the na#e o" the ty%eFclass is +ight, the na#e o" this %articular +ight ob0ect is lt, and the reAuests that you can #ake o" a +ight ob0ect are to turn it on, turn it o"", #ake it brighter, or #ake it di##er. /ou create a +ight ob0ect by de"ining a !re"erence$ * lt, "or that ob0ect and calling ne( to reAuest a new ob0ect o" that ty%e. To send a #essage to the ob0ect, you state the na#e o" the ob0ect and connect it to the #essage reAuest with a %eriod *dot,. Ero# the stand%oint o" the user o" a %rede"ined class, that s %retty #uch all there is to %rogra##ing with ob0ects.RFSURFSTIJLT+(6PTE5MTIKKU The diagra# shown above "ollows the "or#at o" the <ni$ied Modeling (anguage *4MD,. Each class is re%resented by a bo&, with the ty%e na#e in the to% %ortion o" the bo&, any data #e#bers that you care to describe in the #iddle %ortion o" the bo&, and the member $unctions *the "unctions that belong to this ob0ect, which receive any #essages you send to that ob0ect, in the botto# %ortion o" the bo&. )"ten, only the na#e o" the class and the %ublic #e#ber "unctions are shown in 4MD design diagra#s, and so the #iddle %ortion is not shown. I" you re interested only in the class na#e, then the botto# %ortion doesn t need to be shown, either.RF SURFSTIJLT+(6PTE5MTIKLU

37

An ob3ect .rovides services #he hidden im.lementation


It is hel%"ul to break u% the %laying "ield into class creators *those who create new data ty%es, and client rogrammers@ *the class consu#ers who use the data ty%es in their a%%lications,. The goal o" the client %rogra##er is to collect a toolbo& "ull o" classes to use "or ra%id a%%lication develo%#ent. The goal o" the class creator is to build a class that e&%oses only what s necessary to the client %rogra##er and kee%s everything else hidden. :hyO Because i" it s hidden, the client %rogra##er can t use it, which #eans that the class creator can change the hidden %ortion at will without worrying about the i#%act to on anyone else. The hidden %ortion usually re%resents the tender insides o" an ob0ect that could easily be corru%ted by a careless or unin"or#ed client %rogra##er, so hiding the i#%le#entation reduces %rogra# bugs. The conce%t o" i#%le#entation hiding cannot be overe#%hasi1ed.RFSURF STIJLT+(6PTE5MTIK?U In any relationshi% it s i#%ortant to have boundaries that are res%ected by all %arties involved. :hen you create a library, you establish a relationshi% with the client %rogra##er, who is also a %rogra##er, but one who is %utting together an a%%lication by using your library, %ossibly to build a bigger library.RFSURFSTIJLT+(6PTE5MTIKHU I" all the #e#bers o" a class are available to everyone, then the client %rogra##er can do anything with that class and there s no way to en"orce rules. Even though you #ight really %re"er that the client %rogra##er not directly #ani%ulate so#e o" the #e#bers o" your class, without access
@ I # indebted to #y "riend Scott Meyers "or this ter#.

Cha ter 1! Introduction to Ob>ects

38

control there s no way to %revent it. Everything s naked to the world.RF SURFSTIJLT+(6PTE5MTIK3U So the "irst reason "or access control is to kee% client %rogra##ers hands o"" %ortions they shouldn t touch9%arts that are necessary "or the internal #achinations o" the data ty%e but not %art o" the inter"ace that users need in order to solve their %articular %roble#s. This is actually a service to users because they can easily see what s i#%ortant to the# and what they can ignore.RFSURFSTIJLT+(6PTE5MTIKGU The second reason "or access control is to allow the library designer to change the internal workings o" the class without worrying about how it will a""ect the client %rogra##er. Eor e&a#%le, you #ight i#%le#ent a %articular class in a si#%le "ashion to ease develo%#ent, and then later discover that you need to rewrite it in order to #ake it run "aster. I" the inter"ace and i#%le#entation are clearly se%arated and %rotected, you can acco#%lish this easily.RFSURFSTIJLT+(6PTE5MTIKIU Java uses three e&%licit keywords to set the boundaries in a class= p*blic, private, and protecte'. Their use and #eaning are Auite straight"orward. These access s eci$iers deter#ine who can use the de"initions that "ollow. p*blic #eans the "ollowing de"initions are available to everyone. The private keyword, on the other hand, #eans that no one can access those de"initions e&ce%t you, the creator o" the ty%e, inside #e#ber "unctions o" that ty%e. private is a brick wall between you and the client %rogra##er. I" so#eone tries to access a private #e#ber, they ll get a co#%ile'ti#e error. protecte' acts like private, with the e&ce%tion that an inheriting class has access to protecte' #e#bers, but not private #e#bers. Inheritance will be introduced shortly.RFSURFSTIJLT+(6PTE5MTIK2U Java also has a !de"ault$ access, which co#es into %lay i" you don t use one o" the a"ore#entioned s%eci"iers. This is so#eti#es called !"riendly$ access because classes can access the "riendly #e#bers o" other classes in the sa#e %ackage, but outside o" the %ackage those sa#e "riendly #e#bers a%%ear to be private.RFSURFSTIJLT+(6PTE5MTIL@U

3:

$eusing the im.lementation


)nce a class has been created and tested, it should *ideally, re%resent a use"ul unit o" code. It turns out that this reusability is not nearly so easy to achieve as #any would ho%e; it takes e&%erience and insight to %roduce a good design. But once you have such a design, it begs to be reused. +ode reuse is one o" the greatest advantages that ob0ect'oriented %rogra##ing languages %rovide.RFSURFSTIJLT+(6PTE5MTILMU The si#%lest way to reuse a class is to 0ust use an ob0ect o" that class directly, but you can also %lace an ob0ect o" that class inside a new class. :e call this !creating a #e#ber ob0ect.$ /our new class can be #ade u% o" any nu#ber and ty%e o" other ob0ects, in any co#bination that you need to achieve the "unctionality desired in your new class. Because you are co#%osing a new class "ro# e&isting classes, this conce%t is called com osition *or #ore generally, aggregation,. +o#%osition is o"ten re"erred to as a !has'a$ relationshi%, as in !a car has an engine.$RFSURF STIJLT+(6PTE5MTILKU

Car

/ngine

*The above 4MD diagra# indicates co#%osition with the "illed dia#ond, which states there is one car. I will ty%ically use a si#%ler "or#= 0ust a line, without the dia#ond, to indicate an association. @,RFSURF STIJLT+(6PTE5MTILLU +o#%osition co#es with a great deal o" "le&ibility. The #e#ber ob0ects o" your new class are usually %rivate, #aking the# inaccessible to the client %rogra##ers who are using the class. This allows you to change those #e#bers without disturbing e&isting client code. /ou can also change the #e#ber ob0ects at run'ti#e, to dyna#ically change the behavior o" your %rogra#. Inheritance, which is described ne&t, does not have this
@ This is usually enough detail "or #ost diagra#s, and you don t need to get s%eci"ic about whether you re using aggregation or co#%osition.

Cha ter 1! Introduction to Ob>ects

3;

"le&ibility since the co#%iler #ust %lace co#%ile'ti#e restrictions on classes created with inheritance.RFSURFSTIJLT+(6PTE5MTIL?U Because inheritance is so i#%ortant in ob0ect'oriented %rogra##ing it is o"ten highly e#%hasi1ed, and the new %rogra##er can get the idea that inheritance should be used everywhere. This can result in awkward and overly co#%licated designs. Instead, you should "irst look to co#%osition when creating new classes, since it is si#%ler and #ore "le&ible. I" you take this a%%roach, your designs will be cleaner. )nce you ve had so#e e&%erience, it will be reasonably obvious when you need inheritance.RF SURFSTIJLT+(6PTE5MTILHU

Inheritance: reusing the interface


By itsel", the idea o" an ob0ect is a convenient tool. It allows you to %ackage data and "unctionality together by conce t, so you can re%resent an a%%ro%riate %roble#'s%ace idea rather than being "orced to use the idio#s o" the underlying #achine. These conce%ts are e&%ressed as "unda#ental units in the %rogra##ing language by using the class keyword.RFSURFSTIJLT+(6PTE5MTIL3U It see#s a %ity, however, to go to all the trouble to create a class and then be "orced to create a brand new one that #ight have si#ilar "unctionality. It s nicer i" we can take the e&isting class, clone it, and then #ake additions and #odi"ications to the clone. This is e""ectively what you get with inheritance, with the e&ce%tion that i" the original class *called the base or su er or arent class, is changed, the #odi"ied !clone$ *called the derived or inherited or sub or child class, also re"lects those changes.RF SURFSTIJLT+(6PTE5MTILGU

4=

;ase

Derived

*The arrow in the above 4MD diagra# %oints "ro# the derived class to the base class. 6s you will see, there can be #ore than one derived class., RFSURFSTIJLT+(6PTE5MTILIU 6 ty%e does #ore than describe the constraints on a set o" ob0ects; it also has a relationshi% with other ty%es. Two ty%es can have characteristics and behaviors in co##on, but one ty%e #ay contain #ore characteristics than another and #ay also handle #ore #essages *or handle the# di""erently,. Inheritance e&%resses this si#ilarity between ty%es using the conce%t o" base ty%es and derived ty%es. 6 base ty%e contains all o" the characteristics and behaviors that are shared a#ong the ty%es derived "ro# it. /ou create a base ty%e to re%resent the core o" your ideas about so#e ob0ects in your syste#. Ero# the base ty%e, you derive other ty%es to e&%ress the di""erent ways that this core can be reali1ed.RFSURF STIJLT+(6PTE5MTIL2U Eor e&a#%le, a trash'recycling #achine sorts %ieces o" trash. The base ty%e is !trash,$ and each %iece o" trash has a weight, a value, and so on, and can be shredded, #elted, or deco#%osed. Ero# this, #ore s%eci"ic ty%es o" trash are derived that #ay have additional characteristics *a bottle has a color, or behaviors *an alu#inu# can #ay be crushed, a steel can is #agnetic,. In addition, so#e behaviors #ay be di""erent *the value o" %a%er de%ends on its ty%e and condition,. 4sing inheritance, you can build a ty%e hierarchy that e&%resses the %roble# you re trying to solve in ter#s o" its ty%es.RFSURFSTIJLT+(6PTE5MTI?@U 6 second e&a#%le is the classic !sha%e$ e&a#%le, %erha%s used in a co#%uter'aided design syste# or ga#e si#ulation. The base ty%e is !sha%e,$ and each sha%e has a si1e, a color, a %osition, and so on. Each sha%e can be drawn, erased, #oved, colored, etc. Ero# this, s%eci"ic ty%es

Cha ter 1! Introduction to Ob>ects

41

o" sha%es are derived *inherited,= circle, sAuare, triangle, and so on, each o" which #ay have additional characteristics and behaviors. +ertain sha%es can be "li%%ed, "or e&a#%le. So#e behaviors #ay be di""erent, such as when you want to calculate the area o" a sha%e. The ty%e hierarchy e#bodies both the si#ilarities and di""erences between the sha%es.RF SURFSTIJLT+(6PTE5MTI?MU

Sha e draw89 erase89 move89 getColor89 setColor89

$ircle

S%uare

&riangle

+asting the solution in the sa#e ter#s as the %roble# is tre#endously bene"icial because you don t need a lot o" inter#ediate #odels to get "ro# a descri%tion o" the %roble# to a descri%tion o" the solution. :ith ob0ects, the ty%e hierarchy is the %ri#ary #odel, so you go directly "ro# the descri%tion o" the syste# in the real world to the descri%tion o" the syste# in code. Indeed, one o" the di""iculties %eo%le have with ob0ect' oriented design is that it s too si#%le to get "ro# the beginning to the end. 6 #ind trained to look "or co#%le& solutions is o"ten stu#%ed by this si#%licity at "irst.RFSURFSTIJLT+(6PTE5MTI?KU :hen you inherit "ro# an e&isting ty%e, you create a new ty%e. This new ty%e contains not only all the #e#bers o" the e&isting ty%e *although the private ones are hidden away and inaccessible,, but #ore i#%ortant, it du%licates the inter"ace o" the base class. That is, all the #essages you can send to ob0ects o" the base class you can also send to ob0ects o" the derived class. Since we know the ty%e o" a class by the #essages we can send to it, this #eans that the derived class is the same t) e as the base

42

class. In the %revious e&a#%le, !a circle is a sha%e.$ This ty%e eAuivalence


via inheritance is one o" the "unda#ental gateways in understanding the #eaning o" ob0ect'oriented %rogra##ing.RFSURF STIJLT+(6PTE5MTI?LU Since both the base class and derived class have the sa#e inter"ace, there #ust be so#e i#%le#entation to go along with that inter"ace. That is, there #ust be so#e code to e&ecute when an ob0ect receives a %articular #essage. I" you si#%ly inherit a class and don t do anything else, the #ethods "ro# the base'class inter"ace co#e right along into the derived class. That #eans ob0ects o" the derived class have not only the sa#e ty%e, they also have the sa#e behavior, which isn t %articularly interesting.RF SURFSTIJLT+(6PTE5MTI??U /ou have two ways to di""erentiate your new derived class "ro# the original base class. The "irst is Auite straight"orward= /ou si#%ly add brand new "unctions to the derived class. These new "unctions are not %art o" the base class inter"ace. This #eans that the base class si#%ly didn t do as #uch as you wanted it to, so you added #ore "unctions. This si#%le and %ri#itive use "or inheritance is, at ti#es, the %er"ect solution to your %roble#. (owever, you should look closely "or the %ossibility that your base class #ight also need these additional "unctions. This %rocess o" discovery and iteration o" your design ha%%ens regularly in ob0ect' oriented %rogra##ing.RFSURFSTIJLT+(6PTE5MTI?HU

Cha ter 1! Introduction to Ob>ects

43

Sha e draw89 erase89 move89 getColor89 setColor89

$ircle

S%uare

&riangle <li.=ertical89 <li.>ori?ontal89

6lthough inheritance #ay so#eti#es i#%ly *es%ecially in Java, where the keyword that indicates inheritance is e4ten's, that you are going to add new "unctions to the inter"ace, that s not necessarily true. The second and #ore i#%ortant way to di""erentiate your new class is to change the behavior o" an e&isting base'class "unction. This is re"erred to as overriding that "unction.RFSURFSTIJLT+(6PTE5MTI?3U

44

Sha e draw89 erase89 move89 getColor89 setColor89

$ircle draw89 erase89

S%uare draw89 erase89

&riangle draw89 erase89

To override a "unction, you si#%ly create a new de"inition "or the "unction in the derived class. /ou re saying, !I # using the sa#e inter"ace "unction here, but I want it to do so#ething di""erent "or #y new ty%e.$RFSURF STIJLT+(6PTE5MTI?GU

Is@a vs) is@like@a relationshi.s


There s a certain debate that can occur about inheritance= Should inheritance override onl) base'class "unctions *and not add new #e#ber "unctions that aren t in the base class,O This would #ean that the derived ty%e is e*actl) the sa#e ty%e as the base class since it has e&actly the sa#e inter"ace. 6s a result, you can e&actly substitute an ob0ect o" the derived class "or an ob0ect o" the base class. This can be thought o" as ure substitution, and it s o"ten re"erred to as the substitution rinci le. In a sense, this is the ideal way to treat inheritance. :e o"ten re"er to the relationshi% between the base class and derived classes in this case as an is/a relationshi%, because you can say !a circle is a sha%e.$ 6 test "or inheritance is to deter#ine whether you can state the is'a relationshi% about the classes and have it #ake sense.RFSURF STIJLT+(6PTE5MTI?IU

Cha ter 1! Introduction to Ob>ects

45

There are ti#es when you #ust add new inter"ace ele#ents to a derived ty%e, thus e&tending the inter"ace and creating a new ty%e. The new ty%e can still be substituted "or the base ty%e, but the substitution isn t %er"ect because your new "unctions are not accessible "ro# the base ty%e. This can be described as an is/like/a@ relationshi%; the new ty%e has the inter"ace o" the old ty%e but it also contains other "unctions, so you can t really say it s e&actly the sa#e. Eor e&a#%le, consider an air conditioner. Su%%ose your house is wired with all the controls "or cooling; that is, it has an inter"ace that allows you to control cooling. I#agine that the air conditioner breaks down and you re%lace it with a heat %u#%, which can both heat and cool. The heat %u#% is/like/an air conditioner, but it can do #ore. Because the control syste# o" your house is designed only to control cooling, it is restricted to co##unication with the cooling %art o" the new ob0ect. The inter"ace o" the new ob0ect has been e&tended, and the e&isting syste# doesn t know about anything e&ce%t the original inter"ace.RFSURFSTIJLT+(6PTE5MTI?2U

&hermostat lower#em.erature89

Controls

$ooling System cool89

Air $onditioner cool89

Heat 'um cool89 heat89

)" course, once you see this design it beco#es clear that the base class !cooling syste#$ is not general enough, and should be rena#ed to !te#%erature control syste#$ so that it can also include heating9at which %oint the substitution %rinci%le will work. (owever, the diagra# above is an e&a#%le o" what can ha%%en in design and in the real world. RFSURF STIJLT+(6PTE5MTIH@U

@ My ter#.

47

:hen you see the substitution %rinci%le it s easy to "eel like this a%%roach *%ure substitution, is the only way to do things, and in "act it is nice i" your design works out that way. But you ll "ind that there are ti#es when it s eAually clear that you #ust add new "unctions to the inter"ace o" a derived class. :ith ins%ection both cases should be reasonably obvious. RFSURFSTIJLT+(6PTE5MTIHMU

Interchangeable ob3ects with .ol:mor.hism


:hen dealing with ty%e hierarchies, you o"ten want to treat an ob0ect not as the s%eci"ic ty%e that it is, but instead as its base ty%e. This allows you to write code that doesn t de%end on s%eci"ic ty%es. In the sha%e e&a#%le, "unctions #ani%ulate generic sha%es without res%ect to whether they re circles, sAuares, triangles, or so#e sha%e that hasn t even been de"ined yet. 6ll sha%es can be drawn, erased, and #oved, so these "unctions si#%ly send a #essage to a sha%e ob0ect; they don t worry about how the ob0ect co%es with the #essage.RFSURFSTIJLT+(6PTE5MTIHKU Such code is una""ected by the addition o" new ty%es, and adding new ty%es is the #ost co##on way to e&tend an ob0ect'oriented %rogra# to handle new situations. Eor e&a#%le, you can derive a new subty%e o" sha%e called %entagon without #odi"ying the "unctions that deal only with generic sha%es. This ability to e&tend a %rogra# easily by deriving new subty%es is i#%ortant because it greatly i#%roves designs while reducing the cost o" so"tware #aintenance.RFSURF STIJLT+(6PTE5MTIHLU There s a %roble#, however, with atte#%ting to treat derived'ty%e ob0ects as their generic base ty%es *circles as sha%es, bicycles as vehicles, cor#orants as birds, etc.,. I" a "unction is going to tell a generic sha%e to draw itsel", or a generic vehicle to steer, or a generic bird to #ove, the co#%iler cannot know at co#%ile'ti#e %recisely what %iece o" code will be e&ecuted. That s the whole %oint9when the #essage is sent, the

Cha ter 1! Introduction to Ob>ects

48

%rogra##er doesn t ,ant to know what %iece o" code will be e&ecuted; the draw "unction can be a%%lied eAually to a circle, a sAuare, or a triangle, and the ob0ect will e&ecute the %ro%er code de%ending on its s%eci"ic ty%e. I" you don t have to know what %iece o" code will be e&ecuted, then when you add a new subty%e, the code it e&ecutes can be di""erent without reAuiring changes to the "unction call. There"ore, the co#%iler cannot know %recisely what %iece o" code is e&ecuted, so what does it doO Eor e&a#%le, in the "ollowing diagra# the 2ir'-ontroller ob0ect 0ust works with generic 2ir' ob0ects, and does not know what e&act ty%e they are. This is convenient "ro# 2ir'-ontroller s %ers%ective because it doesn t have to write s%ecial code to deter#ine the e&act ty%e o" 2ir' it s working with, or that 2ir' s behavior. So how does it ha%%en that, when moveA B is called while ignoring the s%eci"ic ty%e o" 2ir', the right behavior will occur *a "oose runs, "lies, or swi#s, and a #eng*in runs or swi#s,ORFSURFSTIJLT+(6PTE5MTIH?U
Bird$ontroller re&ocate89 What ha..ens when move89 is calledA Bird move89

(oose move89

'enguin move89

The answer is the %ri#ary twist in ob0ect'oriented %rogra##ing= the co#%iler cannot #ake a "unction call in the traditional sense. The "unction call generated by a non'))P co#%iler causes what is called earl) binding, a ter# you #ay not have heard be"ore because you ve never thought about it any other way. It #eans the co#%iler generates a call to a s%eci"ic "unction na#e, and the linker resolves this call to the absolute address o" the code to be e&ecuted. In ))P, the %rogra# cannot deter#ine the address o" the code until run'ti#e, so so#e other sche#e is necessary when a #essage is sent to a generic ob0ect.RFSURF STIJLT+(6PTE5MTIHHU

4:

To solve the %roble#, ob0ect'oriented languages use the conce%t o" late binding. :hen you send a #essage to an ob0ect, the code being called isn t deter#ined until run'ti#e. The co#%iler does ensure that the "unction e&ists and %er"or#s ty%e checking on the argu#ents and return value *a language in which this isn t true is called ,eakl) t) ed,, but it doesn t know the e&act code to e&ecute.RFSURFSTIJLT+(6PTE5MTIH3U To %er"or# late binding, Java uses a s%ecial bit o" code in lieu o" the absolute call. This code calculates the address o" the "unction body, using in"or#ation stored in the ob0ect *this %rocess is covered in great detail in +ha%ter G,. Thus, each ob0ect can behave di""erently according to the contents o" that s%ecial bit o" code. :hen you send a #essage to an ob0ect, the ob0ect actually does "igure out what to do with that #essage.RF SURFSTIJLT+(6PTE5MTIHGU In so#e languages *+<<, in %articular, you #ust e&%licitly state that you want a "unction to have the "le&ibility o" late'binding %ro%erties. In these languages, by de"ault, #e#ber "unctions are not dyna#ically bound. This caused %roble#s, so in Java dyna#ic binding is the de"ault and you don t need to re#e#ber to add any e&tra keywords in order to get %oly#or%his#.RFSURFSTIJLT+(6PTE5MTIHIU +onsider the sha%e e&a#%le. The "a#ily o" classes *all based on the sa#e uni"or# inter"ace, was diagra##ed earlier in this cha%ter. To de#onstrate %oly#or%his#, we want to write a single %iece o" code that ignores the s%eci"ic details o" ty%e and talks only to the base class. That code is decou led "ro# ty%e's%eci"ic in"or#ation, and thus is si#%ler to write and easier to understand. 6nd, i" a new ty%e9a He4agon, "or e&a#%le9is added through inheritance, the code you write will work 0ust as well "or the new ty%e o" )hape as it did on the e&isting ty%es. Thus, the %rogra# is e*tensible.RFSURFSTIJLT+(6PTE5MTIH2U I" you write a #ethod in Java *as you will soon learn how to do,=RFSURF STIJLT+(6PTE5MTI3@U

voi! !o%tuff-%ha"e s. @ s.erase-.< // ... s.!ra:-.< A

Cha ter 1! Introduction to Ob>ects

4;

This "unction s%eaks to any )hape, so it is inde%endent o" the s%eci"ic ty%e o" ob0ect that it s drawing and erasing. I" in so#e other %art o" the %rogra# we use the 'o)t*ffA B "unction=RFSURF STIJLT+(6PTE5MTI3MU

Circle c ? ne: Circle-.< Triangle t ? ne: Triangle-.< Line l ? ne: Line-.< !o%tuff-c.< !o%tuff-t.< !o%tuff-l.<
The calls to 'o)t*ffA B auto#atically work correctly, regardless o" the e&act ty%e o" the ob0ect. RFSURFSTIJLT+(6PTE5MTI3KU This is actually a %retty a#a1ing trick. +onsider the line=

!o%tuff-c.<
:hat s ha%%ening here is that a -ircle is being %assed into a "unction that s e&%ecting a )hape. Since a -ircle is a )hape it can be treated as one by 'o)t*ffA B. That is, any #essage that 'o)t*ffA B can send to a )hape, a -ircle can acce%t. So it is a co#%letely sa"e and logical thing to do.RFSURFSTIJLT+(6PTE5MTI3LU :e call this %rocess o" treating a derived ty%e as though it were its base ty%e u casting. The na#e cast is used in the sense o" casting into a #old and the u co#es "ro# the way the inheritance diagra# is ty%ically arranged, with the base ty%e at the to% and the derived classes "anning out downward. Thus, casting to a base ty%e is #oving u% the inheritance diagra#= !u%casting.$RFSURFSTIJLT+(6PTE5MTI3?U

Sha e

BC.castingB

$ircle

S%uare

&riangle

5=

6n ob0ect'oriented %rogra# contains so#e u%casting so#ewhere, because that s how you decou%le yoursel" "ro# knowing about the e&act ty%e you re working with. Dook at the code in 'o)t*ffA B=RFSURF STIJLT+(6PTE5MTI3HU

s.erase-.< // ... s.!ra:-.<


Cotice that it doesn t say !I" you re a -ircle, do this, i" you re a )C*are, do that, etc.$ I" you write that kind o" code, which checks "or all the %ossible ty%es that a )hape can actually be, it s #essy and you need to change it every ti#e you add a new kind o" )hape. (ere, you 0ust say !/ou re a sha%e, I know you can eraseA B and 'ra(A B yoursel", do it, and take care o" the details correctly.$ RFSURFSTIJLT+(6PTE5MTI33U :hat s i#%ressive about the code in 'o)t*ffA B is that, so#ehow, the right thing ha%%ens. +alling 'ra(A B "or -ircle causes di""erent code to be e&ecuted than when calling 'ra(A B "or a )C*are or a +ine, but when the 'ra(A B #essage is sent to an anony#ous )hape, the correct behavior occurs based on the actual ty%e o" the )hape. This is a#a1ing because, as #entioned earlier, when the Java co#%iler is co#%iling the code "or 'o)t*ffA B, it cannot know e&actly what ty%es it is dealing with. So ordinarily, you d e&%ect it to end u% calling the version o" eraseA B and 'ra(A B "or the base class )hape, and not "or the s%eci"ic -ircle, )C*are, or +ine. 6nd yet the right thing ha%%ens because o" %oly#or%his#. The co#%iler and run'ti#e syste# handle the details; all you need to know is that it ha%%ens, and #ore i#%ortant how to design with it. :hen you send a #essage to an ob0ect, the ob0ect will do the right thing, even when u%casting is involved.RFSURFSTIJLT+(6PTE5MTI3GU

Abstract base classes and interfaces


)"ten in a design, you want the base class to %resent onl) an inter"ace "or its derived classes. That is, you don t want anyone to actually create an ob0ect o" the base class, only to u%cast to it so that its inter"ace can be used. This is acco#%lished by #aking that class abstract using the abstract keyword. I" anyone tries to #ake an ob0ect o" an abstract class,

Cha ter 1! Introduction to Ob>ects

51

the co#%iler %revents the#. This is a tool to en"orce a %articular design. RFSURFSTIJLT+(6PTE5MTI3IU /ou can also use the abstract keyword to describe a #ethod that hasn t been i#%le#ented yet9as a stub indicating !here is an inter"ace "unction "or all ty%es inherited "ro# this class, but at this %oint I don t have any i#%le#entation "or it.$ 6n abstract #ethod #ay be created only inside an abstract class. :hen the class is inherited, that #ethod #ust be i#%le#ented, or the inheriting class beco#es abstract as well. +reating an abstract #ethod allows you to %ut a #ethod in an inter"ace without being "orced to %rovide a %ossibly #eaningless body o" code "or that #ethod.RFSURFSTIJLT+(6PTE5MTI32U The interface keyword takes the conce%t o" an abstract class one ste% "urther by %reventing any "unction de"initions at all. The interface is a very handy and co##only used tool, as it %rovides the %er"ect se%aration o" inter"ace and i#%le#entation. In addition, you can co#bine #any inter"aces together, i" you wish, whereas inheriting "ro# #ulti%le regular classes or abstract classes is not %ossible.RFSURF STIJLT+(6PTE5MTIG@U

Ob3ect landsca.es and lifetimes


Technically, ))P is 0ust about abstract data ty%ing, inheritance, and %oly#or%his#, but other issues can be at least as i#%ortant. The re#ainder o" this section will cover these issues.RFSURF STIJLT+(6PTE5MTIGMU )ne o" the #ost i#%ortant "actors is the way ob0ects are created and destroyed. :here is the data "or an ob0ect and how is the li"eti#e o" the ob0ect controlledO There are di""erent %hiloso%hies at work here. +<< takes the a%%roach that control o" e""iciency is the #ost i#%ortant issue, so it gives the %rogra##er a choice. Eor #a&i#u# run'ti#e s%eed, the storage and li"eti#e can be deter#ined while the %rogra# is being written, by %lacing the ob0ects on the stack *these are so#eti#es called automatic or sco ed variables, or in the static storage area. This %laces a

52

%riority on the s%eed o" storage allocation and release, and control o" these can be very valuable in so#e situations. (owever, you sacri"ice "le&ibility because you #ust know the e&act Auantity, li"eti#e, and ty%e o" ob0ects while youVre writing the %rogra#. I" you are trying to solve a #ore general %roble# such as co#%uter'aided design, warehouse #anage#ent, or air'tra""ic control, this is too restrictive.RFSURF STIJLT+(6PTE5MTIGKU The second a%%roach is to create ob0ects dyna#ically in a %ool o" #e#ory called the hea%. In this a%%roach, you donVt know until run'ti#e how #any ob0ects you need, what their li"eti#e is, or what their e&act ty%e is. Those are deter#ined at the s%ur o" the #o#ent while the %rogra# is running. I" you need a new ob0ect, you si#%ly #ake it on the hea% at the %oint that you need it. Because the storage is #anaged dyna#ically, at run'ti#e, the a#ount o" ti#e reAuired to allocate storage on the hea% is signi"icantly longer than the ti#e to create storage on the stack. *+reating storage on the stack is o"ten a single asse#bly instruction to #ove the stack %ointer down, and another to #ove it back u%., The dyna#ic a%%roach #akes the generally logical assu#%tion that ob0ects tend to be co#%licated, so the e&tra overhead o" "inding storage and releasing that storage will not have an i#%ortant i#%act on the creation o" an ob0ect. In addition, the greater "le&ibility is essential to solve the general %rogra##ing %roble#.RFSURFSTIJLT+(6PTE5MTIGLU Java uses the second a%%roach, e&clusively @. Every ti#e you want to create an ob0ect, you use the ne( keyword to build a dyna#ic instance o" that ob0ect.RFSURFSTIJLT+(6PTE5MTIG?U ThereVs another issue, however, and thatVs the li"eti#e o" an ob0ect. :ith languages that allow ob0ects to be created on the stack, the co#%iler deter#ines how long the ob0ect lasts and can auto#atically destroy it. (owever, i" you create it on the hea% the co#%iler has no knowledge o" its li"eti#e. In a language like +<<, you #ust deter#ine %rogra##atically when to destroy the ob0ect, which can lead to #e#ory leaks i" you don t do it correctly *and this is a co##on %roble# in +<< %rogra#s,. Java %rovides a "eature called a garbage collector that auto#atically discovers when an ob0ect is no longer in use and destroys it. 6 garbage collector is #uch #ore convenient because it reduces the nu#ber o" issues that you
@ Pri#itive ty%es, which you ll learn about later, are a s%ecial case.

Cha ter 1! Introduction to Ob>ects

53

#ust track and the code you #ust write. More i#%ortant, the garbage collector %rovides a #uch higher level o" insurance against the insidious %roble# o" #e#ory leaks *which has brought #any a +<< %ro0ect to its knees,.RFSURFSTIJLT+(6PTE5MTIGHU The rest o" this section looks at additional "actors concerning ob0ect li"eti#es and landsca%es.RFSURFSTIJLT+(6PTE5MTIG3U

Collections and iterators


I" you don t know how #any ob0ects you re going to need to solve a %articular %roble#, or how long they will last, you also don t know how to store those ob0ects. (ow can you know how #uch s%ace to create "or those ob0ectsO /ou can t, since that in"or#ation isn t known until run' ti#e.RFSURFSTIJLT+(6PTE5MTIGGU The solution to #ost %roble#s in ob0ect'oriented design see#s "li%%ant= you create another ty%e o" ob0ect. The new ty%e o" ob0ect that solves this %articular %roble# holds re"erences to other ob0ects. )" course, you can do the sa#e thing with an array, which is available in #ost languages. But there s #ore. This new ob0ect, generally called a container *also called a collection, but the Java library uses that ter# in a di""erent sense so this book will use !container$,, will e&%and itsel" whenever necessary to acco##odate everything you %lace inside it. So you don t need to know how #any ob0ects you re going to hold in a container. Just create a container ob0ect and let it take care o" the details.RFSURF STIJLT+(6PTE5MTIGIU

54

Eortunately, a good ))P language co#es with a set o" containers as %art o" the %ackage. In +<<, it s %art o" the Standard +<< Dibrary and is so#eti#es called the Standard Te#%late Dibrary *STD,. )b0ect Pascal has containers in its Visual +o#%onent Dibrary *V+D,. S#alltalk has a very co#%lete set o" containers. Java also has containers in its standard library. In so#e libraries, a generic container is considered good enough "or all needs, and in others *Java, "or e&a#%le, the library has di""erent ty%es o" containers "or di""erent needs= a vector *called an Array+ist in Java, "or consistent access to all ele#ents, and a linked list "or consistent insertion at all ele#ents, "or e&a#%le, so you can choose the %articular ty%e that "its your needs. +ontainer libraries #ay also include sets, Aueues, hash tables, trees, stacks, etc.RFSURFSTIJLT+(6PTE5MTIG2U 6ll containers have so#e way to %ut things in and get things out; there are usually "unctions to add ele#ents to a container, and others to "etch those ele#ents back out. But "etching ele#ents can be #ore %roble#atic, because a single'selection "unction is restrictive. :hat i" you want to #ani%ulate or co#%are a set o" ele#ents in the container instead o" 0ust oneORFSURFSTIJLT+(6PTE5MTII@U The solution is an iterator, which is an ob0ect whose 0ob is to select the ele#ents within a container and %resent the# to the user o" the iterator. 6s a class, it also %rovides a level o" abstraction. This abstraction can be used to se%arate the details o" the container "ro# the code that s accessing that container. The container, via the iterator, is abstracted to be si#%ly a seAuence. The iterator allows you to traverse that seAuence without worrying about the underlying structure9that is, whether it s an Array+ist, a +inke'+ist, a )tack, or so#ething else. This gives you the "le&ibility to easily change the underlying data structure without disturbing the code in your %rogra#. Java began *in version M.@ and M.M, with a standard iterator, called &n*meration, "or all o" its container classes. Java K has added a #uch #ore co#%lete container library that contains an iterator called Iterator that does #ore than the older &n*meration.RFSURFSTIJLT+(6PTE5MTIIMU Ero# a design stand%oint, all you really want is a seAuence that can be #ani%ulated to solve your %roble#. I" a single ty%e o" seAuence satis"ied all o" your needs, there d be no reason to have di""erent kinds. There are two reasons that you need a choice o" containers. Eirst, containers

Cha ter 1! Introduction to Ob>ects

55

%rovide di""erent ty%es o" inter"aces and e&ternal behavior. 6 stack has a di""erent inter"ace and behavior than that o" a Aueue, which is di""erent "ro# that o" a set or a list. )ne o" these #ight %rovide a #ore "le&ible solution to your %roble# than the other. Second, di""erent containers have di""erent e""iciencies "or certain o%erations. The best e&a#%le is an Array+ist and a +inke'+ist. Both are si#%le seAuences that can have identical inter"aces and e&ternal behaviors. But certain o%erations can have radically di""erent costs. 5ando#ly accessing ele#ents in an Array+ist is a constant'ti#e o%eration; it takes the sa#e a#ount o" ti#e regardless o" the ele#ent you select. (owever, in a +inke'+ist it is e&%ensive to #ove through the list to rando#ly select an ele#ent, and it takes longer to "ind an ele#ent that is "urther down the list. )n the other hand, i" you want to insert an ele#ent in the #iddle o" a seAuence, it s #uch chea%er in a +inke'+ist than in an Array+ist. These and other o%erations have di""erent e""iciencies de%ending on the underlying structure o" the seAuence. In the design %hase, you #ight start with a +inke'+ist and, when tuning "or %er"or#ance, change to an Array+ist. Because o" the abstraction via iterators, you can change "ro# one to the other with #ini#al i#%act on your code.RFSURF STIJLT+(6PTE5MTIIKU In the end, re#e#ber that a container is only a storage cabinet to %ut ob0ects in. I" that cabinet solves all o" your needs, it doesn t really #atter how it is i#%le#ented *a basic conce%t with #ost ty%es o" ob0ects,. I" you re working in a %rogra##ing environ#ent that has built'in overhead due to other "actors, then the cost di""erence between an Array+ist and a +inke'+ist #ight not #atter. /ou #ight need only one ty%e o" seAuence. /ou can even i#agine the !%er"ect$ container abstraction, which can auto#atically change its underlying i#%le#entation according to the way it is used.RFSURFSTIJLT+(6PTE5MTIILU

57

#he singl: rooted hierarch:


)ne o" the issues in ))P that has beco#e es%ecially %ro#inent since the introduction o" +<< is whether all classes should ulti#ately be inherited "ro# a single base class. In Java *as with virtually all other ))P languages, the answer is !yes$ and the na#e o" this ulti#ate base class is si#%ly .b8ect. It turns out that the bene"its o" the singly rooted hierarchy are #any.RFSURFSTIJLT+(6PTE5MTII?U 6ll ob0ects in a singly rooted hierarchy have an inter"ace in co##on, so they are all ulti#ately the sa#e ty%e. The alternative *%rovided by +<<, is that you don t know that everything is the sa#e "unda#ental ty%e. Ero# a backward'co#%atibility stand%oint this "its the #odel o" + better and can be thought o" as less restrictive, but when you want to do "ull'on ob0ect' oriented %rogra##ing you #ust then build your own hierarchy to %rovide the sa#e convenience that s built into other ))P languages. 6nd in any new class library you acAuire, so#e other inco#%atible inter"ace will be used. It reAuires e""ort *and %ossibly #ulti%le inheritance, to work the new inter"ace into your design. Is the e&tra !"le&ibility$ o" +<< worth itO I" you need it9i" you have a large invest#ent in +9it s Auite valuable. I" you re starting "ro# scratch, other alternatives such as Java can o"ten be #ore %roductive.RFSURFSTIJLT+(6PTE5MTIIHU 6ll ob0ects in a singly rooted hierarchy *such as Java %rovides, can be guaranteed to have certain "unctionality. /ou know you can %er"or# certain basic o%erations on every ob0ect in your syste#. 6 singly rooted hierarchy, along with creating all ob0ects on the hea%, greatly si#%li"ies argu#ent %assing *one o" the #ore co#%le& to%ics in +<<,.RFSURF STIJLT+(6PTE5MTII3U 6 singly rooted hierarchy #akes it #uch easier to i#%le#ent a garbage collector *which is conveniently built into Java,. The necessary su%%ort can be installed in the base class, and the garbage collector can thus send the a%%ro%riate #essages to every ob0ect in the syste#. :ithout a singly rooted hierarchy and a syste# to #ani%ulate an ob0ect via a re"erence, it is di""icult to i#%le#ent a garbage collector.RFSURF STIJLT+(6PTE5MTIIGU Since run'ti#e ty%e in"or#ation is guaranteed to be in all ob0ects, you ll never end u% with an ob0ect whose ty%e you cannot deter#ine. This is

Cha ter 1! Introduction to Ob>ects

58

es%ecially i#%ortant with syste# level o%erations, such as e&ce%tion handling, and to allow greater "le&ibility in %rogra##ing.RFSURF STIJLT+(6PTE5MTIIIU

Collection libraries and su..ort for eas: collection use


Because a container is a tool that you ll use "reAuently, it #akes sense to have a library o" containers that are built in a reusable "ashion, so you can take one o"" the shel" and %lug it into your %rogra#. Java %rovides such a library, which should satis"y #ost needs.RFSURF STIJLT+(6PTE5MTII2U

Downcasting vs) tem.latesDgenerics


To #ake these containers reusable, they hold the one universal ty%e in Java that was %reviously #entioned= .b8ect. The singly rooted hierarchy #eans that everything is an .b8ect, so a container that holds .b8ects can hold anything. This #akes containers easy to reuse.RFSURF STIJLT+(6PTE5MTI2@U To use such a container, you si#%ly add ob0ect re"erences to it, and later ask "or the# back. But, since the container holds only .b8ects, when you add your ob0ect re"erence into the container it is u%cast to .b8ect, thus losing its identity. :hen you "etch it back, you get an .b8ect re"erence, and not a re"erence to the ty%e that you %ut in. So how do you turn it back into so#ething that has the use"ul inter"ace o" the ob0ect that you %ut into the containerORFSURFSTIJLT+(6PTE5MTI2MU (ere, the cast is used again, but this ti#e you re not casting u% the inheritance hierarchy to a #ore general ty%e, you cast down the hierarchy to a #ore s%eci"ic ty%e. This #anner o" casting is called downcasting. :ith u%casting, you know, "or e&a#%le, that a -ircle is a ty%e o" )hape so it s sa"e to u%cast, but you don t know that an .b8ect is necessarily a -ircle or a )hape so it s hardly sa"e to downcast unless you know that s what you re dealing with.RFSURFSTIJLT+(6PTE5MTI2KU It s not co#%letely dangerous, however, because i" you downcast to the wrong thing you ll get a run'ti#e error called an e*ce tionD which will be

5:

described shortly. :hen you "etch ob0ect re"erences "ro# a container, though, you #ust have so#e way to re#e#ber e&actly what they are so you can %er"or# a %ro%er downcast.RFSURFSTIJLT+(6PTE5MTI2LU 7owncasting and the run'ti#e checks reAuire e&tra ti#e "or the running %rogra#, and e&tra e""ort "ro# the %rogra##er. :ouldn t it #ake sense to so#ehow create the container so that it knows the ty%es that it holds, eli#inating the need "or the downcast and a %ossible #istakeO The solution is %ara#eteri1ed ty%es, which are classes that the co#%iler can auto#atically custo#i1e to work with %articular ty%es. Eor e&a#%le, with a %ara#eteri1ed container, the co#%iler could custo#i1e that container so that it would acce%t only Sha%es and "etch only Sha%es.RFSURF STIJLT+(6PTE5MTI2?U Para#eteri1ed ty%es are an i#%ortant %art o" +<<, %artly because +<< has no singly rooted hierarchy. In +<<, the keyword that i#%le#ents %ara#eteri1ed ty%es is !te#%late.$ Java currently has no %ara#eteri1ed ty%es since it is %ossible "or it to get by9however awkwardly9using the singly rooted hierarchy. (owever, a current %ro%osal "or %ara#eteri1ed ty%es uses a synta& that is strikingly si#ilar to +<< te#%lates.RFSURF STIJLT+(6PTE5MTI2HU

#he housekee.ing dilemma: who should clean u.A


Each ob0ect reAuires resources in order to e&ist, #ost notably #e#ory. :hen an ob0ect is no longer needed it #ust be cleaned u% so that these resources are released "or reuse. In si#%le %rogra##ing situations the Auestion o" how an ob0ect is cleaned u% doesn t see# too challenging= you create the ob0ect, use it "or as long as it s needed, and then it should be destroyed. It s not hard, however, to encounter situations in which the situation is #ore co#%le&.RFSURFSTIJLT+(6PTE5MTI23U Su%%ose, "or e&a#%le, you are designing a syste# to #anage air tra""ic "or an air%ort. *The sa#e #odel #ight also work "or #anaging crates in a warehouse, or a video rental syste#, or a kennel "or boarding %ets., 6t "irst it see#s si#%le= #ake a container to hold air%lanes, then create a new air%lane and %lace it in the container "or each air%lane that enters the

Cha ter 1! Introduction to Ob>ects

5;

air'tra""ic'control 1one. Eor cleanu%, si#%ly delete the a%%ro%riate air%lane ob0ect when a %lane leaves the 1one.RFSURF STIJLT+(6PTE5MTI2GU But %erha%s you have so#e other syste# to record data about the %lanes; %erha%s data that doesn t reAuire such i##ediate attention as the #ain controller "unction. Maybe it s a record o" the "light %lans o" all the s#all %lanes that leave the air%ort. So you have a second container o" s#all %lanes, and whenever you create a %lane ob0ect you also %ut it in this second container i" it s a s#all %lane. Then so#e background %rocess %er"or#s o%erations on the ob0ects in this container during idle #o#ents. RFSURFSTIJLT+(6PTE5MTI2IU Cow the %roble# is #ore di""icult= how can you %ossibly know when to destroy the ob0ectsO :hen you re done with the ob0ect, so#e other %art o" the syste# #ight not be. This sa#e %roble# can arise in a nu#ber o" other situations, and in %rogra##ing syste#s *such as +<<, in which you #ust e&%licitly delete an ob0ect when you re done with it this can beco#e Auite co#%le&.RFSURFSTIJLT+(6PTE5MTI22U :ith Java, the garbage collector is designed to take care o" the %roble# o" releasing the #e#ory *although this doesn t include other as%ects o" cleaning u% an ob0ect,. The garbage collector !knows$ when an ob0ect is no longer in use, and it then auto#atically releases the #e#ory "or that ob0ect. This *co#bined with the "act that all ob0ects are inherited "ro# the single root class .b8ect and that you can create ob0ects only one way, on the hea%, #akes the %rocess o" %rogra##ing in Java #uch si#%ler than %rogra##ing in +<<. /ou have "ar "ewer decisions to #ake and hurdles to overco#e.RFSURFSTIJLT+(6PTE5MTIM@@U

'arbage collectors vs) efficienc: and fle0ibilit:


I" all this is such a good idea, why didn t they do the sa#e thing in +<<O :ell o" course there s a %rice you %ay "or all this %rogra##ing convenience, and that %rice is run'ti#e overhead. 6s #entioned be"ore, in +<< you can create ob0ects on the stack, and in this case they re auto#atically cleaned u% *but you don t have the "le&ibility o" creating as #any as you want at run'ti#e,. +reating ob0ects on the stack is the #ost

7=

e""icient way to allocate storage "or ob0ects and to "ree that storage. +reating ob0ects on the hea% can be #uch #ore e&%ensive. 6lways inheriting "ro# a base class and #aking all "unction calls %oly#or%hic also e&acts a s#all toll. But the garbage collector is a %articular %roble# because you never Auite know when it s going to start u% or how long it will take. This #eans that there s an inconsistency in the rate o" e&ecution o" a Java %rogra#, so you can t use it in certain situations, such as when the rate o" e&ecution o" a %rogra# is uni"or#ly critical. *These are generally called real ti#e %rogra#s, although not all real ti#e %rogra##ing %roble#s are this stringent.,RFSURF STIJLT+(6PTE5MTIM@MU The designers o" the +<< language, trying to woo + %rogra##ers *and #ost success"ully, at that,, did not want to add any "eatures to the language that would i#%act the s%eed or the use o" +<< in any situation where %rogra##ers #ight otherwise choose +. This goal was reali1ed, but at the %rice o" greater co#%le&ity when %rogra##ing in +<<. Java is si#%ler than +<<, but the trade'o"" is in e""iciency and so#eti#es a%%licability. Eor a signi"icant %ortion o" %rogra##ing %roble#s, however, Java is the su%erior choice.RFSURFSTIJLT+(6PTE5MTIM@KU

/0ce.tion handling: dealing with errors


Ever since the beginning o" %rogra##ing languages, error handling has been one o" the #ost di""icult issues. Because it s so hard to design a good error handling sche#e, #any languages si#%ly ignore the issue, %assing the %roble# on to library designers who co#e u% with hal"way #easures that can work in #any situations but can easily be circu#vented, generally by 0ust ignoring the#. 6 #a0or %roble# with #ost error handling sche#es is that they rely on %rogra##er vigilance in "ollowing an agreed'u%on convention that is not en"orced by the language. I" the %rogra##er is not vigilant9o"ten the case i" they are in a hurry9these sche#es can easily be "orgotten.RFSURFSTIJLT+(6PTE5MTIM@LU E&ce%tion handling wires error handling directly into the %rogra##ing language and so#eti#es even the o%erating syste#. 6n e&ce%tion is an

Cha ter 1! Introduction to Ob>ects

71

ob0ect that is !thrown$ "ro# the site o" the error and can be !caught$ by an a%%ro%riate e&ce%tion handler designed to handle that %articular ty%e o" error. It s as i" e&ce%tion handling is a di""erent, %arallel %ath o" e&ecution that can be taken when things go wrong. 6nd because it uses a se%arate e&ecution %ath, it doesn t need to inter"ere with your nor#ally e&ecuting code. This #akes that code si#%ler to write since you aren t constantly "orced to check "or errors. In addition, a thrown e&ce%tion is unlike an error value that s returned "ro# a "unction or a "lag that s set by a "unction in order to indicate an error condition9these can be ignored. 6n e&ce%tion cannot be ignored, so it s guaranteed to be dealt with at so#e %oint. Einally, e&ce%tions %rovide a way to reliably recover "ro# a bad situation. Instead o" 0ust e&iting you are o"ten able to set things right and restore the e&ecution o" a %rogra#, which %roduces #uch #ore robust %rogra#s.RFSURFSTIJLT+(6PTE5MTIM@?U Java s e&ce%tion handling stands out a#ong %rogra##ing languages, because in Java, e&ce%tion handling was wired in "ro# the beginning and you re "orced to use it. I" you don t write your code to %ro%erly handle e&ce%tions, you ll get a co#%ile'ti#e error #essage. This guaranteed consistency #akes error handling #uch easier.RFSURF STIJLT+(6PTE5MTIM@HU It s worth noting that e&ce%tion handling isn t an ob0ect'oriented "eature, although in ob0ect'oriented languages the e&ce%tion is nor#ally re%resented with an ob0ect. E&ce%tion handling e&isted be"ore ob0ect' oriented languages.RFSURFSTIJLT+(6PTE5MTIM@3U

Multithreading
6 "unda#ental conce%t in co#%uter %rogra##ing is the idea o" handling #ore than one task at a ti#e. Many %rogra##ing %roble#s reAuire that the %rogra# be able to sto% what it s doing, deal with so#e other %roble#, and then return to the #ain %rocess. The solution has been a%%roached in #any ways. Initially, %rogra##ers with low'level knowledge o" the #achine wrote interru%t service routines and the sus%ension o" the #ain %rocess was initiated through a hardware interru%t. 6lthough this worked well, it was di""icult and non%ortable, so

72

it #ade #oving a %rogra# to a new ty%e o" #achine slow and e&%ensive. RFSURFSTIJLT+(6PTE5MTIM@GU So#eti#es interru%ts are necessary "or handling ti#e'critical tasks, but there s a large class o" %roble#s in which you re si#%ly trying to %artition the %roble# into se%arately running %ieces so that the whole %rogra# can be #ore res%onsive. :ithin a %rogra#, these se%arately running %ieces are called threads, and the general conce%t is called multithreading' 6 co##on e&a#%le o" #ultithreading is the user inter"ace. By using threads, a user can %ress a button and get a Auick res%onse rather than being "orced to wait until the %rogra# "inishes its current task.RFSURF STIJLT+(6PTE5MTIM@IU )rdinarily, threads are 0ust a way to allocate the ti#e o" a single %rocessor. But i" the o%erating syste# su%%orts #ulti%le %rocessors, each thread can be assigned to a di""erent %rocessor and they can truly run in %arallel. )ne o" the convenient "eatures o" #ultithreading at the language level is that the %rogra##er doesn t need to worry about whether there are #any %rocessors or 0ust one. The %rogra# is logically divided into threads and i" the #achine has #ore than one %rocessor then the %rogra# runs "aster, without any s%ecial ad0ust#ents.RFSURF STIJLT+(6PTE5MTIM@2U 6ll this #akes threading sound %retty si#%le. There is a catch= shared resources. I" you have #ore than one thread running that s e&%ecting to access the sa#e resource you have a %roble#. Eor e&a#%le, two %rocesses can t si#ultaneously send in"or#ation to a %rinter. To solve the %roble#, resources that can be shared, such as the %rinter, #ust be locked while they are being used. So a thread locks a resource, co#%letes its task, and then releases the lock so that so#eone else can use the resource.RFSURF STIJLT+(6PTE5MTIMM@U Java s threading is built into the language, which #akes a co#%licated sub0ect #uch si#%ler. The threading is su%%orted on an ob0ect level, so one thread o" e&ecution is re%resented by one ob0ect. Java also %rovides li#ited resource locking. It can lock the #e#ory o" any ob0ect *which is, a"ter all, one kind o" shared resource, so that only one thread can use it at a ti#e. This is acco#%lished with the synchroni7e' keyword. )ther ty%es o" resources #ust be locked e&%licitly by the %rogra##er, ty%ically

Cha ter 1! Introduction to Ob>ects

73

by creating an ob0ect to re%resent the lock that all threads #ust check be"ore accessing that resource.RFSURFSTIJLT+(6PTE5MTIMMMU

ersistence
:hen you create an ob0ect, it e&ists "or as long as you need it, but under no circu#stances does it e&ist when the %rogra# ter#inates. :hile this #akes sense at "irst, there are situations in which it would be incredibly use"ul i" an ob0ect could e&ist and hold its in"or#ation even while the %rogra# wasn t running. Then the ne&t ti#e you started the %rogra#, the ob0ect would be there and it would have the sa#e in"or#ation it had the %revious ti#e the %rogra# was running. )" course, you can get a si#ilar e""ect by writing the in"or#ation to a "ile or to a database, but in the s%irit o" #aking everything an ob0ect it would be Auite convenient to be able to declare an ob0ect %ersistent and have all the details taken care o" "or you. RFSURFSTIJLT+(6PTE5MTIMMKU Java %rovides su%%ort "or !lightweight %ersistence,$ which #eans that you can easily store ob0ects on disk and later retrieve the#. The reason it s !lightweight$ is that you re still "orced to #ake e&%licit calls to do the storage and retrieval. In addition, JavaS%aces *described in +ha%ter MH, %rovide "or a kind o" %ersistent storage o" ob0ects. In so#e "uture release #ore co#%lete su%%ort "or %ersistence #ight a%%ear.RFSURF STIJLT+(6PTE5MTIMMLU

"ava and the Internet


I" Java is, in "act, yet another co#%uter %rogra##ing language, you #ay Auestion why it is so i#%ortant and why it is being %ro#oted as a revolutionary ste% in co#%uter %rogra##ing. The answer isn t i##ediately obvious i" you re co#ing "ro# a traditional %rogra##ing %ers%ective. 6lthough Java is very use"ul "or solving traditional stand' alone %rogra##ing %roble#s, it is also i#%ortant because it will solve %rogra##ing %roble#s on the :orld :ide :eb.RFSURF STIJLT+(6PTE5MTIMM?U

74

What is the WebA


The :eb can see# a bit o" a #ystery at "irst, with all this talk o" !sur"ing,$ !%resence,$ and !ho#e %ages.$ There has even been a growing reaction against !Internet'#ania,$ Auestioning the econo#ic value and outco#e o" such a swee%ing #ove#ent. It s hel%"ul to ste% back and see what it really is, but to do this you #ust understand clientFserver syste#s, another as%ect o" co#%uting that s "ull o" con"using issues.RFSURF STIJLT+(6PTE5MTIMMHU

ClientD1erver com.uting
The %ri#ary idea o" a clientFserver syste# is that you have a central re%ository o" in"or#ation9so#e kind o" data, o"ten in a database9that you want to distribute on de#and to so#e set o" %eo%le or #achines. 6 key to the clientFserver conce%t is that the re%ository o" in"or#ation is centrally located so that it can be changed and so that those changes will %ro%agate out to the in"or#ation consu#ers. Taken together, the in"or#ation re%ository, the so"tware that distributes the in"or#ation, and the #achine*s, where the in"or#ation and so"tware reside is called the server. The so"tware that resides on the re#ote #achine, co##unicates with the server, "etches the in"or#ation, %rocesses it, and then dis%lays it on the re#ote #achine is called the client'RFSURF STIJLT+(6PTE5MTIMM3U The basic conce%t o" clientFserver co#%uting, then, is not so co#%licated. The %roble#s arise because you have a single server trying to serve #any clients at once. 8enerally, a database #anage#ent syste# is involved so the designer !balances$ the layout o" data into tables "or o%ti#al use. In addition, syste#s o"ten allow a client to insert new in"or#ation into a server. This #eans you #ust ensure that one client s new data doesn t walk over another client s new data, or that data isn t lost in the %rocess o" adding it to the database. *This is called transaction %rocessing., 6s client so"tware changes, it #ust be built, debugged, and installed on the client #achines, which turns out to be #ore co#%licated and e&%ensive than you #ight think. It s es%ecially %roble#atic to su%%ort #ulti%le ty%es o" co#%uters and o%erating syste#s. Einally, there s the all'i#%ortant %er"or#ance issue= you #ight have hundreds o" clients #aking reAuests o" your server at any one ti#e, and so any s#all delay is crucial. To

Cha ter 1! Introduction to Ob>ects

75

#ini#i1e latency, %rogra##ers work hard to o""load %rocessing tasks, o"ten to the client #achine, but so#eti#es to other #achines at the server site, using so'called middle,are' *Middleware is also used to i#%rove #aintainability.,RFSURFSTIJLT+(6PTE5MTIMMGU The si#%le idea o" distributing in"or#ation to %eo%le has so #any layers o" co#%le&ity in i#%le#enting it that the whole %roble# can see# ho%elessly enig#atic. 6nd yet it s crucial= clientFserver co#%uting accounts "or roughly hal" o" all %rogra##ing activities. It s res%onsible "or everything "ro# taking orders and credit'card transactions to the distribution o" any kind o" data9stock #arket, scienti"ic, govern#ent, you na#e it. :hat we ve co#e u% with in the %ast is individual solutions to individual %roble#s, inventing a new solution each ti#e. These were hard to create and hard to use, and the user had to learn a new inter"ace "or each one. The entire clientFserver %roble# needs to be solved in a big way.RFSURFSTIJLT+(6PTE5MTIMMIU

#he Web as a giant server


The :eb is actually one giant clientFserver syste#. It s a bit worse than that, since you have all the servers and clients coe&isting on a single network at once. /ou don t need to know that, since all you care about is connecting to and interacting with one server at a ti#e *even though you #ight be ho%%ing around the world in your search "or the correct server,. RFSURFSTIJLT+(6PTE5MTIMM2U Initially it was a si#%le one'way %rocess. /ou #ade a reAuest o" a server and it handed you a "ile, which your #achine s browser so"tware *i.e., the client, would inter%ret by "or#atting onto your local #achine. But in short order %eo%le began wanting to do #ore than 0ust deliver %ages "ro# a server. They wanted "ull clientFserver ca%ability so that the client could "eed in"or#ation back to the server, "or e&a#%le, to do database looku%s on the server, to add new in"or#ation to the server, or to %lace an order *which reAuired #ore security than the original syste#s o""ered,. These are the changes we ve been seeing in the develo%#ent o" the :eb.RFSURF STIJLT+(6PTE5MTIMK@U The :eb browser was a big ste% "orward= the conce%t that one %iece o" in"or#ation could be dis%layed on any ty%e o" co#%uter without change. (owever, browsers were still rather %ri#itive and ra%idly bogged down

77

by the de#ands %laced on the#. They weren t %articularly interactive, and tended to clog u% both the server and the Internet because any ti#e you needed to do so#ething that reAuired %rogra##ing you had to send in"or#ation back to the server to be %rocessed. It could take #any seconds or #inutes to "ind out you had #iss%elled so#ething in your reAuest. Since the browser was 0ust a viewer it couldn t %er"or# even the si#%lest co#%uting tasks. *)n the other hand, it was sa"e, since it couldn t e&ecute any %rogra#s on your local #achine that #ight contain bugs or viruses.,RFSURFSTIJLT+(6PTE5MTIMKMU To solve this %roble#, di""erent a%%roaches have been taken. To begin with, gra%hics standards have been enhanced to allow better ani#ation and video within browsers. The re#ainder o" the %roble# can be solved only by incor%orating the ability to run %rogra#s on the client end, under the browser. This is called client'side %rogra##ing.RFSURF STIJLT+(6PTE5MTIMKKU

Client@side .rogramming
The :eb s initial server'browser design %rovided "or interactive content, but the interactivity was co#%letely %rovided by the server. The server %roduced static %ages "or the client browser, which would si#%ly inter%ret and dis%lay the#. Basic (TMD contains si#%le #echanis#s "or data gathering= te&t'entry bo&es, check bo&es, radio bo&es, lists and dro%' down lists, as well as a button that can only be %rogra##ed to reset the data on the "or# or !sub#it$ the data on the "or# back to the server. This sub#ission %asses through the +o##on 8ateway Inter"ace *+8I, %rovided on all :eb servers. The te&t within the sub#ission tells +8I what to do with it. The #ost co##on action is to run a %rogra# located on the server in a directory that s ty%ically called !cgi'bin.$ *I" you watch the address window at the to% o" your browser when you %ush a button on a :eb %age, you can so#eti#es see !cgi'bin$ within all the gobbledygook there., These %rogra#s can be written in #ost languages. Perl is a co##on choice because it is designed "or te&t #ani%ulation and is inter%reted, so it can be installed on any server regardless o" %rocessor or o%erating syste#.RFSURFSTIJLT+(6PTE5MTIMKLU Many %ower"ul :eb sites today are built strictly on +8I, and you can in "act do nearly anything with it. (owever, :eb sites built on +8I

Cha ter 1! Introduction to Ob>ects

78

%rogra#s can ra%idly beco#e overly co#%licated to #aintain, and there is also the %roble# o" res%onse ti#e. The res%onse o" a +8I %rogra# de%ends on how #uch data #ust be sent, as well as the load on both the server and the Internet. *)n to% o" this, starting a +8I %rogra# tends to be slow., The initial designers o" the :eb did not "oresee how ra%idly this bandwidth would be e&hausted "or the kinds o" a%%lications %eo%le develo%ed. Eor e&a#%le, any sort o" dyna#ic gra%hing is nearly i#%ossible to %er"or# with consistency because a 8IE "ile #ust be created and #oved "ro# the server to the client "or each version o" the gra%h. 6nd you ve no doubt had direct e&%erience with so#ething as si#%le as validating the data on an in%ut "or#. /ou %ress the sub#it button on a %age; the data is shi%%ed back to the server; the server starts a +8I %rogra# that discovers an error, "or#ats an (TMD %age in"or#ing you o" the error, and then sends the %age back to you; you #ust then back u% a %age and try again. Cot only is this slow, it s inelegant.RFSURF STIJLT+(6PTE5MTIMK?U The solution is client'side %rogra##ing. Most #achines that run :eb browsers are %ower"ul engines ca%able o" doing vast work, and with the original static (TMD a%%roach they are sitting there, 0ust idly waiting "or the server to dish u% the ne&t %age. +lient'side %rogra##ing #eans that the :eb browser is harnessed to do whatever work it can, and the result "or the user is a #uch s%eedier and #ore interactive e&%erience at your :eb site.RFSURFSTIJLT+(6PTE5MTIMKHU The %roble# with discussions o" client'side %rogra##ing is that they aren t very di""erent "ro# discussions o" %rogra##ing in general. The %ara#eters are al#ost the sa#e, but the %lat"or# is di""erent= a :eb browser is like a li#ited o%erating syste#. In the end, you #ust still %rogra#, and this accounts "or the di11ying array o" %roble#s and solutions %roduced by client'side %rogra##ing. The rest o" this section %rovides an overview o" the issues and a%%roaches in client'side %rogra##ing.RFSURFSTIJLT+(6PTE5MTIMK3U

lug@ins
)ne o" the #ost signi"icant ste%s "orward in client'side %rogra##ing is the develo%#ent o" the %lug'in. This is a way "or a %rogra##er to add new "unctionality to the browser by downloading a %iece o" code that

7:

%lugs itsel" into the a%%ro%riate s%ot in the browser. It tells the browser !"ro# now on you can %er"or# this new activity.$ */ou need to download the %lug'in only once., So#e "ast and %ower"ul behavior is added to browsers via %lug'ins, but writing a %lug'in is not a trivial task, and isn t so#ething you d want to do as %art o" the %rocess o" building a %articular site. The value o" the %lug'in "or client'side %rogra##ing is that it allows an e&%ert %rogra##er to develo% a new language and add that language to a browser without the %er#ission o" the browser #anu"acturer. Thus, %lug'ins %rovide a !back door$ that allows the creation o" new client'side %rogra##ing languages *although not all languages are i#%le#ented as %lug'ins,.RFSURFSTIJLT+(6PTE5MTIMKGU

1cri.ting languages
Plug'ins resulted in an e&%losion o" scri%ting languages. :ith a scri%ting language you e#bed the source code "or your client'side %rogra# directly into the (TMD %age, and the %lug'in that inter%rets that language is auto#atically activated while the (TMD %age is being dis%layed. Scri%ting languages tend to be reasonably easy to understand and, because they are si#%ly te&t that is %art o" an (TMD %age, they load very Auickly as %art o" the single server hit reAuired to %rocure that %age. The trade'o"" is that your code is e&%osed "or everyone to see *and steal,. 8enerally, however, you aren t doing a#a1ingly so%histicated things with scri%ting languages so this is not too #uch o" a hardshi%.RFSURF STIJLT+(6PTE5MTIMKIU This %oints out that the scri%ting languages used inside :eb browsers are really intended to solve s%eci"ic ty%es o" %roble#s, %ri#arily the creation o" richer and #ore interactive gra%hical user inter"aces *84Is,. (owever, a scri%ting language #ight solve I@ %ercent o" the %roble#s encountered in client'side %rogra##ing. /our %roble#s #ight very well "it co#%letely within that I@ %ercent, and since scri%ting languages can allow easier and "aster develo%#ent, you should %robably consider a scri%ting language be"ore looking at a #ore involved solution such as Java or 6ctiveZ %rogra##ing.RFSURFSTIJLT+(6PTE5MTIMK2U The #ost co##only discussed browser scri%ting languages are JavaScri%t *which has nothing to do with Java; it s na#ed that way 0ust to grab so#e o" Java s #arketing #o#entu#,, VBScri%t *which looks like

Cha ter 1! Introduction to Ob>ects

7;

Visual Basic,, and TclFTk, which co#es "ro# the %o%ular cross'%lat"or# 84I'building language. There are others out there, and no doubt #ore in develo%#ent.RFSURFSTIJLT+(6PTE5MTIML@U JavaScri%t is %robably the #ost co##only su%%orted. It co#es built into both Cetsca%e Cavigator and the Microso"t Internet E&%lorer *IE,. In addition, there are %robably #ore JavaScri%t books available than there are "or the other browser languages, and so#e tools auto#atically create %ages using JavaScri%t. (owever, i" you re already "luent in Visual Basic or TclFTk, you ll be #ore %roductive using those scri%ting languages rather than learning a new one. */ou ll have your hands "ull dealing with the :eb issues already., RFSURFSTIJLT+(6PTE5MTIMLMU

"ava
I" a scri%ting language can solve I@ %ercent o" the client'side %rogra##ing %roble#s, what about the other K@ %ercent9the !really hard stu""O$ The #ost %o%ular solution today is Java. Cot only is it a %ower"ul %rogra##ing language built to be secure, cross'%lat"or#, and international, but Java is being continually e&tended to %rovide language "eatures and libraries that elegantly handle %roble#s that are di""icult in traditional %rogra##ing languages, such as #ultithreading, database access, network %rogra##ing, and distributed co#%uting. Java allows client'side %rogra##ing via the a let.RFSURF STIJLT+(6PTE5MTIMLKU 6n a%%let is a #ini'%rogra# that will run only under a :eb browser. The a%%let is downloaded auto#atically as %art o" a :eb %age *0ust as, "or e&a#%le, a gra%hic is auto#atically downloaded,. :hen the a%%let is activated it e&ecutes a %rogra#. This is %art o" its beauty9it %rovides you with a way to auto#atically distribute the client so"tware "ro# the server at the ti#e the user needs the client so"tware, and no sooner. The user gets the latest version o" the client so"tware without "ail and without di""icult reinstallation. Because o" the way Java is designed, the %rogra##er needs to create only a single %rogra#, and that %rogra# auto#atically works with all co#%uters that have browsers with built'in Java inter%reters. *This sa"ely includes the vast #a0ority o" #achines., Since Java is a "ull'"ledged %rogra##ing language, you can do as #uch work as %ossible on the client be"ore and a"ter #aking reAuests o" the

8=

server. Eor e&a#%le, you won t need to send a reAuest "or# across the Internet to discover that you ve gotten a date or so#e other %ara#eter wrong, and your client co#%uter can Auickly do the work o" %lotting data instead o" waiting "or the server to #ake a %lot and shi% a gra%hic i#age back to you. Cot only do you get the i##ediate win o" s%eed and res%onsiveness, but the general network tra""ic and load on servers can be reduced, %reventing the entire Internet "ro# slowing down.RFSURF STIJLT+(6PTE5MTIMLLU )ne advantage a Java a%%let has over a scri%ted %rogra# is that it s in co#%iled "or#, so the source code isn t available to the client. )n the other hand, a Java a%%let can be deco#%iled without too #uch trouble, but hiding your code is o"ten not an i#%ortant issue. Two other "actors can be i#%ortant. 6s you will see later in this book, a co#%iled Java a%%let can co#%rise #any #odules and take #ulti%le server !hits$ *accesses, to download. *In Java M.M and higher this is #ini#i1ed by Java archives, called J65 "iles, that allow all the reAuired #odules to be %ackaged together and co#%ressed "or a single download., 6 scri%ted %rogra# will 0ust be integrated into the :eb %age as %art o" its te&t *and will generally be s#aller and reduce server hits,. This could be i#%ortant to the res%onsiveness o" your :eb site. 6nother "actor is the all' i#%ortant learning curve. 5egardless o" what you ve heard, Java is not a trivial language to learn. I" you re a Visual Basic %rogra##er, #oving to VBScri%t will be your "astest solution, and since it will %robably solve #ost ty%ical clientFserver %roble#s you #ight be hard %ressed to 0usti"y learning Java. I" you re e&%erienced with a scri%ting language you will certainly bene"it "ro# looking at JavaScri%t or VBScri%t be"ore co##itting to Java, since they #ight "it your needs handily and you ll be #ore %roductive sooner.RFSURFSTIJLT+(6PTE5MTIML?U

ActiveE
To so#e degree, the co#%etitor to Java is Microso"t s 6ctiveZ, although it takes a co#%letely di""erent a%%roach. 6ctiveZ was originally a :indows' only solution, although it is now being develo%ed via an inde%endent consortiu# to beco#e cross'%lat"or#. E""ectively, 6ctiveZ says !i" your %rogra# connects to its environ#ent 0ust so, it can be dro%%ed into a :eb %age and run under a browser that su%%orts 6ctiveZ.$ *IE directly su%%orts 6ctiveZ and Cetsca%e does so using a %lug'in., Thus, 6ctiveZ

Cha ter 1! Introduction to Ob>ects

81

does not constrain you to a %articular language. I", "or e&a#%le, you re already an e&%erienced :indows %rogra##er using a language such as +<<, Visual Basic, or Borland s 7el%hi, you can create 6ctiveZ co#%onents with al#ost no changes to your %rogra##ing knowledge. 6ctiveZ also %rovides a %ath "or the use o" legacy code in your :eb %ages. RFSURFSTIJLT+(6PTE5MTIMLHU

1ecurit:
6uto#atically downloading and running %rogra#s across the Internet can sound like a virus'builder s drea#. 6ctiveZ es%ecially brings u% the thorny issue o" security in client'side %rogra##ing. I" you click on a :eb site, you #ight auto#atically download any nu#ber o" things along with the (TMD %age= 8IE "iles, scri%t code, co#%iled Java code, and 6ctiveZ co#%onents. So#e o" these are benign; 8IE "iles can t do any har#, and scri%ting languages are generally li#ited in what they can do. Java was also designed to run its a%%lets within a !sandbo&$ o" sa"ety, which %revents it "ro# writing to disk or accessing #e#ory outside the sandbo&. RFSURFSTIJLT+(6PTE5MTIML3U 6ctiveZ is at the o%%osite end o" the s%ectru#. Progra##ing with 6ctiveZ is like %rogra##ing :indows9you can do anything you want. So i" you click on a %age that downloads an 6ctiveZ co#%onent, that co#%onent #ight cause da#age to the "iles on your disk. )" course, %rogra#s that you load onto your co#%uter that are not restricted to running inside a :eb browser can do the sa#e thing. Viruses downloaded "ro# Bulletin'Board Syste#s *BBSs, have long been a %roble#, but the s%eed o" the Internet a#%li"ies the di""iculty.RFSURF STIJLT+(6PTE5MTIMLGU The solution see#s to be !digital signatures,$ whereby code is veri"ied to show who the author is. This is based on the idea that a virus works because its creator can be anony#ous, so i" you re#ove the anony#ity individuals will be "orced to be res%onsible "or their actions. This see#s like a good %lan because it allows %rogra#s to be #uch #ore "unctional, and I sus%ect it will eli#inate #alicious #ischie". I", however, a %rogra# has an unintentional destructive bug it will still cause %roble#s.RFSURF STIJLT+(6PTE5MTIMLIU

82

The Java a%%roach is to %revent these %roble#s "ro# occurring, via the sandbo&. The Java inter%reter that lives on your local :eb browser e&a#ines the a%%let "or any untoward instructions as the a%%let is being loaded. In %articular, the a%%let cannot write "iles to disk or erase "iles *one o" the #ainstays o" viruses,. 6%%lets are generally considered to be sa"e, and since this is essential "or reliable clientFserver syste#s, any bugs in the Java language that allow viruses are ra%idly re%aired. *It s worth noting that the browser so"tware actually en"orces these security restrictions, and so#e browsers allow you to select di""erent security levels to %rovide varying degrees o" access to your syste#.,RFSURF STIJLT+(6PTE5MTIML2U /ou #ight be ske%tical o" this rather draconian restriction against writing "iles to your local disk. Eor e&a#%le, you #ay want to build a local database or save data "or later use o""line. The initial vision see#ed to be that eventually everyone would get online to do anything i#%ortant, but that was soon seen to be i#%ractical *although low'cost !Internet a%%liances$ #ight so#eday satis"y the needs o" a signi"icant seg#ent o" users,. The solution is the !signed a%%let$ that uses %ublic'key encry%tion to veri"y that an a%%let does indeed co#e "ro# where it clai#s it does. 6 signed a%%let can still trash your disk, but the theory is that since you can now hold the a%%let creator accountable they won t do vicious things. Java %rovides a "ra#ework "or digital signatures so that you will eventually be able to allow an a%%let to ste% outside the sandbo& i" necessary.RFSURFSTIJLT+(6PTE5MTIM?@U 7igital signatures have #issed an i#%ortant issue, which is the s%eed that %eo%le #ove around on the Internet. I" you download a buggy %rogra# and it does so#ething untoward, how long will it be be"ore you discover the da#ageO It could be days or even weeks. By then, how will you track down the %rogra# that s done itO 6nd what good will it do you at that %ointORFSURFSTIJLT+(6PTE5MTIM?MU

Internet vs) intranet


The :eb is the #ost general solution to the clientFserver %roble#, so it #akes sense that you can use the sa#e technology to solve a subset o" the %roble#, in %articular the classic clientFserver %roble# ,ithin a co#%any. :ith traditional clientFserver a%%roaches you have the

Cha ter 1! Introduction to Ob>ects

83

%roble# o" #ulti%le ty%es o" client co#%uters, as well as the di""iculty o" installing new client so"tware, both o" which are handily solved with :eb browsers and client'side %rogra##ing. :hen :eb technology is used "or an in"or#ation network that is restricted to a %articular co#%any, it is re"erred to as an intranet. Intranets %rovide #uch greater security than the Internet, since you can %hysically control access to the servers within your co#%any. In ter#s o" training, it see#s that once %eo%le understand the general conce%t o" a browser it s #uch easier "or the# to deal with di""erences in the way %ages and a%%lets look, so the learning curve "or new kinds o" syste#s see#s to be reduced.RFSURF STIJLT+(6PTE5MTIM?KU The security %roble# brings us to one o" the divisions that see#s to be auto#atically "or#ing in the world o" client'side %rogra##ing. I" your %rogra# is running on the Internet, you don t know what %lat"or# it will be working under, and you want to be e&tra care"ul that you don t disse#inate buggy code. /ou need so#ething cross'%lat"or# and secure, like a scri%ting language or Java. RFSURFSTIJLT+(6PTE5MTIM?LU I" you re running on an intranet, you #ight have a di""erent set o" constraints. It s not unco##on that your #achines could all be IntelF :indows %lat"or#s. )n an intranet, you re res%onsible "or the Auality o" your own code and can re%air bugs when they re discovered. In addition, you #ight already have a body o" legacy code that you ve been using in a #ore traditional clientFserver a%%roach, whereby you #ust %hysically install client %rogra#s every ti#e you do an u%grade. The ti#e wasted in installing u%grades is the #ost co#%elling reason to #ove to browsers, because u%grades are invisible and auto#atic. I" you are involved in such an intranet, the #ost sensible a%%roach to take is the shortest %ath that allows you to use your e&isting code base, rather than trying to recode your %rogra#s in a new language.RFSURFSTIJLT+(6PTE5MTIM??U :hen "aced with this bewildering array o" solutions to the client'side %rogra##ing %roble#, the best %lan o" attack is a cost'bene"it analysis. +onsider the constraints o" your %roble# and what would be the shortest %ath to your solution. Since client'side %rogra##ing is still %rogra##ing, it s always a good idea to take the "astest develo%#ent a%%roach "or your %articular situation. This is an aggressive stance to

84

%re%are "or inevitable encounters with the %roble#s o" %rogra# develo%#ent.RFSURFSTIJLT+(6PTE5MTIM?HU

1erver@side .rogramming
This whole discussion has ignored the issue o" server'side %rogra##ing. :hat ha%%ens when you #ake a reAuest o" a serverO Most o" the ti#e the reAuest is si#%ly !send #e this "ile.$ /our browser then inter%rets the "ile in so#e a%%ro%riate "ashion= as an (TMD %age, a gra%hic i#age, a Java a%%let, a scri%t %rogra#, etc. 6 #ore co#%licated reAuest to a server generally involves a database transaction. 6 co##on scenario involves a reAuest "or a co#%le& database search, which the server then "or#ats into an (TMD %age and sends to you as the result. *)" course, i" the client has #ore intelligence via Java or a scri%ting language, the raw data can be sent and "or#atted at the client end, which will be "aster and less load on the server., )r you #ight want to register your na#e in a database when you 0oin a grou% or %lace an order, which will involve changes to that database. These database reAuests #ust be %rocessed via so#e code on the server side, which is generally re"erred to as server'side %rogra##ing. Traditionally, server'side %rogra##ing has been %er"or#ed using Perl and +8I scri%ts, but #ore so%histicated syste#s have been a%%earing. These include Java'based :eb servers that allow you to %er"or# all your server'side %rogra##ing in Java by writing what are called servlets. Servlets and their o""s%ring, JSPs, are two o" the #ost co#%elling reasons that co#%anies who develo% :eb sites are #oving to Java, es%ecially because they eli#inate the %roble#s o" dealing with di""erently abled browsers. RFSURFSTIJLT+(6PTE5MTIM?3U

A se.arate arena: a..lications


Much o" the brouhaha over Java has been over a%%lets. Java is actually a general'%ur%ose %rogra##ing language that can solve any ty%e o" %roble#9at least in theory. 6nd as %ointed out %reviously, there #ight be #ore e""ective ways to solve #ost clientFserver %roble#s. :hen you #ove out o" the a%%let arena *and si#ultaneously release the restrictions, such as the one against writing to disk, you enter the world o" general'%ur%ose a%%lications that run standalone, without a :eb browser, 0ust like any ordinary %rogra# does. (ere, Java s strength is not only in its %ortability,

Cha ter 1! Introduction to Ob>ects

85

but also its %rogra##ability. 6s you ll see throughout this book, Java has #any "eatures that allow you to create robust %rogra#s in a shorter %eriod than with %revious %rogra##ing languages.RFSURF STIJLT+(6PTE5MTIM?GU Be aware that this is a #i&ed blessing. /ou %ay "or the i#%rove#ents through slower e&ecution s%eed *although there is signi"icant work going on in this area9J7> M.L, in %articular, introduces the so'called !hots%ot$ %er"or#ance i#%rove#ents,. Dike any language, Java has built'in li#itations that #ight #ake it ina%%ro%riate to solve certain ty%es o" %rogra##ing %roble#s. Java is a ra%idly evolving language, however, and as each new release co#es out it beco#es #ore and #ore attractive "or solving larger sets o" %roble#s.RFSURFSTIJLT+(6PTE5MTIM?IU

Anal:sis and design


The ob0ect'oriented %aradig# is a new and di""erent way o" thinking about %rogra##ing. Many "olks have trouble at "irst knowing how to a%%roach an ))P %ro0ect. )nce you know that everything is su%%osed to be an ob0ect, and as you learn to think #ore in an ob0ect'oriented style, you can begin to create !good$ designs that take advantage o" all the bene"its that ))P has to o""er.RFSURFSTIJLT+(6PTE5MTIM?2U 6 methodolog) * o"ten so#eti#es si#%ly called a methodolog), is a set o" %rocesses and heuristics used to break down the co#%le&ity o" a %rogra##ing %roble#. Many ))P #ethod ologies have been "or#ulated since the dawn o" ob0ect'oriented %rogra##ing. This section will give you a "eel "or what you re trying to acco#%lish when using a #ethod ology.RF SURFSTIJLT+(6PTE5MTIMH@U Es%ecially in ))P, #ethodology is a "ield o" #any e&%eri#ents, so it is i#%ortant to understand what %roble# the #ethod ology is trying to solve be"ore you consider ado%ting one. This is %articularly true with Java, in which the %rogra##ing language is intended to reduce the co#%le&ity *co#%ared to +, involved in e&%ressing a %rogra#. This #ay in "act alleviate the need "or ever'#ore'co#%le& #ethodologies. Instead, si#%le #ethodologies #ay su""ice in Java "or a #uch larger class o" %roble#s

87

than you could handle using si#%le #ethodologies with %rocedural languages.RFSURFSTIJLT+(6PTE5MTIMHMU It s also i#%ortant to reali1e that the ter# !#ethodology$ is o"ten too grand and %ro#ises too #uch. :hatever you do now when you design and write a %rogra# is a #ethod ology. It #ay be your own #ethod ology, and you #ay not be conscious o" doing it, but it is a %rocess you go through as you create. I" it is an e""ective %rocess, it #ay need only a s#all tune'u% to work with Java. I" you are not satis"ied with your %roductivity and the way your %rogra#s turn out, you #ay want to consider ado%ting a "or#al #ethod ology, or choosing %ieces "ro# a#ong the #any "or#al #ethod ologies.F/GHF/GTIJ3IC."PTE-1II152H :hile you re going through the develo%#ent %rocess, the #ost i#%ortant issue is this= 7on t get lost. It s easy to do. Most o" the analysis and design #ethod oligies are intended to solve the largest o" %roble#s. 5e#e#ber that #ost %ro0ects don t "it into that category, so you can usually have success"ul analysis and design with a relatively s#all subset o" what a #ethod ology reco##ends @. But so#e sort o" %rocess, no #atter how li#ited, will generally get you on your way in a #uch better "ashion than si#%ly beginning to code.RFSURFSTIJLT+(6PTE5MTIMHLU It s also easy to get stuck, to "all into !analysis %aralysis,$ where you "eel like you can t #ove "orward because you haven t nailed down every little detail at the current stage. 5e#e#ber, no #atter how #uch analysis you do, there are so#e things about a syste# that won t reveal the#selves until design ti#e, and #ore things that won t reveal the#selves until you re coding, or not even until a %rogra# is u% and running. Because o" this, it s crucial to #ove "airly Auickly through analysis and design, and to i#%le#ent a test o" the %ro%osed syste#.RFSURF STIJLT+(6PTE5MTIMH?U This %oint is worth e#%hasi1ing. Because o" the history we ve had with %rocedural languages, it is co##endable that a tea# will want to %roceed care"ully and understand every #inute detail be"ore #oving to design and i#%le#entation. +ertainly, when creating a 7atabase Manage#ent Syste# *D4/*,, it %ays to understand a custo#er s needs thoroughly.
@ 6n e&cellent e&a#%le o" this is <M( %istilled, Knd edition, by Martin Eowler *6ddison' :esley K@@@,, which reduces the so#eti#es'overwhel#ing 4MD %rocess to a #anageable subset.

Cha ter 1! Introduction to Ob>ects

88

But a 7BMS is in a class o" %roble#s that is very well'%osed and well' understood; in #any such %rogra#s, the database structure is the %roble# to be tackled. The class o" %rogra##ing %roble# discussed in this cha%ter is o" the !wild'card$ *#y ter#, variety, in which the solution isn t si#%ly re'"or#ing a well'known solution, but instead involves one or #ore !wild'card "actors$9ele#ents "or which there is no well'understood %revious solution, and "or which research is necessary @. 6tte#%ting to thoroughly analy1e a wild'card %roble# be"ore #oving into design and i#%le#entation results in analysis %aralysis because you don t have enough in"or#ation to solve this kind o" %roble# during the analysis %hase. Solving such a %roble# reAuires iteration through the whole cycle, and that reAuires risk'taking behavior *which #akes sense, because you re trying to do so#ething new and the %otential rewards are higher,. It #ay see# like the risk is co#%ounded by !rushing$ into a %reli#inary i#%le#entation, but it can instead reduce the risk in a wild'card %ro0ect because you re "inding out early whether a %articular a%%roach to the %roble# is viable. Product develo%#ent is risk #anage#ent.RFSURF STIJLT+(6PTE5MTIMHHU It s o"ten %ro%osed that you !build one to throw away.$ :ith ))P, you #ay still throw art o" it away, but because code is enca%sulated into classes, during the "irst %ass you will inevitably %roduce so#e use"ul class designs and develo% so#e worthwhile ideas about the syste# design that do not need to be thrown away. Thus, the "irst ra%id %ass at a %roble# not only %roduces critical in"or#ation "or the ne&t analysis, design, and i#%le#entation %ass, it also creates a code "oundation.RFSURF STIJLT+(6PTE5MTIMH3U That said, i" you re looking at a #ethodology that contains tre#endous detail and suggests #any ste%s and docu#ents, it s still di""icult to know when to sto%. >ee% in #ind what you re trying to discover=RFSURF STIJLT+(6PTE5MTIMHGU

(!)

:hat are the ob0ectsO *(ow do you %artition your %ro0ect into its co#%onent %artsO,

@ My rule o" thu#b "or esti#ating such %ro0ects= I" there s #ore than one wild card, don t even try to %lan how long it s going to take or how #uch it will cost until you ve created a working %rototy%e. There are too #any degrees o" "reedo#.

8:

(*)

:hat are their inter"acesO *:hat #essages do you need to send to each ob0ectO,

I" you co#e u% with nothing #ore than the ob0ects and their inter"aces, then you can write a %rogra#. Eor various reasons you #ight need #ore descri%tions and docu#ents than this, but you can t get away with any less.RFSURFSTIJLT+(6PTE5MTIMHIU The %rocess can be undertaken in "ive %hases, and a Phase @ that is 0ust the initial co##it#ent to using so#e kind o" structure.RFSURF STIJLT+(6PTE5MTIMH2U

hase 7: Make a .lan


/ou #ust "irst decide what ste%s you re going to have in your %rocess. It sounds si#%le *in "act, all o" this sounds si#%le,, and yet %eo%le o"ten don t #ake this decision be"ore they start coding. I" your %lan is !let s 0u#% in and start coding,$ "ine. *So#eti#es that s a%%ro%riate when you have a well'understood %roble#., 6t least agree that this is the %lan.RF SURFSTIJLT+(6PTE5MTIM3@U /ou #ight also decide at this %hase that so#e additional %rocess structure is necessary, but not the whole nine yards. 4nderstandably, so#e %rogra##ers like to work in !vacation #ode,$ in which no structure is i#%osed on the %rocess o" develo%ing their work; !It will be done when it s done.$ This can be a%%ealing "or a while, but I ve "ound that having a "ew #ilestones along the way hel%s to "ocus and galvani1e your e""orts around those #ilestones instead o" being stuck with the single goal o" !"inish the %ro0ect.$ In addition, it divides the %ro0ect into #ore bite'si1ed %ieces and #akes it see# less threatening *%lus the #ilestones o""er #ore o%%ortunities "or celebration,.RFSURF STIJLT+(6PTE5MTIM3MU :hen I began to study story structure *so that I will so#eday write a novel, I was initially resistant to the idea o" structure, "eeling that I wrote best when I si#%ly let it "low onto the %age. But I later reali1ed that when I write about co#%uters the structure is clear enough to #e that I don t have to think about it very #uch. But I still structure #y work, albeit only se#i'consciously in #y head. Even i" you think that your %lan is to 0ust

Cha ter 1! Introduction to Ob>ects

8;

start coding, you still so#ehow go through the subseAuent %hases while asking and answering certain Auestions.RFSURF STIJLT+(6PTE5MTIM3KU

#he mission statement


6ny syste# you build, no #atter how co#%licated, has a "unda#ental %ur%ose; the business that it s in, the basic need that it satis"ies. I" you can look %ast the user inter"ace, the hardware' or syste#'s%eci"ic details, the coding algorith#s and the e""iciency %roble#s, you will eventually "ind the core o" its being9si#%le and straight"orward. Dike the so'called high conce t "ro# a (ollywood #ovie, you can describe it in one or two sentences. This %ure descri%tion is the starting %oint.RFSURF STIJLT+(6PTE5MTIM3LU The high conce%t is Auite i#%ortant because it sets the tone "or your %ro0ect; it s a #ission state#ent. /ou won t necessarily get it right the "irst ti#e *you #ay be in a later %hase o" the %ro0ect be"ore it beco#es co#%letely clear,, but kee% trying until it "eels right. Eor e&a#%le, in an air'tra""ic control syste# you #ay start out with a high conce%t "ocused on the syste# that you re building= !The tower %rogra# kee%s track o" the aircra"t.$ But consider what ha%%ens when you shrink the syste# to a very s#all air"ield; %erha%s there s only a hu#an controller, or none at all. 6 #ore use"ul #odel won t concern the solution you re creating as #uch as it describes the %roble#= !6ircra"t arrive, unload, service and reload, then de%art.$RFSURFSTIJLT+(6PTE5MTIM3?U

hase (: What are we makingA


In the %revious generation o" %rogra# design *called rocedural design,, this is called !creating the re#uirements anal)sis and s)stem s eci$ication.$ These, o" course, were %laces to get lost; inti#idatingly na#ed docu#ents that could beco#e big %ro0ects in their own right. Their intention was good, however. The reAuire#ents analysis says !Make a list o" the guidelines we will use to know when the 0ob is done and the custo#er is satis"ied.$ The syste# s%eci"ication says !(ere s a descri%tion o" ,hat the %rogra# will do *not ho,, to satis"y the reAuire#ents.$ The reAuire#ents analysis is really a contract between you and the custo#er *even i" the custo#er works within your co#%any, or is so#e other ob0ect

:=

or syste#,. The syste# s%eci"ication is a to%'level e&%loration into the %roble# and in so#e sense a discovery o" whether it can be done and how long it will take. Since both o" these will reAuire consensus a#ong %eo%le *and because they will usually change over ti#e,, I think it s best to kee% the# as bare as %ossible9ideally, to lists and basic diagra#s9to save ti#e. /ou #ight have other constraints that reAuire you to e&%and the# into bigger docu#ents, but by kee%ing the initial docu#ent s#all and concise, it can be created in a "ew sessions o" grou% brainstor#ing with a leader who dyna#ically creates the descri%tion. This not only solicits in%ut "ro# everyone, it also "osters initial buy'in and agree#ent by everyone on the tea#. Perha%s #ost i#%ortantly, it can kick o"" a %ro0ect with a lot o" enthusias#.RFSURFSTIJLT+(6PTE5MTIM3HU It s necessary to stay "ocused on the heart o" what you re trying to acco#%lish in this %hase= deter#ine what the syste# is su%%osed to do. The #ost valuable tool "or this is a collection o" what are called !use cases. $ 4se cases identi"y key "eatures in the syste# that will reveal so#e o" the "unda#ental classes you ll be using. These are essentially descri%tive answers to Auestions like @=RFSURFSTIJLT+(6PTE5MTIM33U

!:ho will use this syste#O$ !:hat can those actors do with the syste#O$ !(ow does this actor do that with this syste#O$ !(ow else #ight this work i" so#eone else were doing this, or i" the sa#e actor had a di""erent ob0ectiveO$ *to reveal variations, !:hat %roble#s #ight ha%%en while doing this with the syste#O $ *to reveal e&ce%tions,

I" you are designing an auto'teller, "or e&a#%le, the use case "or a %articular as%ect o" the "unctionality o" the syste# is able to describe what the auto'teller does in every %ossible situation. Each o" these !situations$ is re"erred to as a scenario, and a use case can be considered a collection o" scenarios. /ou can think o" a scenario as a Auestion that starts with= !:hat does the syste# do i"-O$ Eor e&a#%le, !:hat does the auto'teller do i" a custo#er has 0ust de%osited a check within the last K? hours, and there s not enough in the account without the check having cleared to %rovide a desired withdrawalO$ RFSURFSTIJLT+(6PTE5MTIM3GU
@ Thanks "or hel% "ro# Ja#es ( Jarrett.

Cha ter 1! Introduction to Ob>ects

:1

4se case diagra#s are intentionally si#%le to %revent you "ro# getting bogged down in syste# i#%le#entation details %re#aturely=
;ank
Make De.osit Make Withdrawal

Cses

#eller

Customer

'et Account ;alance #ransfer ;etween Accounts

A#M

Each stick %erson re%resents an !actor,$ which is ty%ically a hu#an or so#e other kind o" "ree agent. *These can even be other co#%uter syste#s, as is the case with !6TM.$, The bo& re%resents the boundary o" your syste#. The elli%ses re%resent the use cases, which are descri%tions o" valuable work that can be %er"or#ed with the syste#. The lines between the actors and the use cases re%resent the interactions.RFSURF STIJLT+(6PTE5MTIM3IU It doesn t #atter how the syste# is actually i#%le#ented, as long as it looks like this to the user.RFSURFSTIJLT+(6PTE5MTIM32U 6 use case does not need to be terribly co#%le&, even i" the underlying syste# is co#%le&. It is only intended to show the syste# as it a%%ears to the user. Eor e&a#%le=RFSURFSTIJLT+(6PTE5MTIMG@U

'reenhouse
Maintain 'rowing #em.erature

'ardener

:2

The use cases %roduce the reAuire#ents s%eci"ications by deter#ining all the interactions that the user #ay have with the syste#. /ou try to discover a "ull set o" use cases "or your syste#, and once you ve done that you have the core o" what the syste# is su%%osed to do. The nice thing about "ocusing on use cases is that they always bring you back to the essentials and kee% you "ro# dri"ting o"" into issues that aren t critical "or getting the 0ob done. That is, i" you have a "ull set o" use cases, you can describe your syste# and #ove on to the ne&t %hase. /ou %robably won t get it all "igured out %er"ectly on the "irst try, but that s )>. Everything will reveal itsel" in ti#e, and i" you de#and a %er"ect syste# s%eci"ication at this %oint you ll get stuck.RFSURFSTIJLT+(6PTE5MTIMGMU I" you do get stuck, you can kick'start this %hase by using a rough a%%ro&i#ation tool= describe the syste# in a "ew %aragra%hs and then look "or nouns and verbs. The nouns can suggest actors, conte&t o" the use case *e.g., !lobby$,, or arti"acts #ani%ulated in the use case. Verbs can suggest interactions between actors and use cases, and s%eci"y ste%s within the use case. /ou ll also discover that nouns and verbs %roduce ob0ects and #essages during the design %hase *and note that use cases describe interactions between subsyste#s, so the !noun and verb$ techniAue can be used only as a brainstor#ing tool as it does not generate use cases, D.RFSURFSTIJLT+(6PTE5MTIMGKU The boundary between a use case and an actor can %oint out the e&istence o" a user inter"ace, but it does not de"ine such a user inter"ace. Eor a %rocess o" de"ining and creating user inter"aces, see So$t,are $or <se by Darry +onstantine and Ducy Dockwood, *6ddison':esley Dong#an, M222, or go to ,,,'9or<se'com.RFSURFSTIJLT+(6PTE5MTIMGLU 6lthough it s a black art, at this %oint so#e kind o" basic scheduling is i#%ortant. /ou now have an overview o" what you re building, so you ll %robably be able to get so#e idea o" how long it will take. 6 lot o" "actors co#e into %lay here. I" you esti#ate a long schedule then the co#%any #ight decide not to build it *and thus use their resources on so#ething #ore reasonable9that s a good thing,. )r a #anager #ight have already decided how long the %ro0ect should take and will try to in"luence your
@ More in"or#ation on use cases can be "ound in " l)ing <se Cases by Schneider N :inters *6ddison':esley M22I, and <se Case %riven Ob>ect Modeling ,ith <M( by 5osenberg *6ddison':esley M222,.

Cha ter 1! Introduction to Ob>ects

:3

esti#ate. But it s best to have an honest schedule "ro# the beginning and deal with the tough decisions early. There have been a lot o" atte#%ts to co#e u% with accurate scheduling techniAues *#uch like techniAues to %redict the stock #arket,, but %robably the best a%%roach is to rely on your e&%erience and intuition. 8et a gut "eeling "or how long it will really take, then double that and add M@ %ercent. /our gut "eeling is %robably correct; you can get so#ething working in that ti#e. The !doubling$ will turn that into so#ething decent, and the M@ %ercent will deal with the "inal %olishing and details @. (owever you want to e&%lain it, and regardless o" the #oans and #ani%ulations that ha%%en when you reveal such a schedule, it 0ust see#s to work out that way.RFSURF STIJLT+(6PTE5MTIMG?U

hase !: >ow will we build itA


In this %hase you #ust co#e u% with a design that describes what the classes look like and how they will interact. 6n e&cellent techniAue in deter#ining classes and interactions is the Class/-es onsibilit)/ Collaboration *+5+, card. Part o" the value o" this tool is that it s so low' tech= you start out with a set o" blank L & H cards, and you write on the#. Each card re%resents a single class, and on the card you write=RFSURF STIJLT+(6PTE5MTIMGHU

(+)

The na#e o" the class. It s i#%ortant that this na#e ca%ture the essence o" what the class does, so that it #akes sense at a glance. RFSURFSTIJLT+(6PTE5MTIMG3U The !res%onsibilities$ o" the class= what it should do. This can ty%ically be su##ari1ed by 0ust stating the na#es o" the #e#ber "unctions *since those na#es should be descri%tive in a good design,, but it does not %reclude other notes. I" you need to seed the %rocess, look at the %roble# "ro# a la1y %rogra##er s stand%oint= :hat ob0ects would you like to #agically a%%ear to solve your %roble#O RFSURFSTIJLT+(6PTE5MTIMGGU

(,)

@ My %ersonal take on this has changed lately. 7oubling and adding M@ %ercent will give you a reasonably accurate esti#ate *assu#ing there are not too #any wild'card "actors,, but you still have to work Auite diligently to "inish in that ti#e. I" you want ti#e to really #ake it elegant and to en0oy yoursel" in the %rocess, the correct #ulti%lier is #ore like three or "our ti#es, I believe.

:4

(-)

The !collaborations$ o" the class= what other classes does it interact withO !Interact$ is an intentionally broad ter#; it could #ean aggregation or si#%ly that so#e other ob0ect e&ists that will %er"or# services "or an ob0ect o" the class. +ollaborations should also consider the audience "or this class. Eor e&a#%le, i" you create a class Firecracker, who is going to observe it, a -hemist or a )pectatorO The "or#er will want to know what che#icals go into the construction, and the latter will res%ond to the colors and sha%es released when it e&%lodes. RFSURF STIJLT+(6PTE5MTIMGIU

/ou #ay "eel like the cards should be bigger because o" all the in"or#ation you d like to get on the#, but they are intentionally s#all, not only to kee% your classes s#all but also to kee% you "ro# getting into too #uch detail too early. I" you can t "it all you need to know about a class on a s#all card, the class is too co#%le& *either you re getting too detailed, or you should create #ore than one class,. The ideal class should be understood at a glance. The idea o" +5+ cards is to assist you in co#ing u% with a "irst cut o" the design so that you can get the big %icture and then re"ine your design.RFSURFSTIJLT+(6PTE5MTIMG2U )ne o" the great bene"its o" +5+ cards is in co##unication. It s best done real ti#e, in a grou%, without co#%uters. Each %erson takes res%onsibility "or several classes *which at "irst have no na#es or other in"or#ation,. /ou run a live si#ulation by solving one scenario at a ti#e, deciding which #essages are sent to the various ob0ects to satis"y each scenario. 6s you go through this %rocess, you discover the classes that you need along with their res%onsibilities and collaborations, and you "ill out the cards as you do this. :hen you ve #oved through all the use cases, you should have a "airly co#%lete "irst cut o" your design.RFSURF STIJLT+(6PTE5MTIMI@U Be"ore I began using +5+ cards, the #ost success"ul consulting e&%eriences I had when co#ing u% with an initial design involved standing in "ront o" a tea#9who hadn t built an ))P %ro0ect be"ore9and drawing ob0ects on a whiteboard. :e talked about how the ob0ects should co##unicate with each other, and erased so#e o" the# and re%laced the# with other ob0ects. E""ectively, I was #anaging all the !+5+ cards$ on the whiteboard. The tea# *who knew what the %ro0ect was su%%osed

Cha ter 1! Introduction to Ob>ects

:5

to do, actually created the design; they !owned$ the design rather than having it given to the#. 6ll I was doing was guiding the %rocess by asking the right Auestions, trying out the assu#%tions, and taking the "eedback "ro# the tea# to #odi"y those assu#%tions. The true beauty o" the %rocess was that the tea# learned how to do ob0ect'oriented design not by reviewing abstract e&a#%les, but by working on the one design that was #ost interesting to the# at that #o#ent= theirs.RFSURF STIJLT+(6PTE5MTIMIMU )nce you ve co#e u% with a set o" +5+ cards, you #ay want to create a #ore "or#al descri%tion o" your design using 4MD @. /ou don t need to use 4MD, but it can be hel%"ul, es%ecially i" you want to %ut u% a diagra# on the wall "or everyone to %onder, which is a good idea. 6n alternative to 4MD is a te&tual descri%tion o" the ob0ects and their inter"aces, or, de%ending on your %rogra##ing language, the code itsel" @.RFSURF STIJLT+(6PTE5MTIMIKU 4MD also %rovides an additional diagra##ing notation "or describing the dyna#ic #odel o" your syste#. This is hel%"ul in situations in which the state transitions o" a syste# or subsyste# are do#inant enough that they need their own diagra#s *such as in a control syste#,. /ou #ay also need to describe the data structures, "or syste#s or subsyste#s in which data is a do#inant "actor *such as a database,.RFSURFSTIJLT+(6PTE5MTIMILU /ou ll know you re done with Phase K when you have described the ob0ects and their inter"aces. :ell, #ost o" the#9there are usually a "ew that sli% through the cracks and don t #ake the#selves known until Phase L. But that s )>. 6ll you are concerned with is that you eventually discover all o" your ob0ects. It s nice to discover the# early in the %rocess, but ))P %rovides enough structure so that it s not so bad i" you discover the# later. In "act, the design o" an ob0ect tends to ha%%en in "ive stages, throughout the %rocess o" %rogra# develo%#ent.RFSURF STIJLT+(6PTE5MTIMI?U

@ Eor starters, I reco##end the a"ore#entioned <M( %istilled, Knd edition. @ Python *www.Python.org, is o"ten used as !e&ecutable %seudocode.$

:7

<ive stages of ob3ect design


The design li"e o" an ob0ect is not li#ited to the ti#e when you re writing the %rogra#. Instead, the design o" an ob0ect a%%ears over a seAuence o" stages. It s hel%"ul to have this %ers%ective because you sto% e&%ecting %er"ection right away; instead, you reali1e that the understanding o" what an ob0ect does and what it should look like ha%%ens over ti#e. This view also a%%lies to the design o" various ty%es o" %rogra#s; the %attern "or a %articular ty%e o" %rogra# e#erges through struggling again and again with that %roble# *This is chronicled in the book Thinking in Patterns ,ith Java, downloadable at ,,,'0ruceEckel'com,. )b0ects, too, have their %atterns that e#erge through understanding, use, and reuse.RF SURFSTIJLT+(6PTE5MTIMIHU

). Object discovery. This stage occurs during the initial analysis o" a
%rogra#. )b0ects #ay be discovered by looking "or e&ternal "actors and boundaries, du%lication o" ele#ents in the syste#, and the s#allest conce%tual units. So#e ob0ects are obvious i" you already have a set o" class libraries. +o##onality between classes suggesting base classes and inheritance #ay a%%ear right away, or later in the design %rocess.RFSURF STIJLT+(6PTE5MTIMI3U

*. Object assembly. 6s you re building an ob0ect you ll discover the


need "or new #e#bers that didn t a%%ear during discovery. The internal needs o" the ob0ect #ay reAuire other classes to su%%ort it.RFSURF STIJLT+(6PTE5MTIMIGU

+. System construction. )nce again, #ore reAuire#ents "or an


ob0ect #ay a%%ear at this later stage. 6s you learn, you evolve your ob0ects. The need "or co##unication and interconnection with other ob0ects in the syste# #ay change the needs o" your classes or reAuire new classes. Eor e&a#%le, you #ay discover the need "or "acilitator or hel%er classes, such as a linked list, that contain little or no state in"or#ation and si#%ly hel% other classes "unction.RFSURFSTIJLT+(6PTE5MTIMIIU

,. System e-tension. 6s you add new "eatures to a syste# you #ay


discover that your %revious design doesn t su%%ort easy syste# e&tension. :ith this new in"or#ation, you can restructure %arts o" the syste#, %ossibly adding new classes or class hierarchies. This is also a good ti#e to consider taking "eatures out o" a %ro0ectRFSURF

Cha ter 1! Introduction to Ob>ects

:8

STIJLT+(6PTE5MTIMI2U . In the heat o" the initial design session, you

o"ten end u% with "eatures that are !solutions in search o" a %roble#.$ In E*treme Programming %ractice, the best answer to a "eature that is not absolutely essential to solve the %roble# at hand is !you re not going to need it.$ .. Object reuse. This is the real stress test "or a class. I" so#eone tries
to reuse it in an entirely new situation, they ll %robably discover so#e shortco#ings. 6s you change a class to ada%t to #ore new %rogra#s, the general %rinci%les o" the class will beco#e clearer, until you have a truly reusable ty%e. (owever, don t e&%ect #ost ob0ects "ro# a syste# design to be reusable9it is %er"ectly acce%table "or the bulk o" your ob0ects to be syste#'s%eci"ic. 5eusable ty%es tend to be less co##on, and they #ust solve #ore general %roble#s in order to be reusable.RFSURF STIJLT+(6PTE5MTIM2@U

'uidelines for ob3ect develo.ment


These stages suggest so#e guidelines when thinking about develo%ing your classes=RFSURFSTIJLT+(6PTE5MTIM2MU

(4)

Det a s%eci"ic %roble# generate a class, then let the class grow and #ature during the solution o" other %roble#s. RFSURF STIJLT+(6PTE5MTIM2KU 5e#e#ber, discovering the classes you need *and their inter"aces, is the #a0ority o" the syste# design. I" you already had those classes, this would be an easy %ro0ect. RFSURF STIJLT+(6PTE5MTIM2LU 7on t "orce yoursel" to know everything at the beginning; learn as you go. This will ha%%en anyway. RFSURF STIJLT+(6PTE5MTIM2?U Start %rogra##ing; get so#ething working so you can %rove or dis%rove your design. 7on t "ear that you ll end u% with %rocedural'style s%aghetti code9classes %artition the %roble# and hel% control anarchy and entro%y. Bad classes do not break good classes. RFSURFSTIJLT+(6PTE5MTIM2HU

(5)

(6)

!7)

::

!()

6lways kee% it si#%le. Dittle clean ob0ects with obvious utility are better than big co#%licated inter"aces. :hen decision %oints co#e u%, use an )cca# s 5a1or a%%roach= +onsider the choices and select the one that is si#%lest, because si#%le classes are al#ost always best. Start s#all and si#%le, and you can e&%and the class inter"ace when you understand it better. 6s ti#e goes on, it s di""icult to re#ove ele#ents "ro# a class. RFSURF STIJLT+(6PTE5MTIM23U

hase *: ;uild the core


This is the initial conversion "ro# the rough design into a co#%iling and e&ecuting body o" code that can be tested, and es%ecially that will %rove or dis%rove your architecture. This is not a one'%ass %rocess, but rather the beginning o" a series o" ste%s that will iteratively build the syste#, as you ll see in Phase ?.RFSURFSTIJLT+(6PTE5MTIM2GU /our goal is to "ind the core o" your syste# architecture that needs to be i#%le#ented in order to generate a running syste#, no #atter how inco#%lete that syste# is in this initial %ass. /ou re creating a "ra#ework that you can build on with "urther iterations. /ou re also %er"or#ing the "irst o" #any syste# integrations and tests, and giving the stakeholders "eedback about what their syste# will look like and how it is %rogressing. Ideally, you are also e&%osing so#e o" the critical risks. /ou ll %robably also discover changes and i#%rove#ents that can be #ade to your original architecture9things you would not have learned without i#%le#enting the syste#.RFSURFSTIJLT+(6PTE5MTIM2IU Part o" building the syste# is the reality check that you get "ro# testing against your reAuire#ents analysis and syste# s%eci"ication *in whatever "or# they e&ist,. Make sure that your tests veri"y the reAuire#ents and use cases. :hen the core o" the syste# is stable, you re ready to #ove on and add #ore "unctionality.RFSURFSTIJLT+(6PTE5MTIM22U

hase +: Iterate the use cases


)nce the core "ra#ework is running, each "eature set you add is a s#all %ro0ect in itsel". /ou add a "eature set during an iteration, a reasonably short %eriod o" develo%#ent.RFSURFSTIJLT+(6PTE5MTIK@@U

Cha ter 1! Introduction to Ob>ects

:;

(ow big is an iterationO Ideally, each iteration lasts one to three weeks *this can vary based on the i#%le#entation language,. 6t the end o" that %eriod, you have an integrated, tested syste# with #ore "unctionality than it had be"ore. But what s %articularly interesting is the basis "or the iteration= a single use case. Each use case is a %ackage o" related "unctionality that you build into the syste# all at once, during one iteration. Cot only does this give you a better idea o" what the sco%e o" a use case should be, but it also gives #ore validation to the idea o" a use case, since the conce%t isn t discarded a"ter analysis and design, but instead it is a "unda#ental unit o" develo%#ent throughout the so"tware' building %rocess. RFSURFSTIJLT+(6PTE5MTIK@MU /ou sto% iterating when you achieve target "unctionality or an e&ternal deadline arrives and the custo#er can be satis"ied with the current version. *5e#e#ber, so"tware is a subscri%tion business., Because the %rocess is iterative, you have #any o%%ortunities to shi% a %roduct rather than a single end%oint; o%en'source %ro0ects work e&clusively in an iterative, high'"eedback environ#ent, which is %recisely what #akes the# success"ul.RFSURFSTIJLT+(6PTE5MTIK@KU 6n iterative develo%#ent %rocess is valuable "or #any reasons. /ou can reveal and resolve critical risks early, the custo#ers have a#%le o%%ortunity to change their #inds, %rogra##er satis"action is higher, and the %ro0ect can be steered with #ore %recision. But an additional i#%ortant bene"it is the "eedback to the stakeholders, who can see by the current state o" the %roduct e&actly where everything lies. This #ay reduce or eli#inate the need "or #ind'nu#bing status #eetings and increase the con"idence and su%%ort "ro# the stakeholders.RFSURF STIJLT+(6PTE5MTIK@LU

hase ,: /volution
This is the %oint in the develo%#ent cycle that has traditionally been called !#aintenance,$ a catch'all ter# that can #ean everything "ro# !getting it to work the way it was really su%%osed to in the "irst %lace$ to !adding "eatures that the custo#er "orgot to #ention$ to the #ore traditional !"i&ing the bugs that show u%$ and !adding new "eatures as the need arises.$ So #any #isconce%tions have been a%%lied to the ter# !#aintenance$ that it has taken on a slightly deceiving Auality, %artly

;=

because it suggests that you ve actually built a %ristine %rogra# and all you need to do is change %arts, oil it, and kee% it "ro# rusting. Perha%s there s a better ter# to describe what s going on.RFSURF STIJLT+(6PTE5MTIK@?U I ll use the ter# evolution@. That is, !/ou won t get it right the "irst ti#e, so give yoursel" the latitude to learn and to go back and #ake changes.$ /ou #ight need to #ake a lot o" changes as you learn and understand the %roble# #ore dee%ly. The elegance you ll %roduce i" you evolve until you get it right will %ay o"", both in the short and the long ter#. Evolution is where your %rogra# goes "ro# good to great, and where those issues that you didn t really understand in the "irst %ass beco#e clear. It s also where your classes can evolve "ro# single'%ro0ect usage to reusable resources.RF SURFSTIJLT+(6PTE5MTIK@HU :hat it #eans to !get it right$ isn t 0ust that the %rogra# works according to the reAuire#ents and the use cases. It also #eans that the internal structure o" the code #akes sense to you, and "eels like it "its together well, with no awkward synta&, oversi1ed ob0ects, or ungainly e&%osed bits o" code. In addition, you #ust have so#e sense that the %rogra# structure will survive the changes that it will inevitably go through during its li"eti#e, and that those changes can be #ade easily and cleanly. This is no s#all "eat. /ou #ust not only understand what you re building, but also how the %rogra# will evolve *what I call the vector o$ change,. Eortunately, ob0ect'oriented %rogra##ing languages are %articularly ade%t at su%%orting this kind o" continuing #odi"ication9the boundaries created by the ob0ects are what tend to kee% the structure "ro# breaking down. They also allow you to #ake changes9ones that would see# drastic in a %rocedural %rogra#9without causing earthAuakes throughout your code. In "act, su%%ort "or evolution #ight be the #ost i#%ortant bene"it o" ))P.RFSURFSTIJLT+(6PTE5MTIK@3U :ith evolution, you create so#ething that at least a%%ro&i#ates what you think you re building, and then you kick the tires, co#%are it to your reAuire#ents, and see where it "alls short. Then you can go back and "i& it by redesigning and rei#%le#enting the %ortions o" the %rogra# that
@ 6t least one as%ect o" evolution is covered in Martin Eowler s book -e$actoring! im roving the design o$ e*isting code *6ddison':esley M222,, which uses Java e&a#%les e&clusively.

Cha ter 1! Introduction to Ob>ects

;1

didn t work right @. /ou #ight actually need to solve the %roble#, or an as%ect o" the %roble#, several ti#es be"ore you hit on the right solution. *6 study o" %esign Patterns is usually hel%"ul here. /ou can "ind in"or#ation in Thinking in Patterns ,ith Java, downloadable at ,,,' 0ruceEckel'com.,RFSURFSTIJLT+(6PTE5MTIK@GU Evolution also occurs when you build a syste#, see that it #atches your reAuire#ents, and then discover it wasn t actually what you wanted. :hen you see the syste# in o%eration, you "ind that you really wanted to solve a di""erent %roble#. I" you think this kind o" evolution is going to ha%%en, then you owe it to yoursel" to build your "irst version as Auickly as %ossible so you can "ind out i" it is indeed what you want.RFSURF STIJLT+(6PTE5MTIK@IU Perha%s the #ost i#%ortant thing to re#e#ber is that by de"ault9by de"inition, really9i" you #odi"y a class, its su%er' and subclasses will still "unction. /ou need not "ear #odi"ication *es%ecially i" you have a built'in set o" unit tests to veri"y the correctness o" your #odi"ications,. Modi"ication won t necessarily break the %rogra#, and any change in the outco#e will be li#ited to subclasses andFor s%eci"ic collaborators o" the class you change.RFSURFSTIJLT+(6PTE5MTIK@2U

lans .a: off


)" course you wouldn t build a house without a lot o" care"ully drawn %lans. I" you build a deck or a dog house your %lans won t be so elaborate, but you ll %robably still start with so#e kind o" sketches to guide you on your way. So"tware develo%#ent has gone to e&tre#es. Eor a long ti#e, %eo%le didn t have #uch structure in their develo%#ent, but then big %ro0ects began "ailing. In reaction, we ended u% with #ethodologies that had an inti#idating a#ount o" structure and detail, %ri#arily intended "or those big %ro0ects. These #ethodologies were too scary to use9it looked like you d s%end all your ti#e writing docu#ents and no ti#e %rogra##ing. *This was o"ten the case., I ho%e that what I ve shown you
@ This is so#ething like !ra%id %rototy%ing,$ where you were su%%osed to build a Auick' and'dirty version so that you could learn about the syste#, and then throw away your %rototy%e and build it right. The trouble with ra%id %rototy%ing is that %eo%le didn t throw away the %rototy%e, but instead built u%on it. +o#bined with the lack o" structure in %rocedural %rogra##ing, this o"ten leads to #essy syste#s that are e&%ensive to #aintain.

;2

here suggests a #iddle %ath9a sliding scale. 4se an a%%roach that "its your needs *and your %ersonality,. Co #atter how #ini#al you choose to #ake it, some kind o" %lan will #ake a big i#%rove#ent in your %ro0ect as o%%osed to no %lan at all. 5e#e#ber that, by #ost esti#ates, over H@ %ercent o" %ro0ects "ail *so#e esti#ates go u% to G@ %ercent.,. RFSURF STIJLT+(6PTE5MTIKM@U By "ollowing a %lan9%re"erably one that is si#%le and brie"9and co#ing u% with design structure be"ore coding, you ll discover that things "all together "ar #ore easily than i" you dive in and start hacking. /ou ll also reali1e a great deal o" satis"action. It s #y e&%erience that co#ing u% with an elegant solution is dee%ly satis"ying at an entirely di""erent level; it "eels closer to art than technology. 6nd elegance always %ays o""; it s not a "rivolous %ursuit. Cot only does it give you a %rogra# that s easier to build and debug, but it s also easier to understand and #aintain, and that s where the "inancial value lies.RFSURFSTIJLT+(6PTE5MTIKMMU

/0treme .rogramming
I have studied analysis and design techniAues, on and o"", since I was in graduate school. The conce%t o" E*treme Programming *ZP, is the #ost radical, and delight"ul, that I ve seen. /ou can "ind it chronicled in E*treme Programming E* lained by >ent Beck *6ddison':esley, K@@@, and on the :eb at ,,,'* rogramming'com.RFSURF STIJLT+(6PTE5MTIKMKU ZP is both a %hiloso%hy about %rogra##ing work and a set o" guidelines to do it. So#e o" these guidelines are re"lected in other recent #ethodologies, but the two #ost i#%ortant and distinct contributions, in #y o%inion, are !write tests "irst$ and !%air %rogra##ing.$ 6lthough he argues strongly "or the whole %rocess, Beck %oints out that i" you ado%t only these two %ractices you ll greatly i#%rove your %roductivity and reliability.RFSURFSTIJLT+(6PTE5MTIKMLU

Write tests first


Testing has traditionally been relegated to the last %art o" a %ro0ect, a"ter you ve !gotten everything working, but 0ust to be sure.$ It s i#%licitly had

Cha ter 1! Introduction to Ob>ects

;3

a low %riority, and %eo%le who s%eciali1e in it have not been given a lot o" status and have o"ten even been cordoned o"" in a base#ent, away "ro# the !real %rogra##ers.$ Test tea#s have res%onded in kind, going so "ar as to wear black clothing and cackling with glee whenever they break so#ething *to be honest, I ve had this "eeling #ysel" when breaking co#%ilers,.RFSURFSTIJLT+(6PTE5MTIKM?U ZP co#%letely revolutioni1es the conce%t o" testing by giving it eAual *or even greater, %riority than the code. In "act, you write the tests be$ore you write the code that will be tested, and the tests stay with the code "orever. The tests #ust be e&ecuted success"ully every ti#e you do an integration o" the %ro0ect *which is o"ten, so#eti#es #ore than once a day,.RFSURF STIJLT+(6PTE5MTIKMHU :riting tests "irst has two e&tre#ely i#%ortant e""ects.RFSURF STIJLT+(6PTE5MTIKM3U Eirst, it "orces a clear de"inition o" the inter"ace o" a class. I ve o"ten suggested that %eo%le !i#agine the %er"ect class to solve a %articular %roble#$ as a tool when trying to design the syste#. The ZP testing strategy goes "urther than that9it s%eci"ies e&actly what the class #ust look like, to the consu#er o" that class, and e&actly how the class #ust behave. In no uncertain ter#s. /ou can write all the %rose, or create all the diagra#s you want, describing how a class should behave and what it looks like, but nothing is as real as a set o" tests. The "or#er is a wish list, but the tests are a contract that is en"orced by the co#%iler and the running %rogra#. It s hard to i#agine a #ore concrete descri%tion o" a class than the tests.RFSURFSTIJLT+(6PTE5MTIKMGU :hile creating the tests, you are "orced to co#%letely think out the class and will o"ten discover needed "unctionality that #ight be #issed during the thought e&%eri#ents o" 4MD diagra#s, +5+ cards, use cases, etc. RF SURFSTIJLT+(6PTE5MTIKMIU The second i#%ortant e""ect o" writing the tests "irst co#es "ro# running the tests every ti#e you do a build o" your so"tware. This activity gives you the other hal" o" the testing that s %er"or#ed by the co#%iler. I" you look at the evolution o" %rogra##ing languages "ro# this %ers%ective, you ll see that the real i#%rove#ents in the technology have actually revolved around testing. 6sse#bly language checked only "or synta&, but

;4

+ i#%osed so#e se#antic restrictions, and these %revented you "ro# #aking certain ty%es o" #istakes. ))P languages i#%ose even #ore se#antic restrictions, which i" you think about it are actually "or#s o" testing. !Is this data ty%e being used %ro%erlyO$ and !Is this "unction being called %ro%erlyO$ are the kinds o" tests that are being %er"or#ed by the co#%iler or run'ti#e syste#. :e ve seen the results o" having these tests built into the language= %eo%le have been able to write #ore co#%le& syste#s, and get the# to work, with #uch less ti#e and e""ort. I ve %u11led over why this is, but now I reali1e it s the tests= you do so#ething wrong, and the sa"ety net o" the built'in tests tells you there s a %roble# and %oints you to where it is. RFSURFSTIJLT+(6PTE5MTIKM2U But the built'in testing a""orded by the design o" the language can only go so "ar. 6t so#e %oint, )ou #ust ste% in and add the rest o" the tests that %roduce a "ull suite *in coo%eration with the co#%iler and run'ti#e syste#, that veri"ies all o" your %rogra#. 6nd, 0ust like having a co#%iler watching over your shoulder, wouldn t you want these tests hel%ing you right "ro# the beginningO That s why you write the# "irst, and run the# auto#atically with every build o" your syste#. /our tests beco#e an e&tension o" the sa"ety net %rovided by the language. RFSURF STIJLT+(6PTE5MTIKK@U )ne o" the things that I ve discovered about the use o" #ore and #ore %ower"ul %rogra##ing languages is that I a# e#boldened to try #ore bra1en e&%eri#ents, because I know that the language will kee% #e "ro# wasting #y ti#e chasing bugs. The ZP test sche#e does the sa#e thing "or your entire %ro0ect. Because you know your tests will always catch any %roble#s that you introduce *and you regularly add any new tests as you think o" the#,, you can #ake big changes when you need to without worrying that you ll throw the whole %ro0ect into co#%lete disarray. This is incredibly %ower"ul. RFSURFSTIJLT+(6PTE5MTIKKMU

air .rogramming
Pair %rogra##ing goes against the rugged individualis# that we ve been indoctrinated into "ro# the beginning, through school *where we succeed or "ail on our own, and working with our neighbors is considered !cheating$,, and #edia, es%ecially (ollywood #ovies in which the hero is

Cha ter 1! Introduction to Ob>ects

;5

usually "ighting against #indless con"or#ity @. Progra##ers, too, are considered %aragons o" individuality9!cowboy coders$ as Darry +onstantine likes to say. 6nd yet ZP, which is itsel" battling against conventional thinking, says that code should be written with two %eo%le %er workstation. 6nd that this should be done in an area with a grou% o" workstations, without the barriers that the "acilities'design %eo%le are so "ond o". In "act, Beck says that the "irst task o" converting to ZP is to arrive with screwdrivers and 6llen wrenches and take a%art everything that gets in the way. @ *This will reAuire a #anager who can de"lect the ire o" the "acilities de%art#ent., RFSURFSTIJLT+(6PTE5MTIKKKU The value o" %air %rogra##ing is that one %erson is actually doing the coding while the other is thinking about it. The thinker kee%s the big %icture in #ind9not only the %icture o" the %roble# at hand, but the guidelines o" ZP. I" two %eo%le are working, it s less likely that one o" the# will get away with saying, !I don t want to write the tests "irst,$ "or e&a#%le. 6nd i" the coder gets stuck, they can swa% %laces. I" both o" the# get stuck, their #usings #ay be overheard by so#eone else in the work area who can contribute. :orking in %airs kee%s things "lowing and on track. Probably #ore i#%ortant, it #akes %rogra##ing a lot #ore social and "un. RFSURFSTIJLT+(6PTE5MTIKKLU I ve begun using %air %rogra##ing during the e&ercise %eriods in so#e o" #y se#inars and it see#s to signi"icantly i#%rove everyone s e&%erience. RFSURFSTIJLT+(6PTE5MTIKK?U

Wh: "ava succeeds


The reason Java has been so success"ul is that the goal was to solve #any o" the %roble#s "acing develo%ers today. The goal o" Java is i#%roved %roductivity. This %roductivity co#es in #any ways, but the language is
@ 6lthough this #ay be a #ore 6#erican %ers%ective, the stories o" (ollywood reach everywhere. @ Including *es%ecially, the P6 syste#. I once worked in a co#%any that insisted on broadcasting every %hone call that arrived "or every e&ecutive, and it constantly interru%ted our %roductivity *but the #anagers couldn t begin to conceive o" sti"ling such an i#%ortant service as the P6,. Einally, when no one was looking I started sni%%ing s%eaker wires.

;7

designed to aid you as #uch as %ossible, while hindering you as little as %ossible with arbitrary rules or any reAuire#ent that you use a %articular set o" "eatures. Java is designed to be %ractical; Java language design decisions were based on %roviding the #a&i#u# bene"its to the %rogra##er. RFSURFSTIJLT+(6PTE5MTIKKHU

1:stems are easier to e0.ress and understand


+lasses designed to "it the %roble# tend to e&%ress it better. This #eans that when you write the code, you re describing your solution in the ter#s o" the %roble# s%ace *!Put the gro##et in the bin$, rather than the ter#s o" the co#%uter, which is the solution s%ace *!Set the bit in the chi% that #eans that the relay will close$,. /ou deal with higher'level conce%ts and can do #uch #ore with a single line o" code. RFSURF STIJLT+(6PTE5MTIKK3U The other bene"it o" this ease o" e&%ression is #aintenance, which *i" re%orts can be believed, takes a huge %ortion o" the cost over a %rogra# s li"eti#e. I" a %rogra# is easier to understand, then it s easier to #aintain. This can also reduce the cost o" creating and #aintaining the docu#entation. RFSURFSTIJLT+(6PTE5MTIKKGU

Ma0imal leverage with libraries


The "astest way to create a %rogra# is to use code that s already written= a library. 6 #a0or goal in Java is to #ake library use easier. This is acco#%lished by casting libraries into new data ty%es *classes,, so that bringing in a library #eans adding new ty%es to the language. Because the Java co#%iler takes care o" how the library is used9guaranteeing %ro%er initiali1ation and cleanu%, and ensuring that "unctions are called %ro%erly 9you can "ocus on what you want the library to do, not how you have to do it. RFSURFSTIJLT+(6PTE5MTIKKIU

/rror handling
Error handling in + is a notorious %roble#, and one that is o"ten ignored 9"inger'crossing is usually involved. I" you re building a large, co#%le&

Cha ter 1! Introduction to Ob>ects

;8

%rogra#, there s nothing worse than having an error buried so#ewhere with no clue as to where it ca#e "ro#. Java e*ce tion handling is a way to guarantee that an error is noticed, and that so#ething ha%%ens as a result. RFSURFSTIJLT+(6PTE5MTIKK2U

rogramming in the large


Many traditional languages have built'in li#itations to %rogra# si1e and co#%le&ity. B6SI+, "or e&a#%le, can be great "or %ulling together Auick solutions "or certain classes o" %roble#s, but i" the %rogra# gets #ore than a "ew %ages long, or ventures out o" the nor#al %roble# do#ain o" that language, it s like trying to swi# through an ever'#ore viscous "luid. There s no clear line that tells you when your language is "ailing you, and even i" there were, you d ignore it. /ou don t say, !My B6SI+ %rogra# 0ust got too big; I ll have to rewrite it in +.$ Instead, you try to shoehorn a "ew #ore lines in to add that one new "eature. So the e&tra costs co#e cree%ing u% on you. RFSURFSTIJLT+(6PTE5MTIKL@U Java is designed to aid rogramming in the large9that is, to erase those cree%ing'co#%le&ity boundaries between a s#all %rogra# and a large one. /ou certainly don t need to use ))P when you re writing a !hello world$ style utility %rogra#, but the "eatures are there when you need the#. 6nd the co#%iler is aggressive about "erreting out bug'%roducing errors "or s#all and large %rogra#s alike. RFSURF STIJLT+(6PTE5MTIKLMU

1trategies for transition


I" you buy into ))P, your ne&t Auestion is %robably, !(ow can I get #y #anagerFcolleaguesFde%art#entF%eers to start using ob0ectsO$ Think about how you9one inde%endent %rogra##er9would go about learning to use a new language and a new %rogra##ing %aradig#. /ou ve done it be"ore. Eirst co#es education and e&a#%les; then co#es a trial %ro0ect to give you a "eel "or the basics without doing anything too con"using. Then co#es a !real world$ %ro0ect that actually does so#ething use"ul. Throughout your "irst %ro0ects you continue your education by reading, asking Auestions o" e&%erts, and trading hints with "riends. This is the a%%roach #any e&%erienced %rogra##ers suggest "or the switch to Java.

;:

Switching an entire co#%any will o" course introduce certain grou% dyna#ics, but it will hel% at each ste% to re#e#ber how one %erson would do it. RFSURFSTIJLT+(6PTE5MTIKLKU

'uidelines
(ere are so#e guidelines to consider when #aking the transition to ))P and Java= RFSURFSTIJLT+(6PTE5MTIKLLU

() #raining
The "irst ste% is so#e "or# o" education. 5e#e#ber the co#%any s invest#ent in code, and try not to throw everything into disarray "or si& to nine #onths while everyone %u11les over how inter"aces work. Pick a s#all grou% "or indoctrination, %re"erably one co#%osed o" %eo%le who are curious, work well together, and can "unction as their own su%%ort network while they re learning Java. 6n alternative a%%roach that is so#eti#es suggested is the education o" all co#%any levels at once, including overview courses "or strategic #anagers as well as design and %rogra##ing courses "or %ro0ect builders. This is es%ecially good "or s#aller co#%anies #aking "unda#ental shi"ts in the way they do things, or at the division level o" larger co#%anies. Because the cost is higher, however, so#e #ay choose to start with %ro0ect'level training, do a %ilot %ro0ect *%ossibly with an outside #entor,, and let the %ro0ect tea# beco#e the teachers "or the rest o" the co#%any. RFSURFSTIJLT+(6PTE5MTIKL?U

!) &ow@risk .ro3ect
Try a low'risk %ro0ect "irst and allow "or #istakes. )nce you ve gained so#e e&%erience, you can either seed other %ro0ects "ro# #e#bers o" this "irst tea# or use the tea# #e#bers as an ))P technical su%%ort sta"". This "irst %ro0ect #ay not work right the "irst ti#e, so it should not be #ission'critical "or the co#%any. It should be si#%le, sel"'contained, and instructive; this #eans that it should involve creating classes that will be #eaning"ul to the other %rogra##ers in the co#%any when they get their turn to learn Java. RFSURFSTIJLT+(6PTE5MTIKLHU

Cha ter 1! Introduction to Ob>ects

;;

*) Model from success


Seek out e&a#%les o" good ob0ect'oriented design be"ore starting "ro# scratch. There s a good %robability that so#eone has solved your %roble# already, and i" they haven t solved it e&actly you can %robably a%%ly what you ve learned about abstraction to #odi"y an e&isting design to "it your needs. This is the general conce%t o" design atternsD covered in Thinking in Patterns ,ith Java, downloadable at ,,,'0ruceEckel'com. RFSURF STIJLT+(6PTE5MTIKL3U

+) Cse e0isting class libraries


The %ri#ary econo#ic #otivation "or switching to ))P is the easy use o" e&isting code in the "or# o" class libraries *in %articular, the Standard Java libraries, which are covered throughout this book,. The shortest a%%lication develo%#ent cycle will result when you can create and use ob0ects "ro# o""'the'shel" libraries. (owever, so#e new %rogra##ers don t understand this, are unaware o" e&isting class libraries, or, through "ascination with the language, desire to write classes that #ay already e&ist. /our success with ))P and Java will be o%ti#i1ed i" you #ake an e""ort to seek out and reuse other %eo%le s code early in the transition %rocess. RFSURFSTIJLT+(6PTE5MTIKLGU

,) Dont rewrite e0isting code in "ava


It is not usually the best use o" your ti#e to take e&isting, "unctional code and rewrite it in Java. *I" you #ust turn it into ob0ects, you can inter"ace to the + or +<< code using the Java Cative Inter"ace, described in 6%%endi& B., There are incre#ental bene"its, es%ecially i" the code is slated "or reuse. But chances are you aren t going to see the dra#atic increases in %roductivity that you ho%e "or in your "irst "ew %ro0ects unless that %ro0ect is a new one. Java and ))P shine best when taking a %ro0ect "ro# conce%t to reality. RFSURFSTIJLT+(6PTE5MTIKLIU

Management obstacles
I" you re a #anager, your 0ob is to acAuire resources "or your tea#, to overco#e barriers to your tea# s success, and in general to try to %rovide the #ost %roductive and en0oyable environ#ent so your tea# is #ost likely to %er"or# those #iracles that are always being asked o" you.

1==

Moving to Java "alls in all three o" these categories, and it would be wonder"ul i" it didn t cost you anything as well. 6lthough #oving to Java #ay be chea%er9de%ending on your constraints9than the ))P alternatives "or a tea# o" + %rogra##ers *and %robably "or %rogra##ers in other %rocedural languages,, it isn t "ree, and there are obstacles you should be aware o" be"ore trying to sell the #ove to Java within your co#%any and e#barking on the #ove itsel". RFSURF STIJLT+(6PTE5MTIKL2U

1tartu. costs
The cost o" #oving to Java is #ore than 0ust the acAuisition o" Java co#%ilers *the Sun Java co#%iler is "ree, so this is hardly an obstacle,. /our #ediu#' and long'ter# costs will be #ini#i1ed i" you invest in training *and %ossibly #entoring "or your "irst %ro0ect, and also i" you identi"y and %urchase class libraries that solve your %roble# rather than trying to build those libraries yoursel". These are hard'#oney costs that #ust be "actored into a realistic %ro%osal. In addition, there are the hidden costs in loss o" %roductivity while learning a new language and %ossibly a new %rogra##ing environ#ent. Training and #entoring can certainly #ini#i1e these, but tea# #e#bers #ust overco#e their own struggles to understand the new technology. 7uring this %rocess they will #ake #ore #istakes *this is a "eature, because acknowledged #istakes are the "astest %ath to learning, and be less %roductive. Even then, with so#e ty%es o" %rogra##ing %roble#s, the right classes, and the right develo%#ent environ#ent, it s %ossible to be #ore %roductive while you re learning Java *even considering that you re #aking #ore #istakes and writing "ewer lines o" code %er day, than i" you d stayed with +. RF SURFSTIJLT+(6PTE5MTIK?@U

erformance issues
6 co##on Auestion is, !7oesn t ))P auto#atically #ake #y %rogra#s a lot bigger and slowerO$ The answer is, !It de%ends.$ The e&tra sa"ety "eatures in Java have traditionally e&tracted a %er"or#ance %enalty over a language like +<<. Technologies such as !hots%ot$ and co#%ilation technologies have i#%roved the s%eed signi"icantly in #ost cases, and e""orts continue toward higher %er"or#ance. RFSURF STIJLT+(6PTE5MTIK?MU

Cha ter 1! Introduction to Ob>ects

1=1

:hen your "ocus is on ra%id %rototy%ing, you can throw together co#%onents as "ast as %ossible while ignoring e""iciency issues. I" you re using any third'%arty libraries, these are usually already o%ti#i1ed by their vendors; in any case it s not an issue while you re in ra%id' develo%#ent #ode. :hen you have a syste# that you like, i" it s s#all and "ast enough, then you re done. I" not, you begin tuning with a %ro"iling tool, looking "irst "or s%eedu%s that can be done by rewriting s#all %ortions o" code. I" that doesn t hel%, you look "or #odi"ications that can be #ade in the underlying i#%le#entation so no code that uses a %articular class needs to be changed. )nly i" nothing else solves the %roble# do you need to change the design. The "act that %er"or#ance is so critical in that %ortion o" the design is an indicator that it #ust be %art o" the %ri#ary design criteria. /ou have the bene"it o" "inding this out early using ra%id develo%#ent. I" you "ind a "unction that is a %articular bottleneck, you can rewrite it in +F+<< using Java s native methods, the sub0ect o" 6%%endi& B. RFSURF STIJLT+(6PTE5MTIK?KU

Common design errors


:hen starting your tea# into ))P and Java, %rogra##ers will ty%ically go through a series o" co##on design errors. This o"ten ha%%ens due to insu""icient "eedback "ro# e&%erts during the design and i#%le#entation o" early %ro0ects, because no e&%erts have been develo%ed within the co#%any, and because there #ay be resistance to retaining consultants. It s easy to "eel that you understand ))P too early in the cycle and go o"" on a bad tangent. So#ething that s obvious to so#eone e&%erienced with the language #ay be a sub0ect o" great internal debate "or a novice. Much o" this trau#a can be ski%%ed by using an e&%erienced outside e&%ert "or training and #entoring. RFSURFSTIJLT+(6PTE5MTIK?LU

"ava vs) CFFA


Java looks a lot like +<<, and so naturally it would see# that +<< will be re%laced by Java. But I # starting to Auestion this logic. Eor one thing, +<< still has so#e "eatures that Java doesn t, and although there have been a lot o" %ro#ises about Java so#eday being as "ast or "aster than

1=2

+<<, we ve seen steady i#%rove#ents but no dra#atic breakthroughs. 6lso, there see#s to be a continuing interest in +<<, so I don t think that language is going away any ti#e soon. *Danguages see# to hang around. S%eaking at one o" #y !Inter#ediateF6dvanced Java Se#inars,$ 6llen (olub asserted that the two #ost co##only used languages are 5e&& and +)B)D, in that order., RFSURFSTIJLT+(6PTE5MTIK??U I # beginning to think that the strength o" Java lies in a slightly di""erent arena than that o" +<<. +<< is a language that doesn t try to "it a #old. +ertainly it has been ada%ted in a nu#ber o" ways to solve %articular %roble#s. So#e +<< tools co#bine libraries, co#%onent #odels, and code'generation tools to solve the %roble# o" develo%ing windowed end' user a%%lications *"or Microso"t :indows,. 6nd yet, what do the vast #a0ority o" :indows develo%ers useO Microso"t s Visual Basic *VB,. This des%ite the "act that VB %roduces the kind o" code that beco#es un#anageable when the %rogra# is only a "ew %ages long *and synta& that can be %ositively #ysti"ying,. 6s success"ul and %o%ular as VB is, it s not a very good e&a#%le o" language design. It would be nice to have the ease and %ower o" VB without the resulting un#anageable code. 6nd that s where I think Java will shine= as the !ne&t VB.$ /ou #ay or #ay not shudder to hear this, but think about it= so #uch o" Java is intended to #ake it easy "or the %rogra##er to solve a%%lication'level %roble#s like networking and cross'%lat"or# 4I, and yet it has a language design that allows the creation o" very large and "le&ible bodies o" code. 6dd to this the "act that Java has the #ost robust ty%e checking and error handling syste#s I ve ever seen in a language and you have the #akings o" a signi"icant lea% "orward in %rogra##ing %roductivity. RFSURF STIJLT+(6PTE5MTIK?HU Should you use Java instead o" +<< "or your %ro0ectO )ther than :eb a%%lets, there are two issues to consider. Eirst, i" you want to use a lot o" e&isting +<< libraries *and you ll certainly get a lot o" %roductivity gains there,, or i" you have an e&isting + or +<< code base, Java #ight slow your develo%#ent down rather than s%eeding it u%. RFSURF STIJLT+(6PTE5MTIK?3U I" you re develo%ing all your code %ri#arily "ro# scratch, then the si#%licity o" Java over +<< will signi"icantly shorten your develo%#ent ti#e9the anecdotal evidence *stories "ro# +<< tea#s that I ve talked to

Cha ter 1! Introduction to Ob>ects

1=3

who have switched to Java, suggests a doubling o" develo%#ent s%eed over +<<. I" Java %er"or#ance doesn t #atter or you can so#ehow co#%ensate "or it, sheer ti#e'to'#arket issues #ake it di""icult to choose +<< over Java. RFSURFSTIJLT+(6PTE5MTIK?GU The biggest issue is %er"or#ance. Inter%reted Java has been slow, even K@ to H@ ti#es slower than + in the original Java inter%reters. This has i#%roved greatly over ti#e, but it will still re#ain an i#%ortant nu#ber. +o#%uters are about s%eed; i" it wasn t signi"icantly "aster to do so#ething on a co#%uter then you d do it by hand. *I ve even heard it suggested that you start with Java, to gain the short develo%#ent ti#e, then use a tool and su%%ort libraries to translate your code to +<<, i" you need "aster e&ecution s%eed., RFSURFSTIJLT+(6PTE5MTIK?IU The key to #aking Java "easible "or #ost develo%#ent %ro0ects is the a%%earance o" s%eed i#%rove#ents like so'called !0ust'in ti#e$ *JIT, co#%ilers, Sun s own !hots%ot$ technology, and even native code co#%ilers. )" course, native code co#%ilers will eli#inate the touted cross'%lat"or# e&ecution o" the co#%iled %rogra#s, but they will also bring the s%eed o" the e&ecutable closer to that o" + and +<<. 6nd cross' co#%iling a %rogra# in Java should be a lot easier than doing so in + or +<<. *In theory, you 0ust reco#%ile, but that %ro#ise has been #ade be"ore "or other languages., RFSURFSTIJLT+(6PTE5MTIK?2U /ou can "ind co#%arisons o" Java and +<< and observations about Java realities in the a%%endices o" the "irst edition o" this book *6vailable on this book s acco#%anying +7 5)M, as well as at ,,,'0ruceEckel'comA. RFSURFSTIJLT+(6PTE5MTIKH@U

1ummar:
This cha%ter atte#%ts to give you a "eel "or the broad issues o" ob0ect' oriented %rogra##ing and Java, including why ))P is di""erent, and why Java in %articular is di""erent, conce%ts o" ))P #ethodologies, and "inally the kinds o" issues you will encounter when #oving your own co#%any to ))P and Java. RFSURFSTIJLT+(6PTE5MTIKHMU ))P and Java #ay not be "or everyone. It s i#%ortant to evaluate your own needs and decide whether Java will o%ti#ally satis"y those needs, or

1=4

i" you #ight be better o"" with another %rogra##ing syste# *including the one you re currently using,. I" you know that your needs will be very s%eciali1ed "or the "oreseeable "uture and i" you have s%eci"ic constraints that #ay not be satis"ied by Java, then you owe it to yoursel" to investigate the alternatives @. Even i" you eventually choose Java as your language, you ll at least understand what the o%tions were and have a clear vision o" why you took that direction. RFSURF STIJLT+(6PTE5MTIKHKU /ou know what a %rocedural %rogra# looks like= data de"initions and "unction calls. To "ind the #eaning o" such a %rogra# you have to work a little, looking through the "unction calls and low'level conce%ts to create a #odel in your #ind. This is the reason we need inter#ediate re%resentations when designing %rocedural %rogra#s9by the#selves, these %rogra#s tend to be con"using because the ter#s o" e&%ression are oriented #ore toward the co#%uter than to the %roble# you re solving. RFSURFSTIJLT+(6PTE5MTIKHLU Because Java adds #any new conce%ts on to% o" what you "ind in a %rocedural language, your natural assu#%tion #ay be that the mainA B in a Java %rogra# will be "ar #ore co#%licated than "or the eAuivalent + %rogra#. (ere, you ll be %leasantly sur%rised= 6 well'written Java %rogra# is generally "ar si#%ler and #uch easier to understand than the eAuivalent + %rogra#. :hat you ll see are the de"initions o" the ob0ects that re%resent conce%ts in your %roble# s%ace *rather than the issues o" the co#%uter re%resentation, and #essages sent to those ob0ects to re%resent the activities in that s%ace. )ne o" the delights o" ob0ect' oriented %rogra##ing is that, with a well'designed %rogra#, it s easy to understand the code by reading it. 4sually there s a lot less code as well, because #any o" your %roble#s will be solved by reusing e&isting library code. RFSU

@ In %articular, I reco##end looking at Python *htt%=FFwww.Python.org,.

Cha ter 1! Introduction to Ob>ects

1=5

!: /ver:thing is an Ob3ect
RFSTIJLT+(6PTE5KTI@U6lthough it is based on +<<, Java is #ore o" a !%ure$ ob0ect'oriented language.
Both +<< and Java are hybrid languages, but in Java the designers "elt that the hybridi1ation was not as i#%ortant as it was in +<<. 6 hybrid language allows #ulti%le %rogra##ing styles; the reason +<< is hybrid is to su%%ort backward co#%atibility with the + language. Because +<< is a su%erset o" the + language, it includes #any o" that language s undesirable "eatures, which can #ake so#e as%ects o" +<< overly co#%licated. RFSURFSTIJLT+(6PTE5KTIMU The Java language assu#es that you want to do only ob0ect'oriented %rogra##ing. This #eans that be"ore you can begin you #ust shi"t your #indset into an ob0ect'oriented world *unless it s already there, ' The bene"it o" this initial e""ort is the ability to %rogra# in a language that is si#%ler to learn and to use than #any other ))P languages. In this cha%ter we ll see the basic co#%onents o" a Java %rogra# and we ll learn that everything in Java is an ob0ect, even a Java %rogra#. RFSURF STIJLT+(6PTE5KTIKU

Gou mani.ulate ob3ects with references


Each %rogra##ing language has its own #eans o" #ani%ulating data. So#eti#es the %rogra##er #ust be constantly aware o" what ty%e o" #ani%ulation is going on. 6re you #ani%ulating the ob0ect directly, or are you dealing with so#e kind o" indirect re%resentation *a %ointer in + or

1=7

+<<, that #ust be treated with a s%ecial synta&O RFSURF STIJLT+(6PTE5KTILU 6ll this is si#%li"ied in Java. /ou treat everything as an ob0ect, so there is a single consistent synta& that you use everywhere. 6lthough you treat everything as an ob0ect, the identi"ier you #ani%ulate is actually a !re"erence$ to an ob0ect @. /ou #ight i#agine this scene as a television *the ob0ect, with your re#ote control *the re"erence,. 6s long as you re holding this re"erence, you have a connection to the television, but when so#eone says !change the channel$ or !lower the volu#e,$ what you re #ani%ulating is the re"erence, which in turn #odi"ies the ob0ect. I" you want to #ove around the roo# and still control the television, you take the re#oteFre"erence with you, not the television. RFSURF STIJLT+(6PTE5KTI?U 6lso, the re#ote control can stand on its own, with no television. That is, 0ust because you have a re"erence doesn t #ean there s necessarily an ob0ect connected to it. So i" you want to hold a word or sentence, you create a )tring re"erence= F/GHF/GTIJ3IC."PTE-2II5H

%tring s<
But here you ve created onl) the re"erence, not an ob0ect. I" you decided to send a #essage to s at this %oint, you ll get an error *at run'ti#e, because s isn t actually attached to anything *there s no television,. 6 sa"er %ractice, then, is always to initiali1e a re"erence when you create it= RFSURFSTIJLT+(6PTE5KTI3U
@ This can be a "lash%oint. There are those who say !clearly, it s a %ointer,$ but this %resu#es an underlying i#%le#entation. 6lso, Java re"erences are #uch #ore akin to +<< re"erences than %ointers in their synta&. In the "irst edition o" this book, I chose to invent a new ter#, !handle,$ because +<< re"erences and Java re"erences have so#e i#%ortant di""erences. I was co#ing out o" +<< and did not want to con"use the +<< %rogra##ers who# I assu#ed would be the largest audience "or Java. In the Knd edition, I decided that !re"erence$ was the #ore co##only used ter#, and that anyone changing "ro# +<< would have a lot #ore to co%e with than the ter#inology o" re"erences, so they #ight as well 0u#% in with both "eet. (owever, there are %eo%le who disagree even with the ter# !re"erence.$ I read in one book where it was !co#%letely wrong to say that Java su%%orts %ass by re"erence,$ because Java ob0ect identi"iers *according to that author, are actuall) !ob0ect re"erences.$ 6nd *he goes on, everything is actuall) %ass by value. So you re not %assing by re"erence, you re !%assing an ob0ect re"erence by value.$ )ne could argue "or the %recision o" such convoluted e&%lanations, but I think #y a%%roach si#%li"ies the understanding o" the conce%t without hurting anything *well, the language lawyers #ay clai# that I # lying to you, but I ll say that I # %roviding an a%%ro%riate abstraction.,

Cha ter 2! Ever)thing is an Ob>ect

1=8

%tring s ? 8as!f8<
(owever, this uses a s%ecial Java "eature= strings can be initiali1ed with Auoted te&t. Cor#ally, you #ust use a #ore general ty%e o" initiali1ation "or ob0ects. F/GHF/GTIJ3IC."PTE-2II8H

Gou must create all the ob3ects


:hen you create a re"erence, you want to connect it with a new ob0ect. /ou do so, in general, with the ne( keyword. ne( says, !Make #e a new one o" these ob0ects.$ So in the above e&a#%le, you can say= RFSURF STIJLT+(6PTE5KTIIU

%tring s ? ne: %tring-8as!f8.<


Cot only does this #ean !Make #e a new )tring,$ but it also gives in"or#ation about ho, to #ake the )tring by su%%lying an initial character string. RFSURFSTIJLT+(6PTE5KTI2U )" course, )tring is not the only ty%e that e&ists. Java co#es with a %lethora o" ready'#ade ty%es. :hat s #ore i#%ortant is that you can create your own ty%es. In "act, that s the "unda#ental activity in Java %rogra##ing, and it s what you ll be learning about in the rest o" this book. RFSURFSTIJLT+(6PTE5KTIM@U

Where storage lives


It s use"ul to visuali1e so#e as%ects o" how things are laid out while the %rogra# is running, in %articular how #e#ory is arranged. There are si& di""erent %laces to store data= RFSURFSTIJLT+(6PTE5KTIMMU

!!)

$egisters. This is the "astest storage because it e&ists in a %lace


di""erent "ro# that o" other storage= inside the %rocessor. (owever, the nu#ber o" registers is severely li#ited, so registers are allocated by the co#%iler according to its needs. /ou don t have direct control, nor do you see any evidence in your %rogra#s that registers even e&ist. RFSURFSTIJLT+(6PTE5KTIMKU

1=:

!*)

The stack. This lives in the general 56M *rando#'access


#e#ory, area, but has direct su%%ort "ro# the %rocessor via its stack ointer. The stack %ointer is #oved down to create new #e#ory and #oved u% to release that #e#ory. This is an e&tre#ely "ast and e""icient way to allocate storage, second only to registers. The Java co#%iler #ust know, while it is creating the %rogra#, the e&act si1e and li"eti#e o" all the data that is stored on the stack, because it #ust generate the code to #ove the stack %ointer u% and down. This constraint %laces li#its on the "le&ibility o" your %rogra#s, so while so#e Java storage e&ists on the stack9 in %articular, ob0ect re"erences9Java ob0ects the#selves are not %laced on the stack. RFSURFSTIJLT+(6PTE5KTIMLU

!+)

The heap. This is a general'%ur%ose %ool o" #e#ory *also in the


56M area, where all Java ob0ects live. The nice thing about the hea% is that, unlike the stack, the co#%iler doesn t need to know how #uch storage it needs to allocate "ro# the hea% or how long that storage #ust stay on the hea%. Thus, there s a great deal o" "le&ibility in using storage on the hea%. :henever you need to create an ob0ect, you si#%ly write the code to create it using ne(, and the storage is allocated on the hea% when that code is e&ecuted. )" course there s a %rice you %ay "or this "le&ibility= it takes #ore ti#e to allocate hea% storage than it does to allocate stack storage *that is, i" you even could create ob0ects on the stack in Java, as you can in +<<,. RFSURFSTIJLT+(6PTE5KTIM?U

!,)

)tatic storage. !Static$ is used here in the sense o" !in a "i&ed
location$ *although it s also in 56M,. Static storage contains data that is available "or the entire ti#e a %rogra# is running. /ou can use the static keyword to s%eci"y that a %articular ele#ent o" an ob0ect is static, but Java ob0ects the#selves are never %laced in static storage. RFSURFSTIJLT+(6PTE5KTIMHU

!-)

-onstant storage. +onstant values are o"ten %laced directly in


the %rogra# code, which is sa"e since they can never change. So#eti#es constants are cordoned o"" by the#selves so that they can be o%tionally %laced in read'only #e#ory *5)M,. RFSURF STIJLT+(6PTE5KTIM3U

Cha ter 2! Ever)thing is an Ob>ect

1=;

!4)

/on6$A1 storage. I" data lives co#%letely outside a %rogra# it


can e&ist while the %rogra# is not running, outside the control o" the %rogra#. The two %ri#ary e&a#%les o" this are streamed ob>ectsD in which ob0ects are turned into strea#s o" bytes, generally to be sent to another #achine, and ersistent ob>ectsD in which the ob0ects are %laced on disk so they will hold their state even when the %rogra# is ter#inated. The trick with these ty%es o" storage is turning the ob0ects into so#ething that can e&ist on the other #ediu#, and yet can be resurrected into a regular 56M'based ob0ect when necessary. Java %rovides su%%ort "or light,eight ersistence, and "uture versions o" Java #ight %rovide #ore co#%lete solutions "or %ersistence. RFSURF STIJLT+(6PTE5KTIMGU

1.ecial case: .rimitive t:.es


There is a grou% o" ty%es that gets s%ecial treat#ent; you can think o" these as !%ri#itive$ ty%es that you use Auite o"ten in your %rogra##ing. The reason "or the s%ecial treat#ent is that to create an ob0ect with ne( 9es%ecially a s#all, si#%le variable9isn t very e""icient because ne( %laces ob0ects on the hea%. Eor these ty%es Java "alls back on the a%%roach taken by + and +<<. That is, instead o" creating the variable using ne(, an !auto#atic$ variable is created that is not a re$erence. The variable holds the value, and it s %laced on the stack so it s #uch #ore e""icient. RFSURFSTIJLT+(6PTE5KTIMIU Java deter#ines the si1e o" each %ri#itive ty%e. These si1es don t change "ro# one #achine architecture to another as they do in #ost languages. This si1e invariance is one reason Java %rogra#s are so %ortable. RFSURF STIJLT+(6PTE5KTIM2U

#rimiti ve type boolean char byte

)i7 e
9 M3' bit I' bit

1inim* m
9 4nicode @ 'MKI

1a4im*m
9 4nicode K M3' M <MKG

0rapper type 2oolean -haracte r 2yte

11=

#rimiti ve type short int long float 'o*ble voi'

)i7 e
M3' bit LK' bit 3?' bit LK' bit 3?' bit 9

1inim* m
'K MH 'K LM 'K 3L IEEEGH? IEEEGH? 9

1a4im*m
<K MH9M <K LM9M <K 3L9M IEEEGH? IEEEGH? 9

0rapper type )hort Integer +ong Float o*ble Voi'

6ll nu#eric ty%es are signed, so don t go looking "or unsigned ty%es. RF SURFSTIJLT+(6PTE5KTIK@U The si1e o" the boolean ty%e is not e&%licitly de"ined; it is only s%eci"ied to be able to take the literal values tr*e or false. The %ri#itive data ty%es also have !wra%%er$ classes "or the#. That #eans that i" you want to #ake a non%ri#itive ob0ect on the hea% to re%resent that %ri#itive ty%e, you use the associated wra%%er. Eor e&a#%le= RFSURFSTIJLT+(6PTE5KTIKMU

char c ? 262< Character C ? ne: Character-c.<


)r you could also use=

Character C ? ne: Character-262.<


The reasons "or doing this will be shown in a later cha%ter. RFSURF STIJLT+(6PTE5KTIKKU

>igh@.recision numbers
Java includes two classes "or %er"or#ing high'%recision arith#etic=

2igInteger and 2ig ecimal. 6lthough these a%%ro&i#ately "it into the
sa#e category as the !wra%%er$ classes, neither one has a %ri#itive analogue. RFSURFSTIJLT+(6PTE5KTIKLU

Cha ter 2! Ever)thing is an Ob>ect

111

Both classes have #ethods that %rovide analogues "or the o%erations that you %er"or# on %ri#itive ty%es. That is, you can do anything with a 2igInteger or 2ig ecimal that you can with an int or float, it s 0ust that you #ust use #ethod calls instead o" o%erators. 6lso, since there s #ore involved, the o%erations will be slower. /ou re e&changing s%eed "or accuracy. RFSURFSTIJLT+(6PTE5KTIK?U

2igInteger su%%orts arbitrary'%recision integers. This #eans that you can accurately re%resent integral values o" any si1e without losing any in"or#ation during o%erations. RFSURFSTIJLT+(6PTE5KTIKHU 2ig ecimal is "or arbitrary'%recision "i&ed'%oint nu#bers; you can use these "or accurate #onetary calculations, "or e&a#%le. RFSURF STIJLT+(6PTE5KTIK3U
+onsult your online docu#entation "or details about the constructors and #ethods you can call "or these two classes. RFSURF STIJLT+(6PTE5KTIKGU

Arra:s in "ava
Virtually all %rogra##ing languages su%%ort arrays. 4sing arrays in + and +<< is %erilous because those arrays are only blocks o" #e#ory. I" a %rogra# accesses the array outside o" its #e#ory block or uses the #e#ory be"ore initiali1ation *co##on %rogra##ing errors, there will be un%redictable results. RFSURFSTIJLT+(6PTE5KTIKIU )ne o" the %ri#ary goals o" Java is sa"ety, so #any o" the %roble#s that %lague %rogra##ers in + and +<< are not re%eated in Java. 6 Java array is guaranteed to be initiali1ed and cannot be accessed outside o" its range. The range checking co#es at the %rice o" having a s#all a#ount o" #e#ory overhead on each array as well as veri"ying the inde& at run'ti#e, but the assu#%tion is that the sa"ety and increased %roductivity is worth the e&%ense. RFSURFSTIJLT+(6PTE5KTIK2U :hen you create an array o" ob0ects, you are really creating an array o" re"erences, and each o" those re"erences is auto#atically initiali1ed to a s%ecial value with its own keyword= n*ll. :hen Java sees n*ll, it recogni1es that the re"erence in Auestion isn t %ointing to an ob0ect. /ou #ust assign an ob0ect to each re"erence be"ore you use it, and i" you try to

112

use a re"erence that s still n*ll, the %roble# will be re%orted at run'ti#e. Thus, ty%ical array errors are %revented in Java. RFSURF STIJLT+(6PTE5KTIL@U /ou can also create an array o" %ri#itives. 6gain, the co#%iler guarantees initiali1ation because it 1eroes the #e#ory "or that array. RFSURF STIJLT+(6PTE5KTILMU 6rrays will be covered in detail in later cha%ters. RFSURF STIJLT+(6PTE5KTILKU

Gou never need to destro: an ob3ect


In #ost %rogra##ing languages, the conce%t o" the li"eti#e o" a variable occu%ies a signi"icant %ortion o" the %rogra##ing e""ort. (ow long does the variable lastO I" you are su%%osed to destroy it, when should youO +on"usion over variable li"eti#es can lead to a lot o" bugs, and this section shows how Java greatly si#%li"ies the issue by doing all the cleanu% work "or you. RFSURFSTIJLT+(6PTE5KTILLU

1co.ing
Most %rocedural languages have the conce%t o" sco e. This deter#ines both the visibility and li"eti#e o" the na#es de"ined within that sco%e. In +, +<<, and Java, sco%e is deter#ined by the %lace#ent o" curly braces EF. So "or e&a#%le= RFSURFSTIJLT+(6PTE5KTIL?U

@ int 6 ? ( /B only 6 @ int = ? /B both A /B only 6 /B = Eout A < available B/ C+< 6 D = available B/ available B/ of sco"eF B/

Cha ter 2! Ever)thing is an Ob>ect

113

6 variable de"ined within a sco%e is available only to the end o" that sco%e. RFSURFSTIJLT+(6PTE5KTILHU Indentation #akes Java code easier to read. Since Java is a "ree'"or# language, the e&tra s%aces, tabs, and carriage returns do not a""ect the resulting %rogra#. RFSURFSTIJLT+(6PTE5KTIL3U Cote that you cannot do the "ollowing, even though it is legal in + and +<<=

@ int 6 ? ( < @ int 6 ? C+< /B illegal B/ A A


The co#%iler will announce that the variable 4 has already been de"ined. Thus the + and +<< ability to !hide$ a variable in a larger sco%e is not allowed because the Java designers thought that it led to con"using %rogra#s. RFSURFSTIJLT+(6PTE5KTILGU

1co.e of ob3ects
Java ob0ects do not have the sa#e li"eti#es as %ri#itives. :hen you create a Java ob0ect using ne(, it hangs around %ast the end o" the sco%e. Thus i" you use=

@ %tring s ? ne: %tring-8a string8.< A /B en! of sco"e B/


the re"erence s vanishes at the end o" the sco%e. (owever, the )tring ob0ect that s was %ointing to is still occu%ying #e#ory. In this bit o" code, there is no way to access the ob0ect because the only re"erence to it is out o" sco%e. In later cha%ters you ll see how the re"erence to the ob0ect can be %assed around and du%licated during the course o" a %rogra#. RFSURF STIJLT+(6PTE5KTILIU It turns out that because ob0ects created with ne( stay around "or as long as you want the#, a whole slew o" +<< %rogra##ing %roble#s si#%ly

114

vanish in Java. The hardest %roble#s see# to occur in +<< because you don t get any hel% "ro# the language in #aking sure that the ob0ects are available when they re needed. 6nd #ore i#%ortant, in +<< you #ust #ake sure that you destroy the ob0ects when you re done with the#. RF SURFSTIJLT+(6PTE5KTIL2U That brings u% an interesting Auestion. I" Java leaves the ob0ects lying around, what kee%s the# "ro# "illing u% #e#ory and halting your %rogra#O This is e&actly the kind o" %roble# that would occur in +<<. This is where a bit o" #agic ha%%ens. Java has a garbage collector, which looks at all the ob0ects that were created with ne( and "igures out which ones are not being re"erenced any#ore. Then it releases the #e#ory "or those ob0ects, so the #e#ory can be used "or new ob0ects. This #eans that you never need to worry about reclai#ing #e#ory yoursel". /ou si#%ly create ob0ects, and when you no longer need the# they will go away by the#selves. This eli#inates a certain class o" %rogra##ing %roble#= the so'called !#e#ory leak,$ in which a %rogra##er "orgets to release #e#ory. RFSURFSTIJLT+(6PTE5KTI?@U

Creating new data t:.es: class


I" everything is an ob0ect, what deter#ines how a %articular class o" ob0ect looks and behavesO Put another way, what establishes the t) e o" an ob0ectO /ou #ight e&%ect there to be a keyword called !ty%e,$ and that certainly would have #ade sense. (istorically, however, #ost ob0ect' oriented languages have used the keyword class to #ean !I # about to tell you what a new ty%e o" ob0ect looks like.$ The class keyword *which is so co##on that it will not be e#boldened throughout this book, is "ollowed by the na#e o" the new ty%e. Eor e&a#%le= RFSURF STIJLT+(6PTE5KTI?MU

class 0Ty"e&a#e @ /B class bo!y goes here B/ A


This introduces a new ty%e, so you can now create an ob0ect o" this ty%e using ne(=

0Ty"e&a#e a ? ne: 0Ty"e&a#e-.<

Cha ter 2! Ever)thing is an Ob>ect

115

In AType/ame, the class body consists only o" a co##ent *the stars and slashes and what is inside, which will be discussed later in this cha%ter,, so there is not too #uch that you can do with it. In "act, you cannot tell it to do #uch o" anything *that is, you cannot send it any interesting #essages, until you de"ine so#e #ethods "or it. RFSURF STIJLT+(6PTE5KTI?KU

<ields and methods


:hen you de"ine a class *and all you do in Java is de"ine classes, #ake ob0ects o" those classes, and send #essages to those ob0ects,, you can %ut two ty%es o" ele#ents in your class= data #e#bers *so#eti#es called $ields,, and #e#ber "unctions *ty%ically called methods,. 6 data #e#ber is an ob0ect o" any ty%e that you can co##unicate with via its re"erence. It can also be one o" the %ri#itive ty%es *which isn t a re"erence,. I" it is a re"erence to an ob0ect, you #ust initiali1e that re"erence to connect it to an actual ob0ect *using ne(, as seen earlier, in a s%ecial "unction called a constructor *described "ully in +ha%ter ?,. I" it is a %ri#itive ty%e you can initiali1e it directly at the %oint o" de"inition in the class. *6s you ll see later, re"erences can also be initiali1ed at the %oint o" de"inition., RFSURF STIJLT+(6PTE5KTI?LU Each ob0ect kee%s its own storage "or its data #e#bers; the data #e#bers are not shared a#ong ob0ects. (ere is an e&a#%le o" a class with so#e data #e#bers= RFSURFSTIJLT+(6PTE5KTI??U

class DataGnly @ int i< float f< boolean b< A


This class doesn t do anything, but you can create an ob0ect= RFSURF STIJLT+(6PTE5KTI?HU

DataGnly ! ? ne: DataGnly-.<


/ou can assign values to the data #e#bers, but you #ust "irst know how to re"er to a #e#ber o" an ob0ect. This is acco#%lished by stating the

117

na#e o" the ob0ect re"erence, "ollowed by a %eriod *dot,, "ollowed by the na#e o" the #e#ber inside the ob0ect= RFSURFSTIJLT+(6PTE5KTI?3U

obHect5eference.#e#ber
Eor e&a#%le= RFSURFSTIJLT+(6PTE5KTI?GU

!.i ? I*< !.f ? (.(f< !.b ? false<


It is also %ossible that your ob0ect #ight contain other ob0ects that contain data you d like to #odi"y. Eor this, you 0ust kee% !connecting the dots.$ Eor e&a#%le= RFSURFSTIJLT+(6PTE5KTI?IU

#yPlane.leftTank.ca"acity ? (''<
The ata.nly class cannot do #uch o" anything e&ce%t hold data, because it has no #e#ber "unctions *#ethods,. To understand how those work, you #ust "irst understand arguments and return values, which will be described shortly. RFSURFSTIJLT+(6PTE5KTI?2U

Default values for .rimitive members


:hen a %ri#itive data ty%e is a #e#ber o" a class, it is guaranteed to get a de"ault value i" you do not initiali1e it=

#rimitive type boolean char byte short int long float 'o*ble

efa*lt false GH*DDDD; An*llB AbyteBD AshortBD D D+ D!Df D!D'

Cote care"ully that the de"ault values are what Java guarantees when the variable is used as a member o$ a class. This ensures that #e#ber variables o" %ri#itive ty%es will always be initiali1ed *so#ething +<<

Cha ter 2! Ever)thing is an Ob>ect

118

doesn t do,, reducing a source o" bugs. (owever, this initial value #ay not be correct or even legal "or the %rogra# you are writing. It s best to always e&%licitly initiali1e your variables. RFSURFSTIJLT+(6PTE5KTIH@U This guarantee doesn t a%%ly to !local$ variables9those that are not "ields o" a class. Thus, i" within a "unction de"inition you have=

int 6<
Then 4 will get so#e arbitrary value *as in + and +<<,; it will not auto#atically be initiali1ed to 1ero. /ou are res%onsible "or assigning an a%%ro%riate value be"ore you use 4. I" you "orget, Java de"initely i#%roves on +<<= you get a co#%ile'ti#e error telling you the variable #ight not have been initiali1ed. *Many +<< co#%ilers will warn you about uninitiali1ed variables, but in Java these are errors., RFSURF STIJLT+(6PTE5KTIHMU

MethodsH argumentsH and return values


4% until now, the ter# $unction has been used to describe a na#ed subroutine. The ter# that is #ore co##only used in Java is methodD as in !a way to do so#ething.$ I" you want, you can continue thinking in ter#s o" "unctions. It s really only a syntactic di""erence, but "ro# now on !#ethod$ will be used in this book rather than !"unction.$ RFSURF STIJLT+(6PTE5KTIHKU Methods in Java deter#ine the #essages an ob0ect can receive. In this section you will learn how si#%le it is to de"ine a #ethod. RFSURF STIJLT+(6PTE5KTIHLU The "unda#ental %arts o" a #ethod are the na#e, the argu#ents, the return ty%e, and the body. (ere is the basic "or#=

returnTy"e #etho!&a#e- /B 0rgu#ent list B/ . @ /B Jetho! bo!y B/ A

11:

The return ty%e is the ty%e o" the value that %o%s out o" the #ethod a"ter you call it. The argu#ent list gives the ty%es and na#es "or the in"or#ation you want to %ass into the #ethod. The #ethod na#e and argu#ent list together uniAuely identi"y the #ethod. RFSURF STIJLT+(6PTE5KTIH?U Methods in Java can be created only as %art o" a class. 6 #ethod can be called only "or an ob0ect, @ and that ob0ect #ust be able to %er"or# that #ethod call. I" you try to call the wrong #ethod "or an ob0ect, you ll get an error #essage at co#%ile'ti#e. /ou call a #ethod "or an ob0ect by na#ing the ob0ect "ollowed by a %eriod *dot,, "ollowed by the na#e o" the #ethod and its argu#ent list, like this= ob8ect/ame!metho'/ameAarg>, argI, argJB. Eor e&a#%le, su%%ose you have a #ethod fA B that takes no argu#ents and returns a value o" ty%e int. Then, i" you have an ob0ect called a "or which fA B can be called, you can say this=

int 6 ? a.f-.<
The ty%e o" the return value #ust be co#%atible with the ty%e o" 4. RF SURFSTIJLT+(6PTE5KTIHHU This act o" calling a #ethod is co##only re"erred to as sending a message to an ob>ect. In the above e&a#%le, the #essage is fA B and the ob0ect is a. )b0ect'oriented %rogra##ing is o"ten su##ari1ed as si#%ly !sending #essages to ob0ects.$ RFSURFSTIJLT+(6PTE5KTIH3U

#he argument list


The #ethod argu#ent list s%eci"ies what in"or#ation you %ass into the #ethod. 6s you #ight guess, this in"or#ation9like everything else in Java9takes the "or# o" ob0ects. So, what you #ust s%eci"y in the argu#ent list are the ty%es o" the ob0ects to %ass in and the na#e to use "or each one. 6s in any situation in Java where you see# to be handing ob0ects around, you are actually %assing re"erences @. The ty%e o" the
@ static #ethods, which you ll learn about soon, can be called $or the class, without an ob0ect. @ :ith the usual e&ce%tion o" the a"ore#entioned !s%ecial$ data ty%es boolean, char , byte, short, int, long, float, and 'o*ble. In general, though, you %ass ob0ects, which really #eans you %ass re"erences to ob0ects.

Cha ter 2! Ever)thing is an Ob>ect

11;

re"erence #ust be correct, however. I" the argu#ent is su%%osed to be a )tring, what you %ass in #ust be a string. RFSURF STIJLT+(6PTE5KTIHGU +onsider a #ethod that takes a )tring as its argu#ent. (ere is the de"inition, which #ust be %laced within a class de"inition "or it to be co#%iled=

int storage-%tring s. @ return s.length-. B < A


This #ethod tells you how #any bytes are reAuired to hold the in"or#ation in a %articular )tring! *Each char in a )tring is M3 bits, or two bytes, long, to su%%ort 4nicode characters., The argu#ent is o" ty%e )tring and is called s. )nce s is %assed into the #ethod, you can treat it 0ust like any other ob0ect. */ou can send #essages to it., (ere, the length A B #ethod is called, which is one o" the #ethods "or )trings; it returns the nu#ber o" characters in a string. RFSURFSTIJLT+(6PTE5KTIHIU /ou can also see the use o" the ret*rn keyword, which does two things. Eirst, it #eans !leave the #ethod, I # done.$ Second, i" the #ethod %roduces a value, that value is %laced right a"ter the ret*rn state#ent. In this case, the return value is %roduced by evaluating the e&%ression s! lengthA B K I. RFSURFSTIJLT+(6PTE5KTIH2U /ou can return any ty%e you want, but i" you don t want to return anything at all, you do so by indicating that the #ethod returns voi'. (ere are so#e e&a#%les=

boolean flag-. @ return true< A float naturalLogBase-. @ return voi! nothing-. @ return< A voi! nothing -. @A

.*(1f< A

:hen the return ty%e is voi', then the ret*rn keyword is used only to e&it the #ethod, and is there"ore unnecessary when you reach the end o" the #ethod. /ou can return "ro# a #ethod at any %oint, but i" you ve given a non' voi' return ty%e then the co#%iler will "orce you *with error #essages, to return the a%%ro%riate ty%e o" value regardless o" where you return. RFSURFSTIJLT+(6PTE5KTI3@U

12=

6t this %oint, it can look like a %rogra# is 0ust a bunch o" ob0ects with #ethods that take other ob0ects as argu#ents and send #essages to those other ob0ects. That is indeed #uch o" what goes on, but in the "ollowing cha%ter you ll learn how to do the detailed low'level work by #aking decisions within a #ethod. Eor this cha%ter, sending #essages will su""ice. RFSURFSTIJLT+(6PTE5KTI3MU

;uilding a "ava .rogram


There are several other issues you #ust understand be"ore seeing your "irst Java %rogra#. RFSURFSTIJLT+(6PTE5KTI3KU

2ame visibilit:
6 %roble# in any %rogra##ing language is the control o" na#es. I" you use a na#e in one #odule o" the %rogra#, and another %rogra##er uses the sa#e na#e in another #odule, how do you distinguish one na#e "ro# another and %revent the two na#es "ro# !clashingO$ In + this is a %articular %roble# because a %rogra# is o"ten an un#anageable sea o" na#es. +<< classes *on which Java classes are based, nest "unctions within classes so they cannot clash with "unction na#es nested within other classes. (owever, +<< still allowed global data and global "unctions, so clashing was still %ossible. To solve this %roble#, +<< introduced names aces using additional keywords. RFSURF STIJLT+(6PTE5KTI3LU Java was able to avoid all o" this by taking a "resh a%%roach. To %roduce an una#biguous na#e "or a library, the s%eci"ier used is not unlike an Internet do#ain na#e. In "act, the Java creators want you to use your Internet do#ain na#e in reverse since those are guaranteed to be uniAue. Since #y do#ain na#e is 2r*ce&ckel!com, #y utility library o" "oibles would be na#ed com!br*ceeckel!*tility!foibles. 6"ter your reversed do#ain na#e, the dots are intended to re%resent subdirectories. RFSURF STIJLT+(6PTE5KTI3?U In Java M.@ and Java M.M the do#ain e&tensions com, e'*, org, net, etc., were ca%itali1ed by convention, so the library would a%%ear= -.1! br*ceeckel!*tility!foibles. Partway through the develo%#ent o" Java

Cha ter 2! Ever)thing is an Ob>ect

121

K, however, it was discovered that this caused %roble#s, and so now the entire %ackage na#e is lowercase. RFSURFSTIJLT+(6PTE5KTI3HU This #echanis# #eans that all o" your "iles auto#atically live in their own na#es%aces, and each class within a "ile #ust have a uniAue identi"ier. So you do not need to learn s%ecial language "eatures to solve this %roble#9the language takes care o" it "or you. RFSURF STIJLT+(6PTE5KTI33U

Csing other com.onents


:henever you want to use a %rede"ined class in your %rogra#, the co#%iler #ust know how to locate it. )" course, the class #ight already e&ist in the sa#e source code "ile that it s being called "ro#. In that case, you si#%ly use the class9even i" the class doesn t get de"ined until later in the "ile. Java eli#inates the !"orward re"erencing$ %roble# so you don t need to think about it. RFSURFSTIJLT+(6PTE5KTI3GU :hat about a class that e&ists in so#e other "ileO /ou #ight think that the co#%iler should be s#art enough to si#%ly go and "ind it, but there is a %roble#. I#agine that you want to use a class o" a %articular na#e, but #ore than one de"inition "or that class e&ists *%resu#ably these are di""erent de"initions,. )r worse, i#agine that you re writing a %rogra#, and as you re building it you add a new class to your library that con"licts with the na#e o" an e&isting class. RFSURFSTIJLT+(6PTE5KTI3IU To solve this %roble#, you #ust eli#inate all %otential a#biguities. This is acco#%lished by telling the Java co#%iler e&actly what classes you want using the import keyword. import tells the co#%iler to bring in a ackage, which is a library o" classes. *In other languages, a library could consist o" "unctions and data as well as classes, but re#e#ber that all code in Java #ust be written inside a class., RFSURF STIJLT+(6PTE5KTI32U Most o" the ti#e you ll be using co#%onents "ro# the standard Java libraries that co#e with your co#%iler. :ith these, you don t need to worry about long, reversed do#ain na#es; you 0ust say, "or e&a#%le=

i#"ort Hava.util.0rrayList<

122

to tell the co#%iler that you want to use Java s Array+ist class. (owever, *til contains a nu#ber o" classes and you #ight want to use several o" the# without declaring the# all e&%licitly. This is easily acco#%lished by using [K to indicate a wild card=

i#"ort Hava.util.B<
It is #ore co##on to i#%ort a collection o" classes in this #anner than to i#%ort classes individually. RFSURFSTIJLT+(6PTE5KTIG@U

#he static ke:word


)rdinarily, when you create a class you are describing how ob0ects o" that class look and how they will behave. /ou don t actually get anything until you create an ob0ect o" that class with ne(, and at that %oint data storage is created and #ethods beco#e available. RFSURF STIJLT+(6PTE5KTIGMU But there are two situations in which this a%%roach is not su""icient. )ne is i" you want to have only one %iece o" storage "or a %articular %iece o" data, regardless o" how #any ob0ects are created, or even i" no ob0ects are created. The other is i" you need a #ethod that isn t associated with any %articular ob0ect o" this class. That is, you need a #ethod that you can call even i" no ob0ects are created. /ou can achieve both o" these e""ects with the static keyword. :hen you say so#ething is static, it #eans that data or #ethod is not tied to any %articular ob0ect instance o" that class. So even i" you ve never created an ob0ect o" that class you can call a static #ethod or access a %iece o" static data. :ith ordinary, non'static data and #ethods you #ust create an ob0ect and use that ob0ect to access the data or #ethod, since non' static data and #ethods #ust know the %articular ob0ect they are working with. )" course, since static #ethods don t need any ob0ects to be created be"ore they are used, they cannot directl) access non' static #e#bers or #ethods by si#%ly calling those other #e#bers without re"erring to a na#ed ob0ect *since non' static #e#bers and #ethods #ust be tied to a %articular ob0ect,. RFSURF STIJLT+(6PTE5KTIGKU So#e ob0ect'oriented languages use the ter#s class data and class methods, #eaning that the data and #ethods e&ist only "or the class as a

Cha ter 2! Ever)thing is an Ob>ect

123

whole, and not "or any %articular ob0ects o" the class. So#eti#es the Java literature uses these ter#s too. RFSURFSTIJLT+(6PTE5KTIGLU To #ake a data #e#ber or #ethod static, you si#%ly %lace the keyword be"ore the de"inition. Eor e&a#%le, the "ollowing %roduces a static data #e#ber and initiali1es it= RFSURFSTIJLT+(6PTE5KTIG?U

class %taticTest @ static int i ? I*< A


Cow even i" you #ake two )taticTest ob0ects, there will still be only one %iece o" storage "or )taticTest!i! Both ob0ects will share the sa#e i. +onsider= RFSURFSTIJLT+(6PTE5KTIGHU

%taticTest st( ? ne: %taticTest-.< %taticTest st ? ne: %taticTest-.<


6t this %oint, both st>!i and stI!i have the sa#e value o" ?G since they re"er to the sa#e %iece o" #e#ory. RFSURFSTIJLT+(6PTE5KTIG3U There are two ways to re"er to a static variable. 6s indicated above, you can na#e it via an ob0ect, by saying, "or e&a#%le, stI!i. /ou can also re"er to it directly through its class na#e, so#ething you cannot do with a non' static #e#ber. *This is the %re"erred way to re"er to a static variable since it e#%hasi1es that variable s static nature., RFSURF STIJLT+(6PTE5KTIGGU

%taticTest.iKK<
The LL o%erator incre#ents the variable. 6t this %oint, both st>!i and stI!i will have the value ?I. RFSURFSTIJLT+(6PTE5KTIGIU Si#ilar logic a%%lies to static #ethods. /ou can re"er to a static #ethod either through an ob0ect as you can with any #ethod, or with the s%ecial additional synta& -lass/ame!metho'A B. /ou de"ine a static #ethod in a si#ilar way= RFSURFSTIJLT+(6PTE5KTIG2U

class %taticLun @ static voi! incr-. @ %taticTest.iKK< A A

124

/ou can see that the )taticF*n #ethod incrA B incre#ents the static data i. /ou can call incrA B in the ty%ical way, through an ob0ect= RFSURF STIJLT+(6PTE5KTII@U

%taticLun sf ? ne: %taticLun-.< sf.incr-.<


)r, because incrA B is a static #ethod, you can call it directly through its class= RFSURFSTIJLT+(6PTE5KTIIMU

%taticLun.incr-.<
:hile static, when a%%lied to a data #e#ber, de"initely changes the way the data is created *one "or each class vs. the non' static one "or each ob0ect,, when a%%lied to a #ethod it s not so dra#atic. 6n i#%ortant use o" static "or #ethods is to allow you to call that #ethod without creating an ob0ect. This is essential, as we will see, in de"ining the mainA B #ethod that is the entry %oint "or running an a%%lication. RFSURF STIJLT+(6PTE5KTIIKU Dike any #ethod, a static #ethod can create or use na#ed ob0ects o" its ty%e, so a static #ethod is o"ten used as a !she%herd$ "or a "lock o" instances o" its own ty%e. RFSURFSTIJLT+(6PTE5KTIILU

Gour first "ava .rogram


Einally, here s the %rogra#. @ It starts by %rinting a string, and then the date, using the ate class "ro# the Java standard library. Cote that an additional style o" co##ent is introduced here= the [55 , which is a co##ent until the end o" the line= RFSURFSTIJLT+(6PTE5KTII?U

// MelloDate.Hava
@ So#e %rogra##ing environ#ents will "lash %rogra#s u% on the screen and close the# be"ore youVve had a chance to see the results. /ou can %ut in the "ollowing bit o" code at the end o" mainA B to %ause the out%ut=

try @ %yste#.in.rea!-.< A catch-E6ce"tion e. @A This will %ause the out%ut until you %ress !Enter$ *or any other key,. This code involves conce%ts that will not be introduced until #uch later in the book, so you won t understand it until then, but it will do the trick.

Cha ter 2! Ever)thing is an Ob>ect

125

i#"ort Hava.util.B< "ublic class MelloDate @ "ublic static voi! #ain-%tringNO args. @ %yste#.out."rintln-8Mello, it2s3 8.< %yste#.out."rintln-ne: Date-..< A A
6t the beginning o" each %rogra# "ile, you #ust %lace the import state#ent to bring in any e&tra classes you ll need "or the code in that "ile. Cote that I say !e&tra;$ that s because there s a certain library o" classes that are auto#atically brought into every Java "ile= 8ava!lang. Start u% your :eb browser and look at the docu#entation "ro# Sun. *I" you haven t downloaded it "ro# >ava'sun'com or otherwise installed the Java docu#entation, do so now,. I" you look at the list o" the %ackages, you ll see all the di""erent class libraries that co#e with Java. Select 8ava!lang. This will bring u% a list o" all the classes that are %art o" that library. Since 8ava!lang is i#%licitly included in every Java code "ile, these classes are auto#atically available. There s no ate class listed in 8ava!lang, which #eans you #ust i#%ort another library to use that. I" you don t know the library where a %articular class is, or i" you want to see all o" the classes, you can select !Tree$ in the Java docu#entation. Cow you can "ind every single class that co#es with Java. Then you can use the browser s !"ind$ "unction to "ind ate. :hen you do you ll see it listed as 8ava!*til! ate, which lets you know that it s in the *til library and that you #ust import 8ava!*til!K in order to use ate. RFSURFSTIJLT+(6PTE5KTIIHU I" you go back to the beginning, select 8ava!lang and then )ystem, you ll see that the )ystem class has several "ields, and i" you select o*t you ll discover that it s a static #rint)tream ob0ect. Since it s static you don t need to create anything. The o*t ob0ect is always there and you can 0ust use it. :hat you can do with this o*t ob0ect is deter#ined by the ty%e it is= a #rint)tream. +onveniently, #rint)tream is shown in the descri%tion as a hy%erlink, so i" you click on that you ll see a list o" all the #ethods you can call "or #rint)tream. There are Auite a "ew and these will be covered later in this book. Eor now all we re interested in is printlnA B, which in e""ect #eans !%rint what I # giving you out to the console and end with a new line.$ Thus, in any Java %rogra# you write

127

you can say )ystem!o*t!printlnAMthingsMB whenever you want to %rint so#ething to the console. RFSURFSTIJLT+(6PTE5KTII3U The na#e o" the class is the sa#e as the na#e o" the "ile. :hen you re creating a stand'alone %rogra# such as this one, one o" the classes in the "ile #ust have the sa#e na#e as the "ile. *The co#%iler co#%lains i" you don t do this., That class #ust contain a #ethod called mainA B with the signature shown= RFSURFSTIJLT+(6PTE5KTIIGU

"ublic static voi! #ain-%tringNO args. @


The p*blic keyword #eans that the #ethod is available to the outside world *described in detail in +ha%ter H,. The argu#ent to mainA B is an array o" )tring ob0ects. The args won t be used in this %rogra#, but the Java co#%iler insists that they be there because they hold the argu#ents invoked on the co##and line. RFSURFSTIJLT+(6PTE5KTIIIU The line that %rints the date is Auite interesting= RFSURF STIJLT+(6PTE5KTII2U

%yste#.out."rintln-ne: Date-..<
+onsider the argu#ent= a ate ob0ect is being created 0ust to send its value to printlnA B. 6s soon as this state#ent is "inished, that ate is unnecessary, and the garbage collector can co#e along and get it anyti#e. :e don t need to worry about cleaning it u%. RFSURF STIJLT+(6PTE5KTI2@U

Com.iling and running


To co#%ile and run this %rogra#, and all the other %rogra#s in this book, you #ust "irst have a Java %rogra##ing environ#ent. There are a nu#ber o" third'%arty develo%#ent environ#ents, but in this book we will assu#e that you are using the J7> "ro# Sun, which is "ree. I" you are using another develo%#ent syste#, you will need to look in the docu#entation "or that syste# to deter#ine how to co#%ile and run %rogra#s. RFSURFSTIJLT+(6PTE5KTI2MU 8et on the Internet and go to >ava'sun'com. There you will "ind in"or#ation and links that will lead you through the %rocess o"

Cha ter 2! Ever)thing is an Ob>ect

128

downloading and installing the J7> "or your %articular %lat"or#. RFSURF STIJLT+(6PTE5KTI2KU )nce the J7> is installed, and you ve set u% your co#%uter s %ath in"or#ation so that it will "ind 8avac and 8ava, download and un%ack the source code "or this book *you can "ind it on the +7 5)M that s bound in with this book, or at ,,,'0ruceEckel'com,. This will create a subdirectory "or each cha%ter in this book. Move to subdirectory cDI and ty%e= RFSURFSTIJLT+(6PTE5KTI2LU

Havac MelloDate.Hava
This co##and should %roduce no res%onse. I" you get any kind o" an error #essage it #eans you haven t installed the J7> %ro%erly and you need to investigate those %roble#s. RFSURFSTIJLT+(6PTE5KTI2?U )n the other hand, i" you 0ust get your co##and %ro#%t back, you can ty%e=

Hava MelloDate
and you ll get the #essage and the date as out%ut. RFSURF STIJLT+(6PTE5KTI2HU This is the %rocess you can use to co#%ile and run each o" the %rogra#s in this book. (owever, you will see that the source code "or this book also has a "ile called makefile in each cha%ter, and this contains !#ake$ co##ands "or auto#atically building the "iles "or that cha%ter. See this book s :eb %age at ,,,'0ruceEckel'com "or details on how to use the #ake"iles. RFSURFSTIJLT+(6PTE5KTI23U

Comments and embedded documentation


There are two ty%es o" co##ents in Java. The "irst is the traditional +' style co##ent that was inherited by +<<. These co##ents begin with a 5 K and continue, %ossibly across #any lines, until a K5. Cote that #any

12:

%rogra##ers will begin each line o" a continued co##ent with a K, so you ll o"ten see=

/B This is a co##ent B that continues B across lines B/


5e#e#ber, however, that everything inside the 5K and K5 is ignored, so there s no di""erence in saying= RFSURFSTIJLT+(6PTE5KTI2GU

/B This is a co##ent that continues across lines B/


The second "or# o" co##ent co#es "ro# +<<. It is the single'line co##ent, which starts at a 55 and continues until the end o" the line. This ty%e o" co##ent is convenient and co##only used because it s easy. /ou don t need to hunt on the keyboard to "ind 5 and then K *instead, you 0ust %ress the sa#e key twice,, and you don t need to close the co##ent. So you will o"ten see= RFSURFSTIJLT+(6PTE5KTI2IU

// this is a one-line co##ent

Comment documentation
)ne o" the thought"ul %arts o" the Java language is that the designers didn t consider writing code to be the only i#%ortant activity9they also thought about docu#enting it. Possibly the biggest %roble# with docu#enting code has been #aintaining that docu#entation. I" the docu#entation and the code are se%arate, it beco#es a hassle to change the docu#entation every ti#e you change the code. The solution see#s si#%le= link the code to the docu#entation. The easiest way to do this is to %ut everything in the sa#e "ile. To co#%lete the %icture, however, you need a s%ecial co##ent synta& to #ark s%ecial docu#entation, and a tool to e&tract those co##ents and %ut the# in a use"ul "or#. This is what Java has done. RFSURFSTIJLT+(6PTE5KTI22U The tool to e&tract the co##ents is called >avadoc' It uses so#e o" the technology "ro# the Java co#%iler to look "or s%ecial co##ent tags you %ut in your %rogra#s. It not only e&tracts the in"or#ation #arked by these tags, but it also %ulls out the class na#e or #ethod na#e that

Cha ter 2! Ever)thing is an Ob>ect

12;

ad0oins the co##ent. This way you can get away with the #ini#al a#ount o" work to generate decent %rogra# docu#entation. RFSURF STIJLT+(6PTE5KTIM@@U The out%ut o" 0avadoc is an (TMD "ile that you can view with your :eb browser. This tool allows you to create and #aintain a single source "ile and auto#atically generate use"ul docu#entation. Because o" 0avadoc we have a standard "or creating docu#entation, and it s easy enough that we can e&%ect or even de#and docu#entation with all Java libraries. RFSURF STIJLT+(6PTE5KTIM@MU

1:nta0
6ll o" the 0avadoc co##ands occur only within 5KK co##ents. The co##ents end with K5 as usual. There are two %ri#ary ways to use 0avadoc= e#bed (TMD, or use !doc tags.$ 7oc tags are co##ands that start with a [ 9 and are %laced at the beginning o" a co##ent line. *6 leading [K , however, is ignored., RFSURFSTIJLT+(6PTE5KTIM@KU There are three !ty%es$ o" co##ent docu#entation, which corres%ond to the ele#ent the co##ent %recedes= class, variable, or #ethod. That is, a class co##ent a%%ears right be"ore the de"inition o" a class; a variable co##ent a%%ears right in "ront o" the de"inition o" a variable, and a #ethod co##ent a%%ears right in "ront o" the de"inition o" a #ethod. 6s a si#%le e&a#%le= RFSURFSTIJLT+(6PTE5KTIM@LU

/BB 0 class co##ent B/ "ublic class !ocTest @ /BB 0 variable co##ent B/ "ublic int i< /BB 0 #etho! co##ent B/ "ublic voi! f-. @A A
Cote that 0avadoc will %rocess co##ent docu#entation "or only p*blic and protecte' #e#bers. +o##ents "or private and !"riendly$ #e#bers *see +ha%ter H, are ignored and you ll see no out%ut. *(owever, you can use the 6private "lag to include private #e#bers as well., This #akes sense, since only p*blic and protecte' #e#bers are available outside the "ile, which is the client %rogra##er s %ers%ective. (owever,

13=

all class co##ents are included in the out%ut. RFSURF STIJLT+(6PTE5KTIM@?U The out%ut "or the above code is an (TMD "ile that has the sa#e standard "or#at as all the rest o" the Java docu#entation, so users will be co#"ortable with the "or#at and can easily navigate your classes. It s worth entering the above code, sending it through 0avadoc and viewing the resulting (TMD "ile to see the results. RFSURF STIJLT+(6PTE5KTIM@HU

/mbedded >#M&
Javadoc %asses (TMD co##ands through to the generated (TMD docu#ent. This allows you "ull use o" (TMD; however, the %ri#ary #otive is to let you "or#at code, such as= RFSURF STIJLT+(6PTE5KTIM@3U

/BB B P"reQ B %yste#.out."rintln-ne: Date-..< B P/"reQ B/


/ou can also use (TMD 0ust as you would in any other :eb docu#ent to "or#at the regular te&t in your descri%tions= RFSURF STIJLT+(6PTE5KTIM@GU

/BB B ;ou can Pe#QevenP/e#Q insert a list3 B PolQ B PliQ $te# one B PliQ $te# t:o B PliQ $te# three B P/olQ B/
Cote that within the docu#entation co##ent, asterisks at the beginning o" a line are thrown away by 0avadoc, along with leading s%aces. Javadoc re"or#ats everything so that it con"or#s to the standard docu#entation a%%earance. 7on t use headings such as Nh>O or NhrO as e#bedded

Cha ter 2! Ever)thing is an Ob>ect

131

(TMD because 0avadoc inserts its own headings and yours will inter"ere with the#. RFSURFSTIJLT+(6PTE5KTIM@IU 6ll ty%es o" co##ent docu#entation9class, variable, and #ethod9can su%%ort e#bedded (TMD. RFSURFSTIJLT+(6PTE5KTIM@2U

/see: referring to other classes


6ll three ty%es o" co##ent docu#entation *class, variable, and #ethod, can contain 9see tags, which allow you to re"er to the docu#entation in other classes. Javadoc will generate (TMD with the 9see tags hy%erlinked to the other docu#entation. The "or#s are= RFSURF STIJLT+(6PTE5KTIMM@U

Rsee classna#e Rsee fully-=ualifie!-classna#e Rsee fully-=ualifie!-classna#eS#etho!-na#e


Each one adds a hy%erlinked !See 6lso$ entry to the generated docu#entation. Javadoc will not check the hy%erlinks you give it to #ake sure they are valid. RFSURFSTIJLT+(6PTE5KTIMMMU

Class documentation tags


6long with e#bedded (TMD and 9see re"erences, class docu#entation can include tags "or version in"or#ation and the author s na#e. +lass docu#entation can also be used "or inter$aces *see +ha%ter I,. RFSURF STIJLT+(6PTE5KTIMMKU

Iversion
This is o" the "or#=

Rversion version-infor#ation
in which version6information is any signi"icant in"or#ation you see "it to include. :hen the 6version "lag is %laced on the 0avadoc co##and line, the version in"or#ation will be called out s%ecially in the generated (TMD docu#entation. RFSURFSTIJLT+(6PTE5KTIMMLU

132

Iauthor
This is o" the "or#=

Rauthor author-infor#ation
in which a*thor6information is, %resu#ably, your na#e, but it could also include your e#ail address or any other a%%ro%riate in"or#ation. :hen the 6a*thor "lag is %laced on the 0avadoc co##and line, the author in"or#ation will be called out s%ecially in the generated (TMD docu#entation. RFSURFSTIJLT+(6PTE5KTIMM?U /ou can have #ulti%le author tags "or a list o" authors, but they #ust be %laced consecutively. 6ll the author in"or#ation will be lu#%ed together into a single %aragra%h in the generated (TMD. RFSURF STIJLT+(6PTE5KTIMMHU

Isince
This tag allows you to indicate the version o" this code that began using a %articular "eature. /ou ll see it a%%earing in the (TMD Java docu#entation to indicate what version o" the J7> is used. RFSURF STIJLT+(6PTE5KTIMM3U

=ariable documentation tags


Variable docu#entation can include only e#bedded (TMD and 9see re"erences. RFSURFSTIJLT+(6PTE5KTIMMGU

Method documentation tags


6s well as e#bedded docu#entation and 9see re"erences, #ethods allow docu#entation tags "or %ara#eters, return values, and e&ce%tions. RF SURFSTIJLT+(6PTE5KTIMMIU

I.aram
This is o" the "or#=

R"ara# parameter-name description

Cha ter 2! Ever)thing is an Ob>ect

133

in which parameter6name is the identi"ier in the %ara#eter list, and 'escription is te&t that can continue on subseAuent lines. The descri%tion is considered "inished when a new docu#entation tag is encountered. /ou can have any nu#ber o" these, %resu#ably one "or each %ara#eter. RFSURFSTIJLT+(6PTE5KTIMM2U

Ireturn
This is o" the "or#=

Rreturn description
in which 'escription gives you the #eaning o" the return value. It can continue on subseAuent lines. RFSURFSTIJLT+(6PTE5KTIMK@U

Ithrows
E&ce%tions will be de#onstrated in +ha%ter M@, but brie"ly they are ob0ects that can be !thrown$ out o" a #ethod i" that #ethod "ails. 6lthough only one e&ce%tion ob0ect can e#erge when you call a #ethod, a %articular #ethod #ight %roduce any nu#ber o" di""erent ty%es o" e&ce%tions, all o" which need descri%tions. So the "or# "or the e&ce%tion tag is=

Rthro:s fully-qualified-class-name description


in which f*lly6C*alifie'6class6name gives an una#biguous na#e o" an e&ce%tion class that s de"ined so#ewhere, and 'escription *which can continue on subseAuent lines, tells you why this %articular ty%e o" e&ce%tion can e#erge "ro# the #ethod call. RFSURF STIJLT+(6PTE5KTIMKMU

Ide.recated
This is used to tag "eatures that were su%erseded by an i#%roved "eature. The de%recated tag is a suggestion that you no longer use this %articular "eature, since so#eti#e in the "uture it is likely to be re#oved. 6 #ethod that is #arked 9'eprecate' causes the co#%iler to issue a warning i" it is used. RFSURFSTIJLT+(6PTE5KTIMKKU

134

Documentation e0am.le
(ere is the "irst Java %rogra# again, this ti#e with docu#entation co##ents added=

//3 c' 3MelloDate.Hava i#"ort Hava.util.B< /BB The first Thinking in Java e6a#"le "rogra#. B Dis"lays a string an! to!ay2s !ate. B Rauthor Bruce Eckel B Rauthor :::.BruceEckel.co# B Rversion .' B/ "ublic class MelloDate @ /BB %ole entry "oint to class D a""lication B R"ara# args array of string argu#ents B Rreturn &o return value B Re6ce"tion e6ce"tions &o e6ce"tions thro:n B/ "ublic static voi! #ain-%tringNO args. @ %yste#.out."rintln-8Mello, it2s3 8.< %yste#.out."rintln-ne: Date-..< A A ///3>
The "irst line o" the "ile uses #y own techniAue o" %utting a [< as a s%ecial #arker "or the co##ent line containing the source "ile na#e. That line contains the %ath in"or#ation to the "ile *in this case, cDI indicates +ha%ter K, "ollowed by the "ile na#e @. The last line also "inishes with a co##ent, and this one indicates the end o" the source code listing, which allows it to be auto#atically e&tracted "ro# the te&t o" this book and checked with a co#%iler. RFSURFSTIJLT+(6PTE5KTIMKLU

@ 6 tool that I created using Python *see www.Python.org, uses this in"or#ation to e&tract the code "iles, %ut the# in a%%ro%riate subdirectories, and create #ake"iles.

Cha ter 2! Ever)thing is an Ob>ect

135

Coding st:le
The uno""icial standard in Java is to ca%itali1e the "irst letter o" a class na#e. I" the class na#e consists o" several words, they are run together *that is, you don t use underscores to se%arate the na#es,, and the "irst letter o" each e#bedded word is ca%itali1ed, such as= RFSURF STIJLT+(6PTE5KTIMK?U

class 0llTheColorsGfThe5ainbo: @ // ...


Eor al#ost everything else= #ethods, "ields *#e#ber variables,, and ob0ect re"erence na#es, the acce%ted style is 0ust as it is "or classes e*ce t that the "irst letter o" the identi"ier is lowercase. Eor e&a#%le= RFSURF STIJLT+(6PTE5KTIMKHU

class 0llTheColorsGfThe5ainbo: @ int an$nteger5e"resentingColors< voi! changeTheMueGfTheColor-int ne:Mue. @ // ... A // ... A


)" course, you should re#e#ber that the user #ust also ty%e all these long na#es, and so be #erci"ul. RFSURFSTIJLT+(6PTE5KTIMK3U The Java code you will see in the Sun libraries also "ollows the %lace#ent o" o%en'and'close curly braces that you see used in this book. RFSURF STIJLT+(6PTE5KTIMKGU

1ummar:
In this cha%ter you have seen enough o" Java %rogra##ing to understand how to write a si#%le %rogra#, and you have gotten an overview o" the language and so#e o" its basic ideas. (owever, the e&a#%les so "ar have all been o" the "or# !do this, then do that, then do so#ething else.$ :hat i" you want the %rogra# to #ake choices, such as !i" the result o" doing this is red, do that; i" not, then do so#ething else$O The su%%ort in Java

137

"or this "unda#ental %rogra##ing activity will be covered in the ne&t cha%ter. RFSURFSTIJLT+(6PTE5KTIMKIU

/0ercises
Solutions to selected e&ercises can be "ound in the electronic docu#entThe Thinking in Java "nnotated Solution @uide, available "or a s#all "ee "ro# ,,,'0ruceEckel'com.

() Eollowing the Hello ate!8ava e&a#%le in this cha%ter, create a


!hello, world$ %rogra# that si#%ly %rints out that state#ent. /ou need only a single #ethod in your class *the !#ain$ one that gets e&ecuted when the %rogra# starts,. 5e#e#ber to #ake it static and to include the argu#ent list, even though you don t use the argu#ent list. +o#%ile the %rogra# with 8avac and run it using 8ava. I" you are using a di""erent develo%#ent environ#ent than the J7>, learn how to co#%ile and run %rogra#s in that environ#ent. RFSURFSTIJLT+(6PTE5KTIMK2U

!) Eind the code "rag#ents involving AType/ame and turn the#


into a %rogra# that co#%iles and runs. RFSURF STIJLT+(6PTE5KTIML@U

*) Turn the

ata.nly code "rag#ents into a %rogra# that co#%iles and runs. RFSURFSTIJLT+(6PTE5KTIMLMU ata.nly are
assigned to and %rinted in mainA B. RFSURF STIJLT+(6PTE5KTIMLKU

+) Modi"y E&ercise L so that the values o" the data in

,) :rite a %rogra# that includes and calls the storageA B #ethod


de"ined as a code "rag#ent in this cha%ter. RFSURF STIJLT+(6PTE5KTIMLLU

-) Turn the )taticF*n code "rag#ents into a working %rogra#. RF


SURFSTIJLT+(6PTE5KTIML?U

4) :rite a %rogra# that %rints three argu#ents taken "ro# the


co##and line. To do this, you ll need to inde& into the co##and' line array o" )trings. RFSURFSTIJLT+(6PTE5KTIMLHU

Cha ter 2! Ever)thing is an Ob>ect

138

5) Turn the AllThe-olors.fThe$ainbo( e&a#%le into a %rogra#


that co#%iles and runs. RFSURFSTIJLT+(6PTE5KTIML3U

6) Eind the code "or the second version o" Hello ate!8ava, which is
the si#%le co##ent docu#entation e&a#%le. E&ecute 8ava'oc on the "ile and view the results with your :eb browser. RFSURF STIJLT+(6PTE5KTIMLGU

(7) Turn 'ocTest into a "ile that co#%iles and then run it through
8ava'oc. Veri"y the resulting docu#entation with your :eb
browser. RFSURFSTIJLT+(6PTE5KTIMLIU

(() 6dd an (TMD list o" ite#s to the docu#entation in E&ercise M@.
RFSURFSTIJLT+(6PTE5KTIML2U

(!) Take the %rogra# in E&ercise M and add co##ent docu#entation


to it. E&tract this co##ent docu#entation into an (TMD "ile using 8ava'oc and view it with your :eb browser. RFSURF STIJLT+(6PTE5KTIM?@U RFSU

13:

*: Controlling rogram <low


RFSTIJLT+(6PTE5LTI@UDike a sentient creature, a %rogra# #ust #ani%ulate its world and #ake choices during e&ecution.
In Java you #ani%ulate ob0ects and data using o%erators, and you #ake choices with e&ecution control state#ents. Java was inherited "ro# +<<, so #ost o" these state#ents and o%erators will be "a#iliar to + and +<< %rogra##ers. Java has also added so#e i#%rove#ents and si#%li"ications. RFSURFSTIJLT+(6PTE5LTIMU I" you "ind yoursel" "loundering a bit in this cha%ter, #ake sure you go through the #ulti#edia +7 5)M bound into this book= Thinking in C! 9oundations $or Java and C++. It contains audio lectures, slides, e&ercises, and solutions s%eci"ically designed to bring you u% to s%eed with the + synta& necessary to learn Java. RFSURF STIJLT+(6PTE5LTIKU

Csing "ava o.erators


6n o%erator takes one or #ore argu#ents and %roduces a new value. The argu#ents are in a di""erent "or# than ordinary #ethod calls, but the e""ect is the sa#e. /ou should be reasonably co#"ortable with the general conce%t o" o%erators "ro# your %revious %rogra##ing e&%erience. 6ddition * L,, subtraction and unary #inus * 6,, #ulti%lication * K,, division * 5,, and assign#ent * P, all work #uch the sa#e in any %rogra##ing language. RFSURFSTIJLT+(6PTE5LTILU 6ll o%erators %roduce a value "ro# their o%erands. In addition, an o%erator can change the value o" an o%erand. This is called a side e$$ect. The #ost co##on use "or o%erators that #odi"y their o%erands is to

13;

generate the side e""ect, but you should kee% in #ind that the value %roduced is available "or your use 0ust as in o%erators without side e""ects. RFSURFSTIJLT+(6PTE5LTI?U 6l#ost all o%erators work only with %ri#itives. The e&ce%tions are GP , [PP and [=P , which work with all ob0ects *and are a %oint o" con"usion "or ob0ects,. In addition, the )tring class su%%orts [L and [LP . RFSURF STIJLT+(6PTE5LTIHU

recedence
)%erator %recedence de"ines how an e&%ression evaluates when several o%erators are %resent. Java has s%eci"ic rules that deter#ine the order o" evaluation. The easiest one to re#e#ber is that #ulti%lication and division ha%%en be"ore addition and subtraction. Progra##ers o"ten "orget the other %recedence rules, so you should use %arentheses to #ake the order o" evaluation e&%licit. Eor e&a#%le= RFSURF STIJLT+(6PTE5LTI3U

0 a ? 9 6 K ; y -

K TU<

has a very di""erent #eaning "ro# the sa#e state#ent with a %articular grou%ing o" %arentheses= RFSURFSTIJLT+(6PTE5LTIGU

0 a ? 9 6 K -; y -

./-

K TU.<

Assignment
6ssign#ent is %er"or#ed with the o%erator \. It #eans !take the value o" the right'hand side *o"ten called the rvalue, and co%y it into the le"t'hand side *o"ten called the lvalue,. 6n rvalue is any constant, variable or e&%ression that can %roduce a value, but an lvalue #ust be a distinct, na#ed variable. *That is, there #ust be a %hysical s%ace to store a value., Eor instance, you can assign a constant value to a variable * A P QR,, but you cannot assign anything to constant value9it cannot be an lvalue. */ou can t say Q P AR., RFSURFSTIJLT+(6PTE5LTIIU 6ssign#ent o" %ri#itives is Auite straight"orward. Since the %ri#itive holds the actual value and not a re"erence to an ob0ect, when you assign %ri#itives you co%y the contents "ro# one %lace to another. Eor e&a#%le,

14=

Thinking in Java

,,,'0ruceEckel'com

i" you say A P 2 "or %ri#itives, then the contents o" 2 are co%ied into A. I" you then go on to #odi"y A, 2 is naturally una""ected by this #odi"ication. 6s a %rogra##er, this is what you ve co#e to e&%ect "or #ost situations. RFSURFSTIJLT+(6PTE5LTI2U :hen you assign ob0ects, however, things change. :henever you #ani%ulate an ob0ect, what you re #ani%ulating is the re"erence, so when you assign !"ro# one ob0ect to another$ you re actually co%ying a re"erence "ro# one %lace to another. This #eans that i" you say - P "or ob0ects, you end u% with both - and %ointing to the ob0ect that, originally, only %ointed to. The "ollowing e&a#%le will de#onstrate this. RFSURFSTIJLT+(6PTE5LTIM@U (ere s the e&a#%le=

//3 c')30ssign#ent.Hava // 0ssign#ent :ith obHects is a bit tricky. class &u#ber @ int i< A "ublic class 0ssign#ent @ "ublic static voi! #ain-%tringNO &u#ber n( ? ne: &u#ber-.< &u#ber n ? ne: &u#ber-.< n(.i ? C< n .i ? I*< %yste#.out."rintln-8(3 n(.i3 8 8, n .i3 8 K n .i.< n( ? n < %yste#.out."rintln-8 3 n(.i3 8 8, n .i3 8 K n .i.< n(.i ? *< %yste#.out."rintln-8)3 n(.i3 8 8, n .i3 8 K n .i.< A A ///3> args. @

K n(.i K K n(.i K K n(.i K

The /*mber class is si#%le, and two instances o" it * n> and nI, are created within mainA B. The i value within each /*mber is given a

141

di""erent value, and then nI is assigned to n>, and n> is changed. In #any %rogra##ing languages you would e&%ect n> and nI to be inde%endent at all ti#es, but because you ve assigned a re"erence here s the out%ut you ll see= RFSURFSTIJLT+(6PTE5LTIMMU

(3 n(.i3 C, n .i3 I* 3 n(.i3 I*, n .i3 I* )3 n(.i3 *, n .i3 *


+hanging the n> ob0ect a%%ears to change the nI ob0ect as well. This is because both n> and nI contain the sa#e re"erence, which is %ointing to the sa#e ob0ect. *The original re"erence that was in n> that %ointed to the ob0ect holding a value o" 2 was overwritten during the assign#ent and e""ectively lost; its ob0ect will be cleaned u% by the garbage collector., RF SURFSTIJLT+(6PTE5LTIMKU This %heno#enon is o"ten called aliasing and it s a "unda#ental way that Java works with ob0ects. But what i" you don t want aliasing to occur in this caseO /ou could "orego the assign#ent and say= RFSURF STIJLT+(6PTE5LTIMLU

n(.i ? n .i<
This retains the two se%arate ob0ects instead o" tossing one and tying n> and nI to the sa#e ob0ect, but you ll soon reali1e that #ani%ulating the "ields within ob0ects is #essy and goes against good ob0ect'oriented design %rinci%les. This is a nontrivial to%ic, so it is le"t "or 6%%endi& 6, which is devoted to aliasing. In the #eanti#e, you should kee% in #ind that assign#ent "or ob0ects can add sur%rises. RFSURF STIJLT+(6PTE5LTIM?U

Aliasing during method calls


6liasing will also occur when you %ass an ob0ect into a #ethod=

//3 c')3PassGbHect.Hava // Passing obHects to #etho!s #ay not be :hat // you2re use! to. class Letter @ char c< A

142

Thinking in Java

,,,'0ruceEckel'com

"ublic class PassGbHect @ static voi! f-Letter y. @ y.c ? 2U2< A "ublic static voi! #ain-%tringNO args. @ Letter 6 ? ne: Letter-.< 6.c ? 2a2< %yste#.out."rintln-8(3 6.c3 8 K 6.c.< f-6.< %yste#.out."rintln-8 3 6.c3 8 K 6.c.< A A ///3>
In #any %rogra##ing languages, the #ethod fA B would a%%ear to be #aking a co%y o" its argu#ent +etter y inside the sco%e o" the #ethod. But once again a re"erence is being %assed so the line RFSURF STIJLT+(6PTE5LTIMHU

y.c ? 2U2<
is actually changing the ob0ect outside o" fA B. The out%ut shows this= RF SURFSTIJLT+(6PTE5LTIM3U

(3 6.c3 a 3 6.c3 U
6liasing and its solution is a co#%le& issue and, although you #ust wait until 6%%endi& 6 "or all the answers, you should be aware o" it at this %oint so you can watch "or %it"alls. RFSURFSTIJLT+(6PTE5LTIMGU

Mathematical o.erators
The basic #athe#atical o%erators are the sa#e as the ones available in #ost %rogra##ing languages= addition * L,, subtraction * 6,, division * 5,, #ulti%lication * K, and #odulus * S, which %roduces the re#ainder "ro# integer division,. Integer division truncates, rather than rounds, the result. RFSURFSTIJLT+(6PTE5LTIMIU Java also uses a shorthand notation to %er"or# an o%eration and an assign#ent at the sa#e ti#e. This is denoted by an o%erator "ollowed by an eAual sign, and is consistent with all the o%erators in the language

143

*whenever it #akes sense,. Eor e&a#%le, to add ? to the variable 4 and assign the result to 4, use= 4 LP Q. RFSURFSTIJLT+(6PTE5LTIM2U This e&a#%le shows the use o" the #athe#atical o%erators=

//3 c')3JathG"s.Hava // De#onstrates the #athe#atical o"erators. i#"ort Hava.util.B< "ublic class JathG"s @ // Create a shorthan! to save ty"ing3 static voi! "rt-%tring s. @ %yste#.out."rintln-s.< A // shorthan! to "rint a string an! an int3 static voi! "$nt-%tring s, int i. @ "rt-s K 8 ? 8 K i.< A // shorthan! to "rint a string an! a float3 static voi! "Llt-%tring s, float f. @ "rt-s K 8 ? 8 K f.< A "ublic static voi! #ain-%tringNO args. @ // Create a ran!o# nu#ber generator, // see!s :ith current ti#e by !efault3 5an!o# ran! ? ne: 5an!o#-.< int i, H, k< // 2V2 li#its #a6i#u# value to CC3 H ? ran!.ne6t$nt-. V (''< k ? ran!.ne6t$nt-. V (''< "$nt-8H8,H.< "$nt-8k8,k.< i ? H K k< "$nt-8H K k8, i.< i ? H - k< "$nt-8H - k8, i.< i ? k / H< "$nt-8k / H8, i.< i ? k B H< "$nt-8k B H8, i.< i ? k V H< "$nt-8k V H8, i.< H V? k< "$nt-8H V? k8, H.< // Lloating-"oint nu#ber tests3 float u,v,:< // a""lies to !oubles, too v ? ran!.ne6tLloat-.< : ? ran!.ne6tLloat-.<

144

Thinking in Java

,,,'0ruceEckel'com

"Llt-8v8, v.< "Llt-8:8, :.< u ? v K :< "Llt-8v K :8, u.< u ? v - :< "Llt-8v - :8, u.< u ? v B :< "Llt-8v B :8, u.< u ? v / :< "Llt-8v / :8, u.< // the follo:ing also :orks for // char, byte, short, int, long, // an! !ouble3 u K? v< "Llt-8u K? v8, u.< u -? v< "Llt-8u -? v8, u.< u B? v< "Llt-8u B? v8, u.< u /? v< "Llt-8u /? v8, u.< A A ///3>
The "irst thing you will see are so#e shorthand #ethods "or %rinting= the

prtA B #ethod %rints a )tring, the pIntA B %rints a )tring "ollowed by an int and the pFltA B %rints a )tring "ollowed by a float. )" course, they all ulti#ately end u% using )ystem!o*t!printlnA B. RFSURF
STIJLT+(6PTE5LTIK@U To generate nu#bers, the %rogra# "irst creates a $an'om ob0ect. Because no argu#ents are %assed during creation, Java uses the current ti#e as a seed "or the rando# nu#ber generator. The %rogra# generates a nu#ber o" di""erent ty%es o" rando# nu#bers with the $an'om ob0ect si#%ly by calling di""erent the #ethods= ne4tIntA B, ne4t+ongA B, and ne4tFloatA B *you can also call ne4t+ongA B or ne4t o*bleA B,. RF SURFSTIJLT+(6PTE5LTIKMU The #odulus o%erator, when used with the result o" the rando# nu#ber generator, li#its the result to an u%%er bound o" the o%erand #inus one *22 in this case,. RFSURFSTIJLT+(6PTE5LTIKKU

Cnar: minus and .lus o.erators


The unary #inus *', and unary %lus *<, are the sa#e o%erators as binary #inus and %lus. The co#%iler "igures out which use is intended by the way you write the e&%ression. Eor instance, the state#ent RFSURF STIJLT+(6PTE5LTIKLU

6 ? -a<

145

has an obvious #eaning. The co#%iler is able to "igure out= RFSURF STIJLT+(6PTE5LTIK?U

6 ? a B -b<
but the reader #ight get con"used, so it is clearer to say= RFSURF STIJLT+(6PTE5LTIKHU

6 ? a B --b.<
The unary #inus %roduces the negative o" the value. 4nary %lus %rovides sy##etry with unary #inus, although it doesn t have any e""ect. RFSURF STIJLT+(6PTE5LTIK3U

Auto increment and decrement


Java, like +, is "ull o" shortcuts. Shortcuts can #ake code #uch easier to ty%e, and either easier or harder to read. RFSURF STIJLT+(6PTE5LTIKGU Two o" the nicer shortcuts are the incre#ent and decre#ent o%erators *o"ten re"erred to as the auto'incre#ent and auto'decre#ent o%erators,. The decre#ent o%erator is 66 and #eans !decrease by one unit.$ The incre#ent o%erator is LL and #eans !increase by one unit.$ I" a is an int, "or e&a#%le, the e&%ression LLa is eAuivalent to * a P a L >,. Incre#ent and decre#ent o%erators %roduce the value o" the variable as a result. RF SURFSTIJLT+(6PTE5LTIKIU There are two versions o" each ty%e o" o%erator, o"ten called the %re"i& and %ost"i& versions. Pre'incre#ent #eans the LL o%erator a%%ears be"ore the variable or e&%ression, and %ost'incre#ent #eans the LL o%erator a%%ears a"ter the variable or e&%ression. Si#ilarly, %re' decre#ent #eans the 66 o%erator a%%ears be"ore the variable or e&%ression, and %ost'decre#ent #eans the 66 o%erator a%%ears a"ter the variable or e&%ression. Eor %re'incre#ent and %re'decre#ent, *i.e., LLa or 66a,, the o%eration is %er"or#ed and the value is %roduced. Eor %ost' incre#ent and %ost'decre#ent *i.e. aLL or a66,, the value is %roduced, then the o%eration is %er"or#ed. 6s an e&a#%le= RFSURF STIJLT+(6PTE5LTIK2U

//3 c')30uto$nc.Hava

147

Thinking in Java

,,,'0ruceEckel'com

// De#onstrates the KK an! -- o"erators. "ublic class 0uto$nc @ "ublic static voi! #ain-%tringNO args. @ int i ? (< "rt-8i 3 8 K i.< "rt-8KKi 3 8 K KKi.< // Pre-incre#ent "rt-8iKK 3 8 K iKK.< // Post-incre#ent "rt-8i 3 8 K i.< "rt-8--i 3 8 K --i.< // Pre-!ecre#ent "rt-8i-- 3 8 K i--.< // Post-!ecre#ent "rt-8i 3 8 K i.< A static voi! "rt-%tring s. @ %yste#.out."rintln-s.< A A ///3>
The out%ut "or this %rogra# is= RFSURFSTIJLT+(6PTE5LTIL@U

i 3 KKi iKK i 3 --i i-i 3

( 3 3 ) 3 3 (

/ou can see that "or the %re"i& "or# you get the value a"ter the o%eration has been %er"or#ed, but with the %ost"i& "or# you get the value be"ore the o%eration is %er"or#ed. These are the only o%erators *other than those involving assign#ent, that have side e""ects. *That is, they change the o%erand rather than using 0ust its value., RFSURF STIJLT+(6PTE5LTILMU The incre#ent o%erator is one e&%lanation "or the na#e +<<, i#%lying !one ste% beyond +.$ In an early Java s%eech, Bill Joy *one o" the creators,, said that !Java\+<<''$ *+ %lus %lus #inus #inus,, suggesting that Java is +<< with the unnecessary hard %arts re#oved and there"ore a #uch si#%ler language. 6s you %rogress in this book you ll see that #any

148

%arts are si#%ler, and yet Java isn t that #uch easier than +<<. RFSURF STIJLT+(6PTE5LTILKU

$elational o.erators
5elational o%erators generate a boolean result. They evaluate the relationshi% between the values o" the o%erands. 6 relational e&%ression %roduces tr*e i" the relationshi% is true, and false i" the relationshi% is untrue. The relational o%erators are less than *R,, greater than *U,, less than or eAual to *R\,, greater than or eAual to *U\,, eAuivalent *\\, and not eAuivalent *.\,. EAuivalence and noneAuivalence work s with all built' in data ty%es, but the other co#%arisons won t work with ty%e boolean. RFSURFSTIJLT+(6PTE5LTILLU

#esting ob3ect e%uivalence


The relational o%erators PP and =P also work with all ob0ects, but their #eaning o"ten con"uses the "irst'ti#e Java %rogra##er. (ere s an e&a#%le= RFSURFSTIJLT+(6PTE5LTIL?U

//3 c')3E=uivalence.Hava "ublic class E=uivalence @ "ublic static voi! #ain-%tringNO args. @ $nteger n( ? ne: $nteger-I*.< $nteger n ? ne: $nteger-I*.< %yste#.out."rintln-n( ?? n .< %yste#.out."rintln-n( 4? n .< A A ///3>
The e&%ression )ystem!o*t!printlnAn> PP nIB will %rint the result o" the boolean co#%arison within it. Surely the out%ut should be tr*e and then false, since both Integer ob0ects are the sa#e. But while the contents o" the ob0ects are the sa#e, the re"erences are not the sa#e and the o%erators PP and =P co#%are ob0ect re"erences. So the out%ut is actually false and then tr*e. Caturally, this sur%rises %eo%le at "irst. RF SURFSTIJLT+(6PTE5LTILHU

14:

Thinking in Java

,,,'0ruceEckel'com

:hat i" you want to co#%are the actual contents o" an ob0ect "or eAuivalenceO /ou #ust use the s%ecial #ethod eC*alsA B that e&ists "or all ob0ects *not %ri#itives, which work "ine with PP and =P,. (ere s how it s used= RFSURFSTIJLT+(6PTE5LTIL3U

//3 c')3E=ualsJetho!.Hava "ublic class E=ualsJetho! @ "ublic static voi! #ain-%tringNO args. @ $nteger n( ? ne: $nteger-I*.< $nteger n ? ne: $nteger-I*.< %yste#.out."rintln-n(.e=uals-n ..< A A ///3>
The result will be tr*e, as you would e&%ect. 6h, but it s not as si#%le as that. I" you create your own class, like this= RFSURF STIJLT+(6PTE5LTILGU

//3 c')3E=ualsJetho! .Hava class Walue @ int i< A "ublic class E=ualsJetho! @ "ublic static voi! #ain-%tringNO args. @ Walue v( ? ne: Walue-.< Walue v ? ne: Walue-.< v(.i ? v .i ? (''< %yste#.out."rintln-v(.e=uals-v ..< A A ///3>
you re back to sAuare one= the result is false. This is because the de"ault behavior o" eC*alsA B is to co#%are re"erences. So unless you override eC*alsA B in your new class you won t get the desired behavior. 4n"ortunately, you won t learn about overriding until +ha%ter G, but being aware o" the way eC*alsA B behaves #ight save you so#e grie" in the #eanti#e. RFSURFSTIJLT+(6PTE5LTILIU

14;

Most o" the Java library classes i#%le#ent eC*alsA B so that it co#%ares the contents o" ob0ects instead o" their re"erences. RFSURF STIJLT+(6PTE5LTIL2U

&ogical o.erators
Each o" The the logical o%erators 6C7 *NN,, )5 *]], and C)T *., %roduce s a boolean value o" tr*e or false based on the logical relationshi% o" its argu#ents. This e&a#%le uses the relational and logical o%erators= RFSURFSTIJLT+(6PTE5LTI?@U //3 c')3Bool.Hava // 5elational an! logical o"erators. i#"ort Hava.util.B< "ublic class Bool @ "ublic static voi! #ain-%tringNO args. @ 5an!o# ran! ? ne: 5an!o#-.< int i ? ran!.ne6t$nt-. V (''< int H ? ran!.ne6t$nt-. V (''< "rt-8i ? 8 K i.< "rt-8H ? 8 K H.< "rt-8i Q H is 8 K -i Q H..< "rt-8i P H is 8 K -i P H..< "rt-8i Q? H is 8 K -i Q? H..< "rt-8i P? H is 8 K -i P? H..< "rt-8i ?? H is 8 K -i ?? H..< "rt-8i 4? H is 8 K -i 4? H..< // Treating an int as a boolean is // not legal Java //4 "rt-8i DD H is 8 K -i DD H..< //4 "rt-8i XX H is 8 K -i XX H..< //4 "rt-84i is 8 K 4i.< "rt-8-i P ('. DD -H P ('. is 8 K --i P ('. DD -H P ('.. .< "rt-8-i P ('. XX -H P ('. is 8 K --i P ('. XX -H P ('.. .< A

15=

Thinking in Java

,,,'0ruceEckel'com

static voi! "rt-%tring s. @ %yste#.out."rintln-s.< A A ///3>


/ou can a%%ly 6C7, )5, or C)T to boolean values only. /ou can t use a non' boolean as i" it were a boolean in a logical e&%ression as you can in + and +<<. /ou can see the "ailed atte#%ts at doing this co##ented out with a 55= co##ent #arker. The subseAuent e&%ressions, however, %roduce boolean values using relational co#%arisons, then use logical o%erations on the results. RFSURFSTIJLT+(6PTE5LTI?MU )ne out%ut listing looked like this=

i ? 1, H ? I i Q H is true i P H is false i Q? H is true i P? H is false i ?? H is false i 4? H is true -i P ('. DD -H P ('. is false -i P ('. XX -H P ('. is true
Cote that a boolean value is auto#atically converted to an a%%ro%riate te&t "or# i" it s used where a )tring is e&%ected. RFSURF STIJLT+(6PTE5LTI?KU /ou can re%lace the de"inition "or int in the above %rogra# with any other %ri#itive data ty%e e&ce%t boolean. Be aware, however, that the co#%arison o" "loating'%oint nu#bers is very strict. 6 nu#ber that is the tiniest "raction di""erent "ro# another nu#ber is still !not eAual.$ 6 nu#ber that is the tiniest bit above 1ero is still non1ero. RFSURF STIJLT+(6PTE5LTI?LU

1hort@circuiting
:hen dealing with logical o%erators you run into a %heno#enon called !short circuiting.$ This #eans that the e&%ression will be evaluated only until the truth or "alsehood o" the entire e&%ression can be una#biguously deter#ined. 6s a result, all the %arts o" a logical

151

e&%ression #ight not be evaluated. (ere s an e&a#%le that de#onstrates short'circuiting=

//3 c')3%hortCircuit.Hava // De#onstrates short-circuiting behavior. // :ith logical o"erators. "ublic class %hortCircuit @ static boolean test(-int val. @ %yste#.out."rintln-8test(-8 K val K 8.8.< %yste#.out."rintln-8result3 8 K -val P (..< return val P (< A static boolean test -int val. @ %yste#.out."rintln-8test -8 K val K 8.8.< %yste#.out."rintln-8result3 8 K -val P ..< return val P < A static boolean test)-int val. @ %yste#.out."rintln-8test)-8 K val K 8.8.< %yste#.out."rintln-8result3 8 K -val P )..< return val P )< A "ublic static voi! #ain-%tringNO args. @ if-test(-'. DD test - . DD test)- .. %yste#.out."rintln-8e6"ression is true8.< else %yste#.out."rintln-8e6"ression is false8.< A A ///3>
Each test %er"or#s a co#%arison against the argu#ent and returns true or "alse. It also %rints in"or#ation to show you that it s being called. The tests are used in the e&%ression= RFSURFSTIJLT+(6PTE5LTI??U

if-test(-'. DD test - . DD test)- ..


/ou #ight naturally think that all three tests would be e&ecuted, but the out%ut shows otherwise= RFSURFSTIJLT+(6PTE5LTI?HU

test(-'. result3 true

152

Thinking in Java

,,,'0ruceEckel'com

test - . result3 false e6"ression is false


The "irst test %roduced a tr*e result, so the e&%ression evaluation continues. (owever, the second test %roduced a false result. Since this #eans that the whole e&%ression #ust be false, why continue evaluating the rest o" the e&%ressionO It could be e&%ensive. The reason "or short' circuiting, in "act, is %recisely that; you can get a %otential %er"or#ance increase i" all the %arts o" a logical e&%ression do not need to be evaluated. RFSURFSTIJLT+(6PTE5LTI?3U

;itwise o.erators
The bitwise o%erators allow you to #ani%ulate individual bits in an integral %ri#itive data ty%e. Bitwise o%erators %er"or# boolean algebra on the corres%onding bits in the two argu#ents to %roduce the result. RF SURFSTIJLT+(6PTE5LTI?GU The bitwise o%erators co#e "ro# + s low'level orientation; you were o"ten #ani%ulating hardware directly and had to set the bits in hardware registers. Java was originally designed to be e#bedded in TV set'to% bo&es, so this low'level orientation still #ade sense. (owever, you %robably won t use the bitwise o%erators #uch. RFSURF STIJLT+(6PTE5LTI?IU The bitwise 6C7 o%erator * ,, %roduces a one in the out%ut bit i" both in%ut bits are one; otherwise it %roduces a 1ero. The bitwise )5 o%erator * T, %roduces a one in the out%ut bit i" either in%ut bit is a one and %roduces a 1ero only i" both in%ut bits are 1ero. The bitwise EZ+D4SIVE )5, or Z)5 * U,, %roduces a one in the out%ut bit i" one or the other in%ut bit is a one, but not both. The bitwise C)T * V, also called the ones com lement o%erator, is a unary o%erator; it takes only one argu#ent. *6ll other bitwise o%erators are binary o%erators., Bitwise C)T %roduces the o%%osite o" the in%ut bit9a one i" the in%ut bit is 1ero, a 1ero i" the in%ut bit is one. RFSURFSTIJLT+(6PTE5LTI?2U The bitwise o%erators and logical o%erators use the sa#e characters, so it is hel%"ul to have a #ne#onic device to hel% you re#e#ber the

153

#eanings= since bits are !s#all,$ there is only one character in the bitwise o%erators. RFSURFSTIJLT+(6PTE5LTIH@U Bitwise o%erators can be co#bined with the P sign to unite the o%eration and assign#ent= ,P, TP and UP are all legiti#ate. *Since V is a unary o%erator it cannot be co#bined with the P sign., RFSURF STIJLT+(6PTE5LTIHMU The boolean ty%e is treated as a one'bit value so it is so#ewhat di""erent. /ou can %er"or# a bitwise 6C7, )5 and Z)5, but you can t %er"or# a bitwise C)T *%resu#ably to %revent con"usion with the logical C)T,. Eor booleans the bitwise o%erators have the sa#e e""ect as the logical o%erators e&ce%t that they do not short circuit. 6lso, bitwise o%erations on booleans include an Z)5 logical o%erator that is not included under the list o" !logical$ o%erators. /ou re %revented "ro# using booleans in shi"t e&%ressions, which is described ne&t. RFSURF STIJLT+(6PTE5LTIHKU

1hift o.erators
The shi"t o%erators also #ani%ulate bits. They can be used solely with %ri#itive, integral ty%es. The le"t'shi"t o%erator * NN, %roduces the o%erand to the le"t o" the o%erator shi"ted to the le"t by the nu#ber o" bits s%eci"ied a"ter the o%erator *inserting 1eroes at the lower'order bits,. The signed right'shi"t o%erator * OO, %roduces the o%erand to the le"t o" the o%erator shi"ted to the right by the nu#ber o" bits s%eci"ied a"ter the o%erator. The signed right shi"t OO uses sign e*tension= i" the value is %ositive, 1eroes are inserted at the higher'order bits; i" the value is negative, ones are inserted at the higher'order bits. Java has also added the unsigned right shi"t OOO, which uses ?ero e*tension= regardless o" the sign, 1eroes are inserted at the higher'order bits. This o%erator does not e&ist in + or +<<. F/GHF/GTIJ3IC."PTE-3II53H I" you shi"t a char, byte, or short, it will be %ro#oted to int be"ore the shi"t takes %lace, and the result will be an int. )nly the "ive low'order bits o" the right'hand side will be used. This %revents you "ro# shi"ting #ore than the nu#ber o" bits in an int. I" you re o%erating on a long, you ll get a long result. )nly the si& low'order bits o" the right'hand side will be

154

Thinking in Java

,,,'0ruceEckel'com

used so you can t shi"t #ore than the nu#ber o" bits in a long. RFSURF STIJLT+(6PTE5LTIH?U Shi"ts can be co#bined with the eAual sign * NNP or OOP or OOOP,. The lvalue is re%laced by the lvalue shi"ted by the rvalue. There is a %roble#, however, with the unsigned right shi"t co#bined with assign#ent. I" you use it with byte or short you don t get the correct results. Instead, these are %ro#oted to int and right shi"ted, but then truncated as they are assigned back into their variables, so you get 6> in those cases. The "ollowing e&a#%le de#onstrates this= RFSURFSTIJLT+(6PTE5LTIHHU

//3 c')3Y5%hift.Hava // Test of unsigne! right shift. "ublic class Y5%hift @ "ublic static voi! #ain-%tringNO args. @ int i ? -(< i QQQ? ('< %yste#.out."rintln-i.< long l ? -(< l QQQ? ('< %yste#.out."rintln-l.< short s ? -(< s QQQ? ('< %yste#.out."rintln-s.< byte b ? -(< b QQQ? ('< %yste#.out."rintln-b.< b ? -(< %yste#.out."rintln-bQQQ('.< A A ///3>
In the last line, the resulting value is not assigned back into b, but is %rinted directly and so the correct behavior occurs. RFSURF STIJLT+(6PTE5LTIH3U (ere s an e&a#%le that de#onstrates the use o" all the o%erators involving bits=

//3 c')3BitJani"ulation.Hava // Ysing the bit:ise o"erators.

155

i#"ort Hava.util.B< "ublic class BitJani"ulation @ "ublic static voi! #ain-%tringNO args. @ 5an!o# ran! ? ne: 5an!o#-.< int i ? ran!.ne6t$nt-.< int H ? ran!.ne6t$nt-.< "Bin$nt-8-(8, -(.< "Bin$nt-8K(8, K(.< int #a6"os ? (I*I1)+I*< "Bin$nt-8#a6"os8, #a6"os.< int #a6neg ? - (I*I1)+I1< "Bin$nt-8#a6neg8, #a6neg.< "Bin$nt-8i8, i.< "Bin$nt-8>i8, >i.< "Bin$nt-8-i8, -i.< "Bin$nt-8H8, H.< "Bin$nt-8i D H8, i D H.< "Bin$nt-8i X H8, i X H.< "Bin$nt-8i Z H8, i Z H.< "Bin$nt-8i PP ,8, i PP ,.< "Bin$nt-8i QQ ,8, i QQ ,.< "Bin$nt-8->i. QQ ,8, ->i. QQ ,.< "Bin$nt-8i QQQ ,8, i QQQ ,.< "Bin$nt-8->i. QQQ ,8, ->i. QQQ ,.< long l ? ran!.ne6tLong-.< long # ? ran!.ne6tLong-.< "BinLong-8-(L8, -(L.< "BinLong-8K(L8, K(L.< long ll ? C ))* ')+1,I**,1'*L< "BinLong-8#a6"os8, ll.< long lln ? -C ))* ')+1,I**,1'1L< "BinLong-8#a6neg8, lln.< "BinLong-8l8, l.< "BinLong-8>l8, >l.< "BinLong-8-l8, -l.< "BinLong-8#8, #.< "BinLong-8l D #8, l D #.< "BinLong-8l X #8, l X #.< "BinLong-8l Z #8, l Z #.<

157

Thinking in Java

,,,'0ruceEckel'com

"BinLong-8l PP ,8, l PP ,.< "BinLong-8l QQ ,8, l QQ ,.< "BinLong-8->l. QQ ,8, ->l. QQ ,.< "BinLong-8l QQQ ,8, l QQQ ,.< "BinLong-8->l. QQQ ,8, ->l. QQQ ,.< A static voi! "Bin$nt-%tring s, int i. @ %yste#.out."rintlns K 8, int3 8 K i K 8, binary3 8.< %yste#.out."rint-8 8.< for-int H ? )(< H Q?'< H--. if---( PP H. D i. 4? '. %yste#.out."rint-8(8.< else %yste#.out."rint-8'8.< %yste#.out."rintln-.< A static voi! "BinLong-%tring s, long l. @ %yste#.out."rintlns K 8, long3 8 K l K 8, binary3 8.< %yste#.out."rint-8 8.< for-int i ? +)< i Q?'< i--. if---(L PP i. D l. 4? '. %yste#.out."rint-8(8.< else %yste#.out."rint-8'8.< %yste#.out."rintln-.< A A ///3>
The two #ethods at the end, p2inIntA B and p2in+ongA B take an int or a long, res%ectively, and %rint it out in binary "or#at along with a descri%tive string. /ou can ignore the i#%le#entation o" these "or now. RFSURFSTIJLT+(6PTE5LTIHGU /ou ll note the use o" )ystem!o*t!printA B instead o" )ystem!o*t! printlnA B. The printA B #ethod does not e#it a new line, so it allows you to out%ut a line in %ieces. RFSURFSTIJLT+(6PTE5LTIHIU 6s well as de#onstrating the e""ect o" all the bitwise o%erators "or int and long, this e&a#%le also shows the #ini#u#, #a&i#u#, <M and 'M values

158

"or int and long so you can see what they look like. Cote that the high bit re%resents the sign= @ #eans %ositive and M #eans negative. The out%ut "or the int %ortion looks like this=

-(, int3 -(, binary3 (((((((((((((((((((((((((((((((( K(, int3 (, binary3 '''''''''''''''''''''''''''''''( #a6"os, int3 (I*I1)+I*, binary3 '((((((((((((((((((((((((((((((( #a6neg, int3 - (I*I1)+I1, binary3 (''''''''''''''''''''''''''''''' i, int3 ,C'1(*(+, binary3 ''''''(((''''('(('''''(((((('('' >i, int3 -,C'1(*(*, binary3 (((((('''(((('(''(((((''''''('(( -i, int3 -,C'1(*(+, binary3 (((((('''(((('(''(((((''''''(('' H, int3 (C11,'C,+, binary3 ''''('(((('(('('''(((''(('''(('' i D H, int3 ,1* '+II, binary3 ''''''(((''''''''''''''((''''('' i X H, int3 (CC ( ' 1, binary3 ''''('(((('(((((('((('(((((((('' i Z H, int3 (I'IC()1I, binary3 ''''(''''('(((((('((('(''((((''' i PP ,, int3 (1C'+(IC( , binary3 '(((''''('(('''''(((((('(''''''' i QQ ,, int3 (1I+)'), binary3 '''''''''''(((''''('(('''''((((( ->i. QQ ,, int3 -(1I+)'I, binary3 ((((((((((('''(((('(''(((((''''' i QQQ ,, int3 (1I+)'), binary3 '''''''''''(((''''('(('''''((((( ->i. QQQ ,, int3 () )*(I I, binary3 '''''(((((('''(((('(''((((('''''
The binary re%resentation o" the nu#bers is re"erred to as signed t,oJs com lement. RFSURFSTIJLT+(6PTE5LTIH2U

15:

Thinking in Java

,,,'0ruceEckel'com

#ernar: if@else o.erator


This o%erator is unusual because it has three o%erands. It is truly an o%erator because it %roduces a value, unlike the ordinary i"'else state#ent that you ll see in the ne&t section o" this cha%ter. The e&%ression is o" the "or#= RFSURFSTIJLT+(6PTE5LTI3@U

boolean-e6" [ value' 3 value(


I" boolean/e* evaluates to tr*e, value= is evaluated and its result beco#es the value %roduced by the o%erator. I" boolean/e* is false, value1 is evaluated and its result beco#es the value %roduced by the o%erator. RFSURFSTIJLT+(6PTE5LTI3MU )" course, you could use an ordinary if6else state#ent *described later,, but the ternary o%erator is #uch terser. 6lthough + *where this o%erator originated, %rides itsel" on being a terse language, and the ternary o%erator #ight have been introduced %artly "or e""iciency, you should be so#ewhat wary o" using it on an everyday basis9it s easy to %roduce unreadable code. RFSURFSTIJLT+(6PTE5LTI3KU The conditional o%erator can be used "or its side e""ects or "or the value it %roduces, but in general you want the value since that s what #akes the o%erator distinct "ro# the if6else. (ere s an e&a#%le= RFSURF STIJLT+(6PTE5LTI3LU

static int ternary-int i. @ return i P (' [ i B ('' 3 i B ('< A


/ou can see that this code is #ore co#%act than what you d need to write without the ternary o%erator= RFSURFSTIJLT+(6PTE5LTI3?U

static int alternative-int i. @ if -i P ('. return i B (''< else return i B ('< A


The second "or# is easier to understand, and doesn t reAuire a lot #ore ty%ing. So be sure to %onder your reasons when choosing the ternary

15;

o%erator Y it s generally warranted when you re setting a variable to one o" two values. RFSURFSTIJLT+(6PTE5LTI3HU

#he comma o.erator


The co##a is used in + and +<< not only as a se%arator in "unction argu#ent lists, but also as an o%erator "or seAuential evaluation. The sole %lace that the co##a o erator is used in Java is in for loo%s, which will be described later in this cha%ter. RFSURFSTIJLT+(6PTE5LTI33U

String o.erator F
There s one s%ecial usage o" an o%erator in Java= the L o%erator can be used to concatenate strings, as you ve already seen. It see#s a natural use o" the L even though it doesn t "it with the traditional way that L is used. This ca%ability see#ed like a good idea in +<<, so o erator overloading was added to +<< to allow the +<< %rogra##er to add #eanings to al#ost any o%erator. 4n"ortunately, o%erator overloading co#bined with so#e o" the other restrictions in +<< turns out to be a "airly co#%licated "eature "or %rogra##ers to design into their classes. 6lthough o%erator overloading would have been #uch si#%ler to i#%le#ent in Java than it was in +<<, this "eature was still considered too co#%le&, so Java %rogra##ers cannot i#%le#ent their own overloaded o%erators as +<< %rogra##ers can. RFSURFSTIJLT+(6PTE5LTI3GU The use o" the )tring L has so#e interesting behavior. I" an e&%ression begins with a )tring, then all o%erands that "ollow #ust be )trings *re#e#ber that the co#%iler will turn a Auoted seAuence o" characters into a )tring,= RFSURFSTIJLT+(6PTE5LTI3IU

int 6 ? ', y ? (, U ? < %tring s%tring ? 86, y, U 8< %yste#.out."rintln-s%tring K 6 K y K U.<


(ere, the Java co#%iler will convert 4, y, and 7 into their )tring re%resentations instead o" adding the# together "irst. 6nd i" you say=

%yste#.out."rintln-6 K s%tring.<
Java will turn 4 into a )tring. RFSURFSTIJLT+(6PTE5LTI32U

17=

Thinking in Java

,,,'0ruceEckel'com

Common .itfalls when using o.erators


)ne o" the %it"alls when using o%erators is trying to get away without %arentheses when you are even the least bit uncertain about how an e&%ression will evaluate. This is still true in Java. RFSURF STIJLT+(6PTE5LTIG@U 6n e&tre#ely co##on error in + and +<< looks like this=

:hile-6 ? y. @ // .... A
The %rogra##er was trying to test "or eAuivalence * PP, rather than do an assign#ent. In + and +<< the result o" this assign#ent will always be tr*e i" y is non1ero, and you ll %robably get an in"inite loo%. In Java, the result o" this e&%ression is not a boolean, and the co#%iler e&%ects a boolean and won t convert "ro# an int, so it will conveniently give you a co#%ile'ti#e error and catch the %roble# be"ore you ever try to run the %rogra#. So the %it"all never ha%%ens in Java. *The only ti#e you won t get a co#%ile'ti#e error is when 4 and y are boolean, in which case 4 P y is a legal e&%ression, and in the above case, %robably an error., RFSURF STIJLT+(6PTE5LTIGMU 6 si#ilar %roble# in + and +<< is using bitwise 6C7 and )5 instead o" the logical versions. Bitwise 6C7 and )5 use one o" the characters * , or T, while logical 6C7 and )5 use two * ,, and TT,. Just as with P and PP, it s easy to ty%e 0ust one character instead o" two. In Java, the co#%iler again %revents this because it won t let you cavalierly use one ty%e where it doesn t belong. RFSURFSTIJLT+(6PTE5LTIGKU

Casting o.erators
The word cast is used in the sense o" !casting into a #old.$ Java will auto#atically change one ty%e o" data into another when a%%ro%riate. Eor instance, i" you assign an integral value to a "loating'%oint variable, the co#%iler will auto#atically convert the int to a float. +asting allows you

171

to #ake this ty%e conversion e&%licit, or to "orce it when it wouldn t nor#ally ha%%en. RFSURFSTIJLT+(6PTE5LTIGLU To %er"or# a cast, %ut the desired data ty%e *including all #odi"iers, inside %arentheses to the le"t o" any value. (ere s an e&a#%le=

voi! casts-. @ int i ? ''< long l ? -long.i< long l ? -long. ''< A


6s you can see, it s %ossible to %er"or# a cast on a nu#eric value as well as on a variable. In both casts shown here, however, the cast is su%er"luous, since the co#%iler will auto#atically %ro#ote an int value to a long when necessary. (owever, you are allowed to use su%er"luous casts in to #ake a %oint or to #ake your code #ore clear. In other situations, a cast #ay be essential 0ust to get the code to co#%ile. RFSURF STIJLT+(6PTE5LTIG?U In + and +<<, casting can cause so#e headaches. In Java, casting is sa"e, with the e&ce%tion that when you %er"or# a so'called narro,ing conversion *that is, when you go "ro# a data ty%e that can hold #ore in"or#ation to one that doesn t hold as #uch, you run the risk o" losing in"or#ation. (ere the co#%iler "orces you to do a cast, in e""ect saying !this can be a dangerous thing to do9i" you want #e to do it anyway you #ust #ake the cast e&%licit.$ :ith a ,idening conversion an e&%licit cast is not needed because the new ty%e will #ore than hold the in"or#ation "ro# the old ty%e so that no in"or#ation is ever lost. RFSURF STIJLT+(6PTE5LTIGHU Java allows you to cast any %ri#itive ty%e to any other %ri#itive ty%e, e&ce%t "or boolean, which doesn t allow any casting at all. +lass ty%es do not allow casting. To convert one to the other there #ust be s%ecial #ethods. * )tring is a s%ecial case, and you ll "ind out later in this book that ob0ects can be cast within a $amil) o" ty%es; an .ak can be cast to a Tree and vice'versa, but not to a "oreign ty%e such as a $ock., RFSURF STIJLT+(6PTE5LTIG3U

172

Thinking in Java

,,,'0ruceEckel'com

&iterals
)rdinarily when you insert a literal value into a %rogra# the co#%iler knows e&actly what ty%e to #ake it. So#eti#es, however, the ty%e is a#biguous. :hen this ha%%ens you #ust guide the co#%iler by adding so#e e&tra in"or#ation in the "or# o" characters associated with the literal value. The "ollowing code shows these characters= RFSURF STIJLT+(6PTE5LTIGGU

//3 c')3Literals.Hava "ublic class Literals @ char c ? '6ffff< // #a6 char he6 value byte b ? '6*f< // #a6 byte he6 value short s ? '6*fff< // #a6 short he6 value int i( ? '6 f< // Me6a!eci#al -lo:ercase. int i ? '9 L< // Me6a!eci#al -u""ercase. int i) ? '(**< // Gctal -lea!ing Uero. // Me6 an! Gct also :ork :ith long. long n( ? ''L< // long suffi6 long n ? ''l< // long suffi6 long n) ? ''< //4 long l+- ''.< // not allo:e! float f( ? (< float f ? (L< // float suffi6 float f) ? (f< // float suffi6 float fI ? (e-I,f< // (' to the "o:er float f, ? (eKCf< // float suffi6 !ouble !( ? (!< // !ouble suffi6 !ouble ! ? (D< // !ouble suffi6 !ouble !) ? I*eI*!< // (' to the "o:er A ///3>
(e&adeci#al *base M3,, which works with all the integral data ty%es, is denoted by a leading D4 or DX "ollowed by @92 and a9" either in u%%er or lowercase. I" you try to initiali1e a variable with a value bigger than it can hold *regardless o" the nu#erical "or# o" the value,, the co#%iler will give you an error #essage. Cotice in the above code the #a&i#u# %ossible he&adeci#al values "or char, byte, and short. I" you e&ceed these, the co#%iler will auto#atically #ake the value an int and tell you

173

that you need a narrowing cast "or the assign#ent. /ou ll know you ve ste%%ed over the line. RFSURFSTIJLT+(6PTE5LTIGIU )ctal *base I, is denoted by a leading 1ero in the nu#ber and digits "ro# @'G. There is no literal re%resentation "or binary nu#bers in +, +<< or Java. RFSURFSTIJLT+(6PTE5LTIG2U 6 trailing character a"ter a literal value establishes its ty%e. 4%%er or lowercase + #eans long, u%%er or lowercase F #eans float and u%%er or lowercase #eans 'o*ble. N5WON5WTIJJX-HA#T&$JXIYDO E&%onents use a notation that I ve always "ound rather dis#aying= >!J? e6QZf. In science and engineering, [e re"ers to the base o" natural logarith#s, a%%ro&i#ately K.GMI. *6 #ore %recise 'o*ble value is available in Java as 1ath!&., This is used in e&%onentiation e&%ressions such as M.L2 & e'?G, which #eans M.L2 & K.GMI '?G. (owever, when E)5T56C was invented they decided that e would naturally #ean !ten to the %ower, $ which is an odd decision because E)5T56C was designed "or science and engineering and one would think its designers would be sensitive about introducing such an a#biguity. @ 6t any rate, this custo# was "ollowed in +, +<< and now Java. So i" you re used to thinking in ter#s o" e as the base o" natural logarith#s, you #ust do a #ental translation when you see an e&%ression such as >!J? e6QZf in Java; it #eans M.L2 & M@ '?G. N5WON5WTIJJX-HA#T&$JXIY>O Cote that you don t need to use the trailing character when the co#%iler can "igure out the a%%ro%riate ty%e. :ith RFSURF STIJLT+(6PTE5LTIIKU

long n) ?

''<

@ John >irkha# writes, !I started co#%uting in M23K using E)5T56C II on an IBM M3K@. 6t that ti#e, and throughout the M23@s and into the M2G@s, E)5T56C was an all u%%ercase language. This %robably started because #any o" the early in%ut devices were old telety%e units that used H bit Baudot code, which had no lowercase ca%ability. The [E in the e&%onential notation was also always u%%er case and was never con"used with the natural logarith# base [e , which is always lowercase. The [E si#%ly stood "or e&%onential, which was "or the base o" the nu#ber syste# used9usually M@. 6t the ti#e octal was also widely used by %rogra##ers. 6lthough I never saw it used, i" I had seen an octal nu#ber in e&%onential notation I would have considered it to be base I. The "irst ti#e I re#e#ber seeing an e&%onential using a lowercase [e was in the late M2G@s and I also "ound it con"using. The %roble# arose as lowercase cre%t into E)5T56C, not at its beginning. :e actually had "unctions to use i" you really wanted to use the natural logarith# base, but they were all u%%ercase.$

174

Thinking in Java

,,,'0ruceEckel'com

there s no a#biguity, so an + a"ter the K@@ would be su%er"luous. (owever, with RFSURFSTIJLT+(6PTE5LTIILU

float fI ? (e-I*f< // (' to the "o:er


the co#%iler nor#ally takes e&%onential nu#bers as doubles, so without the trailing f it will give you an error telling you that you #ust use a cast to convert 'o*ble to float. RFSURFSTIJLT+(6PTE5LTII?U

romotion
/ou ll discover that i" you %er"or# any #athe#atical or bitwise o%erations on %ri#itive data ty%es that are s#aller than an int *that is, char, byte, or short,, those values will be %ro#oted to int be"ore %er"or#ing the o%erations, and the resulting value will be o" ty%e int. So i" you want to assign back into the s#aller ty%e, you #ust use a cast. *6nd, since you re assigning back into a s#aller ty%e, you #ight be losing in"or#ation., In general, the largest data ty%e in an e&%ression is the one that deter#ines the si1e o" the result o" that e&%ression; i" you #ulti%ly a float and a 'o*ble, the result will be 'o*ble; i" you add an int and a long, the result will be long. RFSURFSTIJLT+(6PTE5LTIIHU

"ava has no Jsi?eofK


In + and +<<, the si7eofA B o%erator satis"ies a s%eci"ic need= it tells you the nu#ber o" bytes allocated "or data ite#s. The #ost co#%elling need "or si7eofA B in + and +<< is %ortability. 7i""erent data ty%es #ight be di""erent si1es on di""erent #achines, so the %rogra##er #ust "ind out how big those ty%es are when %er"or#ing o%erations that are sensitive to si1e. Eor e&a#%le, one co#%uter #ight store integers in LK bits, whereas another #ight store integers as M3 bits. Progra#s could store larger values in integers on the "irst #achine. 6s you #ight i#agine, %ortability is a huge headache "or + and +<< %rogra##ers. RFSURF STIJLT+(6PTE5LTII3U Java does not need a si7eofA B o%erator "or this %ur%ose because all the data ty%es are the sa#e si1e on all #achines. /ou do not need to think about %ortability on this level9it is designed into the language. RFSURF STIJLT+(6PTE5LTIIGU

175

recedence revisited
4%on hearing #e co#%lain about the co#%le&ity o" re#e#bering o%erator %recedence during one o" #y se#inars, a student suggested a #ne#onic that is si#ultaneously a co##entary= !4lcer 6ddicts 5eally Dike + 6 lot.$

1nemon ic
4lcer 6ddicts 5eally Dike + 6 Dot

.perator type
4nary 6rith#etic *and shi"t, 5elational Dogical *and bitwise, +onditional *ternary, 6ssign#ent

.perators L 6 LL66 K 5 S L 6 NN OO O N OP NP PP =P ,, TT , T U AO2[X<: P *and co#%ound assign#ent like KP,

)" course, with the shi"t and bitwise o%erators distributed around the table it is not a %er"ect #ne#onic, but "or non'bit o%erations it works.

A com.endium of o.erators
The "ollowing e&a#%le shows which %ri#itive data ty%es can be used with %articular o%erators. Basically, it is the sa#e e&a#%le re%eated over and over, but using di""erent %ri#itive data ty%es. The "ile will co#%ile without error because the lines that would cause errors are co##ented out with a 55=. RFSURFSTIJLT+(6PTE5LTIIIU

//3 c')30llG"s.Hava // Tests all the o"erators on all the // "ri#itive !ata ty"es to sho: :hich // ones are acce"te! by the Java co#"iler. "ublic class 0llG"s @ // To acce"t the results of a boolean test3 voi! f-boolean b. @A voi! boolTest-boolean 6, boolean y. @ // 0rith#etic o"erators3

177

Thinking in Java

,,,'0ruceEckel'com

//4 6 ? 6 B y< //4 6 ? 6 / y< //4 6 ? 6 V y< //4 6 ? 6 K y< //4 6 ? 6 - y< //4 6KK< //4 6--< //4 6 ? Ky< //4 6 ? -y< // 5elational an! logical3 //4 f-6 Q y.< //4 f-6 Q? y.< //4 f-6 P y.< //4 f-6 P? y.< f-6 ?? y.< f-6 4? y.< f-4y.< 6 ? 6 DD y< 6 ? 6 XX y< // Bit:ise o"erators3 //4 6 ? >y< 6 ? 6 D y< 6 ? 6 X y< 6 ? 6 Z y< //4 6 ? 6 PP (< //4 6 ? 6 QQ (< //4 6 ? 6 QQQ (< // Co#"oun! assign#ent3 //4 6 K? y< //4 6 -? y< //4 6 B? y< //4 6 /? y< //4 6 V? y< //4 6 PP? (< //4 6 QQ? (< //4 6 QQQ? (< 6 D? y< 6 Z? y< 6 X? y< // Casting3 //4 char c ? -char.6<

178

//4 //4 //4 //4 //4 //4

byte B ? -byte.6< short s ? -short.6< int i ? -int.6< long l ? -long.6< float f ? -float.6< !ouble ! ? -!ouble.6<

A voi! charTest-char 6, char y. @ // 0rith#etic o"erators3 6 ? -char.-6 B y.< 6 ? -char.-6 / y.< 6 ? -char.-6 V y.< 6 ? -char.-6 K y.< 6 ? -char.-6 - y.< 6KK< 6--< 6 ? -char.Ky< 6 ? -char.-y< // 5elational an! logical3 f-6 Q y.< f-6 Q? y.< f-6 P y.< f-6 P? y.< f-6 ?? y.< f-6 4? y.< //4 f-46.< //4 f-6 DD y.< //4 f-6 XX y.< // Bit:ise o"erators3 6? -char.>y< 6 ? -char.-6 D y.< 6 ? -char.-6 X y.< 6 ? -char.-6 Z y.< 6 ? -char.-6 PP (.< 6 ? -char.-6 QQ (.< 6 ? -char.-6 QQQ (.< // Co#"oun! assign#ent3 6 K? y< 6 -? y< 6 B? y< 6 /? y<

17:

Thinking in Java

,,,'0ruceEckel'com

6 V? y< 6 PP? (< 6 QQ? (< 6 QQQ? (< 6 D? y< 6 Z? y< 6 X? y< // Casting3 //4 boolean b ? -boolean.6< byte B ? -byte.6< short s ? -short.6< int i ? -int.6< long l ? -long.6< float f ? -float.6< !ouble ! ? -!ouble.6< A voi! byteTest-byte 6, byte y. @ // 0rith#etic o"erators3 6 ? -byte.-6B y.< 6 ? -byte.-6 / y.< 6 ? -byte.-6 V y.< 6 ? -byte.-6 K y.< 6 ? -byte.-6 - y.< 6KK< 6--< 6 ? -byte.K y< 6 ? -byte.- y< // 5elational an! logical3 f-6 Q y.< f-6 Q? y.< f-6 P y.< f-6 P? y.< f-6 ?? y.< f-6 4? y.< //4 f-46.< //4 f-6 DD y.< //4 f-6 XX y.< // Bit:ise o"erators3 6 ? -byte.>y< 6 ? -byte.-6 D y.< 6 ? -byte.-6 X y.<

17;

6 ? -byte.-6 Z y.< 6 ? -byte.-6 PP (.< 6 ? -byte.-6 QQ (.< 6 ? -byte.-6 QQQ (.< // Co#"oun! assign#ent3 6 K? y< 6 -? y< 6 B? y< 6 /? y< 6 V? y< 6 PP? (< 6 QQ? (< 6 QQQ? (< 6 D? y< 6 Z? y< 6 X? y< // Casting3 //4 boolean b ? -boolean.6< char c ? -char.6< short s ? -short.6< int i ? -int.6< long l ? -long.6< float f ? -float.6< !ouble ! ? -!ouble.6< A voi! shortTest-short 6, short y. @ // 0rith#etic o"erators3 6 ? -short.-6 B y.< 6 ? -short.-6 / y.< 6 ? -short.-6 V y.< 6 ? -short.-6 K y.< 6 ? -short.-6 - y.< 6KK< 6--< 6 ? -short.Ky< 6 ? -short.-y< // 5elational an! logical3 f-6 Q y.< f-6 Q? y.< f-6 P y.< f-6 P? y.<

18=

Thinking in Java

,,,'0ruceEckel'com

f-6 ?? y.< f-6 4? y.< //4 f-46.< //4 f-6 DD y.< //4 f-6 XX y.< // Bit:ise o"erators3 6 ? -short.>y< 6 ? -short.-6 D y.< 6 ? -short.-6 X y.< 6 ? -short.-6 Z y.< 6 ? -short.-6 PP (.< 6 ? -short.-6 QQ (.< 6 ? -short.-6 QQQ (.< // Co#"oun! assign#ent3 6 K? y< 6 -? y< 6 B? y< 6 /? y< 6 V? y< 6 PP? (< 6 QQ? (< 6 QQQ? (< 6 D? y< 6 Z? y< 6 X? y< // Casting3 //4 boolean b ? -boolean.6< char c ? -char.6< byte B ? -byte.6< int i ? -int.6< long l ? -long.6< float f ? -float.6< !ouble ! ? -!ouble.6< A voi! intTest-int 6, int y. @ // 0rith#etic o"erators3 6 ? 6 B y< 6 ? 6 / y< 6 ? 6 V y< 6 ? 6 K y< 6 ? 6 - y<

181

6KK< 6--< 6 ? Ky< 6 ? -y< // 5elational an! logical3 f-6 Q y.< f-6 Q? y.< f-6 P y.< f-6 P? y.< f-6 ?? y.< f-6 4? y.< //4 f-46.< //4 f-6 DD y.< //4 f-6 XX y.< // Bit:ise o"erators3 6 ? >y< 6 ? 6 D y< 6 ? 6 X y< 6 ? 6 Z y< 6 ? 6 PP (< 6 ? 6 QQ (< 6 ? 6 QQQ (< // Co#"oun! assign#ent3 6 K? y< 6 -? y< 6 B? y< 6 /? y< 6 V? y< 6 PP? (< 6 QQ? (< 6 QQQ? (< 6 D? y< 6 Z? y< 6 X? y< // Casting3 //4 boolean b ? -boolean.6< char c ? -char.6< byte B ? -byte.6< short s ? -short.6< long l ? -long.6< float f ? -float.6<

182

Thinking in Java

,,,'0ruceEckel'com

!ouble ! ? -!ouble.6< A voi! longTest-long 6, long y. @ // 0rith#etic o"erators3 6 ? 6 B y< 6 ? 6 / y< 6 ? 6 V y< 6 ? 6 K y< 6 ? 6 - y< 6KK< 6--< 6 ? Ky< 6 ? -y< // 5elational an! logical3 f-6 Q y.< f-6 Q? y.< f-6 P y.< f-6 P? y.< f-6 ?? y.< f-6 4? y.< //4 f-46.< //4 f-6 DD y.< //4 f-6 XX y.< // Bit:ise o"erators3 6 ? >y< 6 ? 6 D y< 6 ? 6 X y< 6 ? 6 Z y< 6 ? 6 PP (< 6 ? 6 QQ (< 6 ? 6 QQQ (< // Co#"oun! assign#ent3 6 K? y< 6 -? y< 6 B? y< 6 /? y< 6 V? y< 6 PP? (< 6 QQ? (< 6 QQQ? (< 6 D? y<

183

6 Z? y< 6 X? y< // Casting3 //4 boolean b ? -boolean.6< char c ? -char.6< byte B ? -byte.6< short s ? -short.6< int i ? -int.6< float f ? -float.6< !ouble ! ? -!ouble.6< A voi! floatTest-float 6, float y. @ // 0rith#etic o"erators3 6 ? 6 B y< 6 ? 6 / y< 6 ? 6 V y< 6 ? 6 K y< 6 ? 6 - y< 6KK< 6--< 6 ? Ky< 6 ? -y< // 5elational an! logical3 f-6 Q y.< f-6 Q? y.< f-6 P y.< f-6 P? y.< f-6 ?? y.< f-6 4? y.< //4 f-46.< //4 f-6 DD y.< //4 f-6 XX y.< // Bit:ise o"erators3 //4 6 ? >y< //4 6 ? 6 D y< //4 6 ? 6 X y< //4 6 ? 6 Z y< //4 6 ? 6 PP (< //4 6 ? 6 QQ (< //4 6 ? 6 QQQ (< // Co#"oun! assign#ent3

184

Thinking in Java

,,,'0ruceEckel'com

6 K? y< 6 -? y< 6 B? y< 6 /? y< 6 V? y< //4 6 PP? (< //4 6 QQ? (< //4 6 QQQ? (< //4 6 D? y< //4 6 Z? y< //4 6 X? y< // Casting3 //4 boolean b ? -boolean.6< char c ? -char.6< byte B ? -byte.6< short s ? -short.6< int i ? -int.6< long l ? -long.6< !ouble ! ? -!ouble.6< A voi! !oubleTest-!ouble 6, !ouble y. @ // 0rith#etic o"erators3 6 ? 6 B y< 6 ? 6 / y< 6 ? 6 V y< 6 ? 6 K y< 6 ? 6 - y< 6KK< 6--< 6 ? Ky< 6 ? -y< // 5elational an! logical3 f-6 Q y.< f-6 Q? y.< f-6 P y.< f-6 P? y.< f-6 ?? y.< f-6 4? y.< //4 f-46.< //4 f-6 DD y.< //4 f-6 XX y.<

185

// Bit:ise o"erators3 //4 6 ? >y< //4 6 ? 6 D y< //4 6 ? 6 X y< //4 6 ? 6 Z y< //4 6 ? 6 PP (< //4 6 ? 6 QQ (< //4 6 ? 6 QQQ (< // Co#"oun! assign#ent3 6 K? y< 6 -? y< 6 B? y< 6 /? y< 6 V? y< //4 6 PP? (< //4 6 QQ? (< //4 6 QQQ? (< //4 6 D? y< //4 6 Z? y< //4 6 X? y< // Casting3 //4 boolean b ? -boolean.6< char c ? -char.6< byte B ? -byte.6< short s ? -short.6< int i ? -int.6< long l ? -long.6< float f ? -float.6< A A ///3>
Cote that boolean is Auite li#ited. /ou can assign to it the values tr*e and false, and you can test it "or truth or "alsehood, but you cannot add booleans or %er"or# any other ty%e o" o%eration on the#. RFSURF STIJLT+(6PTE5LTII2U In char, byte, and short you can see the e""ect o" %ro#otion with the arith#etic o%erators. Each arith#etic o%eration on any o" those ty%es results in an int result, which #ust be e&%licitly cast back to the original ty%e *a narrowing conversion that #ight lose in"or#ation, to assign back to that ty%e. :ith int values, however, you do not need to cast, because

187

Thinking in Java

,,,'0ruceEckel'com

everything is already an int. 7on t be lulled into thinking everything is sa"e, though. I" you #ulti%ly two ints that are big enough, you ll over"low the result. The "ollowing e&a#%le de#onstrates this= RFSURF STIJLT+(6PTE5LTI2@U

//3 c')3Gverflo:.Hava // %ur"rise4 Java lets you overflo:. "ublic class Gverflo: @ "ublic static voi! #ain-%tringNO args. @ int big ? '6*fffffff< // #a6 int value "rt-8big ? 8 K big.< int bigger ? big B I< "rt-8bigger ? 8 K bigger.< A static voi! "rt-%tring s. @ %yste#.out."rintln-s.< A A ///3>
The out%ut o" this is=

big ? (I*I1)+I* bigger ? -I


and you get no errors or warnings "ro# the co#%iler, and no e&ce%tions at run'ti#e. Java is good, but it s not that good. RFSURF STIJLT+(6PTE5LTI2MU +o#%ound assign#ents do not reAuire casts "or char, byte, or short, even though they are %er"or#ing %ro#otions that have the sa#e results as the direct arith#etic o%erations. )n the other hand, the lack o" the cast certainly si#%li"ies the code. RFSURFSTIJLT+(6PTE5LTI2KU /ou can see that, with the e&ce%tion o" boolean, any %ri#itive ty%e can be cast to any other %ri#itive ty%e. 6gain, you #ust be aware o" the e""ect o" a narrowing conversion when casting to a s#aller ty%e, otherwise you #ight unknowingly lose in"or#ation during the cast. RFSURF STIJLT+(6PTE5LTI2LU

188

/0ecution control
Java uses all o" + s e&ecution control state#ents, so i" you ve %rogra##ed with + or +<< then #ost o" what you see will be "a#iliar. Most %rocedural %rogra##ing languages have so#e kind o" control state#ents, and there is o"ten overla% a#ong languages. In Java, the keywords include if6else, (hile, 'o6(hile, for, and a selection state#ent called s(itch. Java does not, however, su%%ort the #uch'#aligned goto *which can still be the #ost e&%edient way to solve certain ty%es o" %roble#s,. /ou can still do a goto'like 0u#%, but it is #uch #ore constrained than a ty%ical goto. RFSURFSTIJLT+(6PTE5LTI2?U

true and false


6ll conditional state#ents use the truth or "alsehood o" a conditional e&%ression to deter#ine the e&ecution %ath. 6n e&a#%le o" a conditional e&%ression is A PP 2. This uses the conditional o%erator PP to see i" the value o" A is eAuivalent to the value o" 2. The e&%ression returns tr*e or false. 6ny o" the relational o%erators you ve seen earlier in this cha%ter can be used to %roduce a conditional state#ent. Cote that Java doesn t allow you to use a nu#ber as a boolean, even though it s allowed in + and +<< *where truth is non1ero and "alsehood is 1ero,. I" you want to use a non' boolean in a boolean test, such as ifAaB, you #ust "irst convert it to a boolean value using a conditional e&%ression, such as ifAa =P DB. RFSURFSTIJLT+(6PTE5LTI2HU

if@else
The if6else state#ent is %robably the #ost basic way to control %rogra# "low. The else is o%tional, so you can use if in two "or#s=

if(Boolean-e6"ression) state#ent
or

if(Boolean-e6"ression) state#ent else

18:

Thinking in Java

,,,'0ruceEckel'com

state#ent
The conditional #ust %roduce a boolean result. The statement #eans either a si#%le state#ent ter#inated by a se#icolon or a co#%ound state#ent, which is a grou% o" si#%le state#ents enclosed in braces. 6ny ti#e the word ! statement$ is used, it always i#%lies that the state#ent can be si#%le or co#%ound. RFSURFSTIJLT+(6PTE5LTI23U 6s an e&a#%le o" if6else, here is a testA B #ethod that will tell you whether a guess is above, below, or eAuivalent to a target nu#ber=

//3 c')3$fElse.Hava "ublic class $fElse @ static int test-int testval, int target. @ int result ? '< if-testval Q target. result ? K(< else if-testval P target. result ? -(< else result ? '< // Jatch return result< A "ublic static voi! #ain-%tringNO args. @ %yste#.out."rintln-test-(', ,..< %yste#.out."rintln-test-,, ('..< %yste#.out."rintln-test-,, ,..< A A ///3> It is conventional to indent the body o" a control "low state#ent so the reader #ight easily deter#ine where it begins and ends.

return
The ret*rn keyword has two %ur%oses= it s%eci"ies what value a #ethod will return *i" it doesn t have a voi' return value, and it causes that value to be returned i##ediately. The testA B #ethod above can be rewritten to take advantage o" this= RFSURFSTIJLT+(6PTE5LTI2GU

//3 c')3$fElse .Hava "ublic class $fElse @

18;

static int test-int testval, int target. @ int result ? '< if-testval Q target. return K(< else if-testval P target. return -(< else return '< // Jatch A "ublic static voi! #ain-%tringNO args. @ %yste#.out."rintln-test-(', ,..< %yste#.out."rintln-test-,, ('..< %yste#.out."rintln-test-,, ,..< A A ///3>
There s no need "or else because the #ethod will not continue a"ter e&ecuting a ret*rn. RFSURFSTIJLT+(6PTE5LTI2IU

Iteration
(hile, 'o6(hile and for control loo%ing and are so#eti#es classi"ied as iteration statements. 6 statement re%eats until the controlling 0oolean' e* ression evaluates to "alse. The "or# "or a (hile loo% is while(Boolean-e6"ression) state#ent
The 0oolean/e* ression is evaluated once at the beginning o" the loo% and again be"ore each "urther iteration o" the statement. RFSURF STIJLT+(6PTE5LTI22U (ere s a si#%le e&a#%le that generates rando# nu#bers until a %articular condition is #et=

//3 c')3\hileTest.Hava // De#onstrates the :hile loo". "ublic class \hileTest @ "ublic static voi! #ain-%tringNO args. @ !ouble r ? '< :hile-r P '.CC!. @

1:=

Thinking in Java

,,,'0ruceEckel'com

r ? Jath.ran!o#-.< %yste#.out."rintln-r.< A A A ///3>


This uses the static #ethod ran'omA B in the 1ath library, which generates a 'o*ble value between @ and M. *It includes @, but not M., The conditional e&%ression "or the (hile says !kee% doing this loo% until the nu#ber is @.22 or greater.$ Each ti#e you run this %rogra# you ll get a di""erent'si1ed list o" nu#bers. RFSURFSTIJLT+(6PTE5LTIM@@U

do@while
The "or# "or 'o6(hile is

do state#ent while(Boolean-e6"ression);
The sole di""erence between (hile and 'o6(hile is that the state#ent o" the 'o6(hile always e&ecutes at least once, even i" the e&%ression evaluates to "alse the "irst ti#e. In a (hile, i" the conditional is "alse the "irst ti#e the state#ent never e&ecutes. In %ractice, 'o6(hile is less co##on than (hile. RFSURFSTIJLT+(6PTE5LTIM@MU

for
6 for loo% %er"or#s initiali1ation be"ore the "irst iteration. Then it %er"or#s conditional testing and, at the end o" each iteration, so#e "or# o" !ste%%ing.$ The "or# o" the for loo% is=

for(initialiUation; Boolean-e6"ression; ste") state#ent


6ny o" the e&%ressions initiali?ation, 0oolean/e* ression or ste can be e#%ty. The e&%ression is tested be"ore each iteration, and as soon as it evaluates to false e&ecution will continue at the line "ollowing the for state#ent. 6t the end o" each loo%, the ste e&ecutes. RFSURF STIJLT+(6PTE5LTIM@KU

1:1

for loo%s are usually used "or !counting$ tasks= //3 c')3ListCharacters.Hava // De#onstrates 8for8 loo" by listing // all the 0%C$$ characters. "ublic class ListCharacters @ "ublic static voi! #ain-%tringNO args. @ for- char c ? '< c P ( 1< cKK. if -c 4? + . // 0&%$ Clear screen %yste#.out."rintln8value3 8 K -int.c K 8 character3 8 K c.< A A ///3>
Cote that the variable c is de"ined at the %oint where it is used, inside the control e&%ression o" the for loo%, rather than at the beginning o" the block denoted by the o%en curly brace. The sco%e o" c is the e&%ression controlled by the for. RFSURFSTIJLT+(6PTE5LTIM@LU Traditional %rocedural languages like + reAuire that all variables be de"ined at the beginning o" a block so when the co#%iler creates a block it can allocate s%ace "or those variables. In Java and +<< you can s%read your variable declarations throughout the block, de"ining the# at the %oint that you need the#. This allows a #ore natural coding style and #akes code easier to understand. RFSURFSTIJLT+(6PTE5LTIM@?U /ou can de"ine #ulti%le variables within a for state#ent, but they #ust be o" the sa#e ty%e=

for-int i ? ', H ? (< i P (' DD H 4? ((< iKK, HKK. /B bo!y of for loo" B/<
The int de"inition in the for state#ent covers both i and 8. The ability to de"ine variables in the control e&%ression is li#ited to the for loo%. /ou cannot use this a%%roach with any o" the other selection or iteration state#ents. RFSURFSTIJLT+(6PTE5LTIM@HU

1:2

Thinking in Java

,,,'0ruceEckel'com

#he comma o.erator


Earlier in this cha%ter I stated that the co##a o erator *not the co##a se arator, which is used to se%arate de"initions and "unction argu#ents, has only one use in Java= in the control e&%ression o" a for loo%. In both the initiali1ation and ste% %ortions o" the control e&%ression you can have a nu#ber o" state#ents se%arated by co##as, and those state#ents will be evaluated seAuentially. The %revious bit o" code uses this ability. (ere s another e&a#%le=

//3 c')3Co##aG"erator.Hava "ublic class Co##aG"erator @ "ublic static voi! #ain-%tringNO args. @ for-int i ? (, H ? i K ('< i P ,< iKK, H ? i B . @ %yste#.out."rintln-8i? 8 K i K 8 H? 8 K H.< A A A ///3>
(ere s the out%ut= RFSURFSTIJLT+(6PTE5LTIM@3U

i? ( H? (( i? H? I i? ) H? + i? I H? 1
/ou can see that in both the initiali1ation and ste% %ortions the state#ents are evaluated in seAuential order. 6lso, the initiali1ation %ortion can have any nu#ber o" de"initions o$ one t) e. RFSURF STIJLT+(6PTE5LTIM@GU

break and continue


Inside the body o" any o" the iteration state#ents you can also control the "low o" the loo% by using break and contin*e. break Auits the loo% without e&ecuting the rest o" the state#ents in the loo%. contin*e sto%s the e&ecution o" the current iteration and goes back to the beginning o" the loo% to begin the ne&t iteration. RFSURFSTIJLT+(6PTE5LTIM@IU

1:3

This %rogra# shows e&a#%les o" break and contin*e within for and

(hile loo%s= //3 c')3Break0n!Continue.Hava // De#onstrates break an! continue key:or!s. "ublic class Break0n!Continue @ "ublic static voi! #ain-%tringNO args. @ for-int i ? '< i P (''< iKK. @ if-i ?? *I. break< // Gut of for loo" if-i V C 4? '. continue< // &e6t iteration %yste#.out."rintln-i.< A int i ? '< // 0n 8infinite loo"83 :hile-true. @ iKK< int H ? i B *< if-H ?? ( +C. break< // Gut of loo" if-i V (' 4? '. continue< // To" of loo" %yste#.out."rintln-i.< A A A ///3>
In the for loo% the value o" i never gets to M@@ because the break state#ent breaks out o" the loo% when i is G?. Cor#ally, you d use a break like this only i" you didn t know when the ter#inating condition was going to occur. The contin*e state#ent causes e&ecution to go back to the to% o" the iteration loo% *thus incre#enting i, whenever i is not evenly divisible by 2. :hen it is, the value is %rinted. RFSURF STIJLT+(6PTE5LTIM@2U The second %ortion shows an !in"inite loo%$ that would, in theory, continue "orever. (owever, inside the loo% there is a break state#ent that will break out o" the loo%. In addition, you ll see that the contin*e #oves back to the to% o" the loo% without co#%leting the re#ainder. *Thus %rinting ha%%ens in the second loo% only when the value o" i is divisible by M@., The out%ut is=

'

1:4

Thinking in Java

,,,'0ruceEckel'com

C (1 * )+ I, ,I +) * (' ' )' I'


The value @ is %rinted because @ ^ 2 %roduces @. RFSURF STIJLT+(6PTE5LTIMM@U 6 second "or# o" the in"inite loo% is forARRB. The co#%iler treats both (hileAtr*eB and forARRB in the sa#e way so whichever one you use is a #atter o" %rogra##ing taste. RFSURFSTIJLT+(6PTE5LTIMMMU

#he infamous JgotoK


The goto keyword has been %resent in %rogra##ing languages "ro# the beginning. Indeed, goto was the genesis o" %rogra# control in asse#bly language= !i" condition 6, then 0u#% here, otherwise 0u#% there.$ I" you read the asse#bly code that is ulti#ately generated by virtually any co#%iler, you ll see that %rogra# control contains #any 0u#%s. (owever, a goto is a 0u#% at the source'code level, and that s what brought it into disre%ute. I" a %rogra# will always 0u#% "ro# one %oint to another, isn t there so#e way to reorgani1e the code so the "low o" control is not so 0u#%yO goto "ell into true dis"avor with the %ublication o" the "a#ous !8oto considered har#"ul$ %a%er by Edsger 7i0kstra, and since then goto' bashing has been a %o%ular s%ort, with advocates o" the cast'out keyword scurrying "or cover. RFSURFSTIJLT+(6PTE5LTIMMKU 6s is ty%ical in situations like this, the #iddle ground is the #ost "ruit"ul. The %roble# is not the use o" goto, but the overuse o" goto9in rare situations goto is actually the best way to structure control "low. N5WON5

WTIJJX-HA#T&$JXI>>JO

1:5

6lthough goto is a reserved word in Java, it is not used in the language; Java has no goto. (owever, it does have so#ething that looks a bit like a 0u#% tied in with the break and contin*e keywords. It s not a 0u#% but rather a way to break out o" an iteration state#ent. The reason it s o"ten thrown in with discussions o" goto is because it uses the sa#e #echanis#= a label. RFSURFSTIJLT+(6PTE5LTIMM?U 6 label is an identi"ier "ollowed by a colon, like this=

label(3
The onl) %lace a label is use"ul in Java is right be"ore an iteration state#ent. 6nd that #eans right be"ore9it does no good to %ut any other state#ent between the label and the iteration. 6nd the sole reason to %ut a label be"ore an iteration is i" you re going to nest another iteration or a switch inside it. That s because the break and contin*e keywords will nor#ally interru%t only the current loo%, but when used with a label they ll interru%t the loo%s u% to where the label e&ists= RFSURF STIJLT+(6PTE5LTIMMHU

label(3 outer-iteration @ inner-iteration @ //] break< // ( //] continue< // //] continue label(< // ) //] break label(< // I A A
In case M, the break breaks out o" the inner iteration and you end u% in the outer iteration. In case K, the contin*e #oves back to the beginning o" the inner iteration. But in case L, the contin*e label> breaks out o" the inner iteration and the outer iteration, all the way back to label>. Then it does in "act continue the iteration, but starting at the outer iteration. In case ?, the break label> also breaks all the way out to

1:7

Thinking in Java

,,,'0ruceEckel'com

label>, but it does not re'enter the iteration. It actually does break out o"
both iterations. RFSURFSTIJLT+(6PTE5LTIMM3U (ere is an e&a#%le using for loo%s=

//3 c')3Labele!Lor.Hava // Java^s 8labele! for8 loo". "ublic class Labele!Lor @ "ublic static voi! #ain-%tringNO args. @ int i ? '< outer3 // Can2t have state#ents here for-< true <. @ // infinite loo" inner3 // Can2t have state#ents here for-< i P ('< iKK. @ "rt-8i ? 8 K i.< if-i ?? . @ "rt-8continue8.< continue< A if-i ?? ). @ "rt-8break8.< iKK< // Gther:ise i never // gets incre#ente!. break< A if-i ?? *. @ "rt-8continue outer8.< iKK< // Gther:ise i never // gets incre#ente!. continue outer< A if-i ?? 1. @ "rt-8break outer8.< break outer< A for-int k ? '< k P ,< kKK. @ if-k ?? ). @ "rt-8continue inner8.< continue inner< A

1:8

A A A // Can2t break or continue // to labels here A static voi! "rt-%tring s. @ %yste#.out."rintln-s.< A A ///3>
This uses the prtA B #ethod that has been de"ined in the other e&a#%les. RFSURFSTIJLT+(6PTE5LTIMMGU Cote that break breaks out o" the for loo%, and that the incre#ent' e&%ression doesn t occur until the end o" the %ass through the for loo%. Since break ski%s the incre#ent e&%ression, the incre#ent is %er"or#ed directly in the case o" i PP J. The contin*e o*ter state#ent in the case o" i PP Z also goes to the to% o" the loo% and also ski%s the incre#ent, so it too is incre#ented directly. RFSURFSTIJLT+(6PTE5LTIMMIU (ere is the out%ut=

i ? ' continue inner i ? ( continue inner i ? continue i ? ) break i ? I continue inner i ? , continue inner i ? + continue inner i ? * continue outer i ? 1 break outer

1::

Thinking in Java

,,,'0ruceEckel'com

I" not "or the break o*ter state#ent, there would be no way to get out o" the outer loo% "ro# within an inner loo%, since break by itsel" can break out o" only the inner#ost loo%. *The sa#e is true "or contin*e., RFSURF STIJLT+(6PTE5LTIMM2U )" course, in the cases where breaking out o" a loo% will also e&it the #ethod, you can si#%ly use a ret*rn. RFSURFSTIJLT+(6PTE5LTIMK@U (ere is a de#onstration o" labeled break and contin*e state#ents with (hile loo%s=

//3 c')3Labele!\hile.Hava // Java2s 8labele! :hile8 loo". "ublic class Labele!\hile @ "ublic static voi! #ain-%tringNO args. @ int i ? '< outer3 :hile-true. @ "rt-8Guter :hile loo"8.< :hile-true. @ iKK< "rt-8i ? 8 K i.< if-i ?? (. @ "rt-8continue8.< continue< A if-i ?? ). @ "rt-8continue outer8.< continue outer< A if-i ?? ,. @ "rt-8break8.< break< A if-i ?? *. @ "rt-8break outer8.< break outer< A A A

1:;

A static voi! "rt-%tring s. @ %yste#.out."rintln-s.< A A ///3>


The sa#e rules hold true "or (hile= RFSURFSTIJLT+(6PTE5LTIMKMU

!5) !6) *7) *()

6 %lain contin*e goes to the to% o" the inner#ost loo% and continues. 6 labeled contin*e goes to the label and re'enters the loo% right a"ter that label. 6 break !dro%s out o" the botto#$ o" the loo%. 6 labeled break dro%s out o" the botto# o" the end o" the loo% denoted by the label.

The out%ut o" this #ethod #akes it clear= RFSURF STIJLT+(6PTE5LTIMKKU

Guter :hile loo" i ? ( continue i ? i ? ) continue outer Guter :hile loo" i ? I i ? , break Guter :hile loo" i ? + i ? * break outer
It s i#%ortant to re#e#ber that the onl) reason to use labels in Java is when you have nested loo%s and you want to break or contin*e through #ore than one nested level. RFSURFSTIJLT+(6PTE5LTIMKLU In 7i0kstra s !goto considered har#"ul$ %a%er, what he s%eci"ically ob0ected to was the labels, not the goto. (e observed that the nu#ber o"

1;=

Thinking in Java

,,,'0ruceEckel'com

bugs see#s to increase with the nu#ber o" labels in a %rogra#. Dabels and gotos #ake %rogra#s di""icult to analy1e statically, since it introduces cycles in the %rogra# e&ecution gra%h. Cote that Java labels don t su""er "ro# this %roble#, since they are constrained in their %lace#ent and can t be used to trans"er control in an ad hoc #anner. It s also interesting to note that this is a case where a language "eature is #ade #ore use"ul by restricting the %ower o" the state#ent. RFSURFSTIJLT+(6PTE5LTIMK?U

switch
The s(itch is so#eti#es classi"ied as a selection statement. The s(itch state#ent selects "ro# a#ong %ieces o" code based on the value o" an integral e&%ression. Its "or# is= RFSURFSTIJLT+(6PTE5LTIMKHU

switch(integral-selector) { case integral-value( : state#ent; case integral-value : state#ent; case integral-value) : state#ent; case integral-valueI : state#ent; case integral-value, : state#ent; // ... default: state#ent; A

break; break; break; break; break;

Integral/selector is an e&%ression that %roduces an integral value. The s(itch co#%ares the result o" integral/selector to each integral/value. I" it "inds a #atch, the corres%onding statement *si#%le or co#%ound, e&ecutes. I" no #atch occurs, the 'efa*lt statement e&ecutes. RFSURF STIJLT+(6PTE5LTIMK3U /ou will notice in the above de"inition that each case ends with a break, which causes e&ecution to 0u#% to the end o" the s(itch body. This is the conventional way to build a s(itch state#ent, but the break is o%tional. I" it is #issing, the code "or the "ollowing case state#ents e&ecute until a break is encountered. 6lthough you don t usually want this kind o" behavior, it can be use"ul to an e&%erienced %rogra##er. Cote the last state#ent, "ollowing the 'efa*lt, doesn t have a break because the e&ecution 0ust "alls through to where the break would have taken it anyway. /ou could %ut a break at the end o" the 'efa*lt state#ent with

1;1

no har# i" you considered it i#%ortant "or style s sake. RFSURF STIJLT+(6PTE5LTIMKGU The s(itch state#ent is a clean way to i#%le#ent #ulti'way selection *i. e., selecting "ro# a#ong a nu#ber o" di""erent e&ecution %aths,, but it reAuires a selector that evaluates to an integral value such as int or char. I" you want to use, "or e&a#%le, a string or a "loating'%oint nu#ber as a selector, it won t work in a s(itch state#ent. Eor non'integral ty%es, you #ust use a series o" if state#ents. RFSURFSTIJLT+(6PTE5LTIMKIU (ere s an e&a#%le that creates letters rando#ly and deter#ines whether they re vowels or consonants= RFSURFSTIJLT+(6PTE5LTIMK2U

//3 c')3Wo:els0n!Consonants.Hava // De#onstrates the s:itch state#ent. "ublic class Wo:els0n!Consonants @ "ublic static voi! #ain-%tringNO args. @ for-int i ? '< i P (''< iKK. @ char c ? -char.-Jath.ran!o#-. B + K 2a2.< %yste#.out."rint-c K 83 8.< s:itch-c. @ case 2a23 case 2e23 case 2i23 case 2o23 case 2u23 %yste#.out."rintln-8vo:el8.< break< case 2y23 case 2:23 %yste#.out."rintln8%o#eti#es a vo:el8.< break< !efault3 %yste#.out."rintln-8consonant8.< A A A A ///3>

1;2

Thinking in Java

,,,'0ruceEckel'com

Since 1ath!ran'omA B generates a value between @ and M, you need only #ulti%ly it by the u%%er bound o" the range o" nu#bers you want to %roduce *K3 "or the letters in the al%habet, and add an o""set to establish the lower bound. RFSURFSTIJLT+(6PTE5LTIML@U 6lthough it a%%ears you re switching on a character here, the s(itch state#ent is actually using the integral value o" the character. The singly' Auoted characters in the case state#ents also %roduce integral values that are used "or co#%arison. RFSURFSTIJLT+(6PTE5LTIMLMU Cotice how the cases can be !stacked$ on to% o" each other to %rovide #ulti%le #atches "or a %articular %iece o" code. /ou should also be aware that it s essential to %ut the break state#ent at the end o" a %articular case, otherwise control will si#%ly dro% through and continue %rocessing on the ne&t case. RFSURFSTIJLT+(6PTE5LTIMLKU

Calculation details
The state#ent= char c ? -char.-Jath.ran!o#-. B + K 2a2.<

deserves a closer look. 1ath!ran'omA B %roduces a 'o*ble, so the value K3 is converted to a 'o*ble to %er"or# the #ulti%lication, which also %roduces a 'o*ble. This #eans that Ga; #ust be converted to a 'o*ble to %er"or# the addition. The 'o*ble result is turned back into a char with a cast. RFSURFSTIJLT+(6PTE5LTIMLLU :hat does the cast to char doO That is, i" you have the value K2.G and you cast it to a char, is the resulting value L@ or K2O The answer to this can be seen in this e&a#%le= RFSURFSTIJLT+(6PTE5LTIML?U

//3 c')3Casting&u#bers.Hava // \hat ha""ens :hen you cast a float // or !ouble to an integral value[ "ublic class Casting&u#bers @ "ublic static voi! #ain-%tringNO args. @ !ouble above ? '.*, belo: ? '.I< %yste#.out."rintln-8above3 8 K above.<

1;3

%yste#.out."rintln-8belo:3 8 K belo:.< %yste#.out."rintln8-int.above3 8 K -int.above.< %yste#.out."rintln8-int.belo:3 8 K -int.belo:.< %yste#.out."rintln8-char.-2a2 K above.3 8 K -char.-2a2 K above..< %yste#.out."rintln8-char.-2a2 K belo:.3 8 K -char.-2a2 K belo:..< A A ///3>
The out%ut is= RFSURFSTIJLT+(6PTE5LTIMLHU

above3 '.* belo:3 '.I -int.above3 ' -int.belo:3 ' -char.-2a2 K above.3 a -char.-2a2 K belo:.3 a
So the answer is that casting "ro# a float or 'o*ble to an integral value always truncates. RFSURFSTIJLT+(6PTE5LTIML3U 6 second Auestion concerns 1ath!ran'omA B. 7oes it %roduce a value "ro# 1ero to one, inclusive or e&clusive o" the value [M O In #ath lingo, is it *@,M,, or _@,M`, or *@,M` or _@,M,O *The sAuare bracket #eans !includes$ whereas the %arenthesis #eans !doesn t include.$, 6gain, a test %rogra# #ight %rovide the answer= RFSURFSTIJLT+(6PTE5LTIMLGU

//3 c')35an!o#Boun!s.Hava // Does Jath.ran!o#-. "ro!uce '.' an! (.'[ "ublic class 5an!o#Boun!s @ static voi! usage-. @ %yste#.out."rintln-8Ysage3 _n_t8 K 85an!o#Boun!s lo:er_n_t8 K 85an!o#Boun!s u""er8.< %yste#.e6it-(.< A

1;4

Thinking in Java

,,,'0ruceEckel'com

"ublic static voi! #ain-%tringNO args. @ if-args.length 4? (. usage-.< if-argsN'O.e=uals-8lo:er8.. @ :hile-Jath.ran!o#-. 4? '.'. < // `ee" trying %yste#.out."rintln-8Pro!uce! '.'48.< A else if-argsN'O.e=uals-8u""er8.. @ :hile-Jath.ran!o#-. 4? (.'. < // `ee" trying %yste#.out."rintln-8Pro!uce! (.'48.< A else usage-.< A A ///3>
To run the %rogra#, you ty%e a co##and line o" either= RFSURF STIJLT+(6PTE5LTIMLIU

Hava 5an!o#Boun!s lo:er


or

Hava 5an!o#Boun!s u""er


In both cases you are "orced to break out o" the %rogra# #anually, so it would a ear that 1ath!ran'omA B never %roduces either @.@ or M.@. But this is where such an e&%eri#ent can be deceiving. I" you consider @ that there are about K 3K di""erent double "ractions between @ and M, the
@ +huck 6llison writes= The total nu#ber o" nu#bers in a "loating'%oint nu#ber syste# is IA16mL>BbUAp6>B L > where b is the base *usually K,, p is the %recision *digits in the #antissa,, 1 is the largest e&%onent, and m is the s#allest e&%onent. IEEE GH? uses= 1 P >DIJ, m P 6>DII, p P @J, b P I so the total nu#ber o" nu#bers is IA>DIJL>DIIL>BIU@I P IAAIU>D6>B L AIU>D6>BBIU@I P AIU>D6>BIU@Q P IU\Q 6 IU@Q (al" o" these nu#bers *corres%onding to e&%onents in the range _'M@KK, @`, are less than M in #agnitude *both %ositive and negative,, so MF? o" that e&%ression, or Ka3K ' KaHK < M *a%%ro&i#ately Ka3K, is in the range _@,M,. See #y %a%er at htt%=FFwww."reshsources. co#FM22H@@3a.ht# *last o" te&t,.

1;5

likelihood o" reaching any one value e&%eri#entally #ight e&ceed the li"eti#e o" one co#%uter, or even one e&%eri#enter. It turns out that @.@ is included in the out%ut o" 1ath!ran'omA B. )r, in #ath lingo, it is _@,M,. RFSURFSTIJLT+(6PTE5LTIML2U

1ummar:
This cha%ter concludes the study o" "unda#ental "eatures that a%%ear in #ost %rogra##ing languages= calculation, o%erator %recedence, ty%e casting, and selection and iteration. Cow you re ready to begin taking ste%s that #ove you closer to the world o" ob0ect'oriented %rogra##ing. The ne&t cha%ter will cover the i#%ortant issues o" initiali1ation and cleanu% o" ob0ects, "ollowed in the subseAuent cha%ter by the essential conce%t o" i#%le#entation hiding. RFSURFSTIJLT+(6PTE5LTIM?@U

/0ercises
Solutions to selected e&ercises can be "ound in the electronic docu#entThe Thinking in Java "nnotated Solution @uide, available "or a s#all "ee "ro# ,,,'0ruceEckel'com.

(*) There are two e&%ressions in the section labeled !%recedence$


early in this cha%ter. Put these e&%ressions into a %rogra# and de#onstrate that they %roduce di""erent results. RFSURF STIJLT+(6PTE5LTIM?MU

(+) Put the #ethods ternaryA B and alternativeA B into a working


%rogra#. RFSURFSTIJLT+(6PTE5LTIM?KU

(,) Ero# the sections labeled !i"'else$ and !return$, %ut the #ethods
testA B and testIA B into a working %rogra#. #odi"y the two test A B #ethods so that testval is tested to see i" it is within the range between *and including, the argu#ents begin and en'. RFSURF
STIJLT+(6PTE5LTIM?LU

(-) :rite a %rogra# that %rints values "ro# one to M@@. RFSURF
STIJLT+(6PTE5LTIM??U

1;7

Thinking in Java

,,,'0ruceEckel'com

(4) Modi"y E&ercise ? so that the %rogra# e&its by using the break
keyword at value ?G. Try using ret*rn instead. RFSURF STIJLT+(6PTE5LTIM?HU

(5) :rite a "unction that takes two )tring argu#ents, and uses all
the boolean co#%arisons to co#%are the two )trings and %rint the results. Eor the PP and =P, also %er"or# the eC*alsA B test. In mainA B, call your "unction with so#e di""erent )tring ob0ects. RF SURFSTIJLT+(6PTE5LTIM?3U

(6) :rite a %rogra# that generates KH rando# int values. Eor each
value, use an if'else state#ent to classi"y it as greater than, less than or eAual to a second rando#ly'generated value. RFSURF STIJLT+(6PTE5LTIM?GU

!7) Modi"y E&ercise G so that your code is surrounded by an


!in"inite$ (hile loo%. It will then run until you interru%t it "ro# the keyboard *ty%ically by %ressing +ontrol'+,. RFSURF STIJLT+(6PTE5LTIM?IU

!() :rite a %rogra# that uses two nested for loo%s and the #odulus
o%erator * S, to detect and %rint %ri#e nu#bers *integral nu#bers that are not evenly divisible by any other nu#bers e&ce%t "or the#selves and M,. RFSURFSTIJLT+(6PTE5LTIM?2U

!!) +reate a s(itch state#ent that %rints a #essage "or each case,
and %ut the s(itch inside a for loo% that tries each case. Put a break a"ter each case and test it, then re#ove the breaks and see what ha%%ens. RFSU

1;8

+: Initiali?ation L Cleanu.
RFSTIJLT+(6PTE5?TI@U6s the co#%uter revolution %rogresses, !unsa"e$ %rogra##ing has beco#e one o" the #a0or cul%rits that #akes %rogra##ing e&%ensive.
Two o" these sa"ety issues are initiali?ation and cleanu . Many + bugs occur when the %rogra##er "orgets to initiali1e a variable. This is es%ecially true with libraries when users don t know how to initiali1e a library co#%onent, or even that they #ust. +leanu% is a s%ecial %roble# because it s easy to "orget about an ele#ent when you re done with it, since it no longer concerns you. Thus, the resources used by that ele#ent are retained and you can easily end u% running out o" resources *#ost notably, #e#ory,. RFSURFSTIJLT+(6PTE5?TIMU +<< introduced the conce%t o" a constructor, a s%ecial #ethod auto#atically called when an ob0ect is created. Java also ado%ted the constructor, and in addition has a garbage collector that auto#atically releases #e#ory resources when they re no longer being used. This cha%ter e&a#ines the issues o" initiali1ation and cleanu%, and their su%%ort in Java. RFSURFSTIJLT+(6PTE5?TIKU

'uaranteed initiali?ation with the constructor


/ou can i#agine creating a #ethod called initiali7eA B "or every class you write. The na#e is a hint that it should be called be"ore using the ob0ect. 4n"ortunately, this #eans the user #ust re#e#ber to call the #ethod. In

1;:

Java, the class designer can guarantee initiali1ation o" every ob0ect by %roviding a s%ecial #ethod called a constructor. I" a class has a constructor, Java auto#atically calls that constructor when an ob0ect is created, be"ore users can even get their hands on it. So initiali1ation is guaranteed. RFSURFSTIJLT+(6PTE5?TILU The ne&t challenge is what to na#e this #ethod. There are two issues. The "irst is that any na#e you use could clash with a na#e you #ight like to use as a #e#ber in the class. The second is that because the co#%iler is res%onsible "or calling the constructor, it #ust always know which #ethod to call. The +<< solution see#s the easiest and #ost logical, so it s also used in Java= the na#e o" the constructor is the sa#e as the na#e o" the class. It #akes sense that such a #ethod will be called auto#atically on initiali1ation. RFSURFSTIJLT+(6PTE5?TI?U (ere s a si#%le class with a constructor=

//3 c'I3%i#"leConstructor.Hava // De#onstration of a si#"le constructor. class 5ock @ 5ock-. @ // This is the constructor %yste#.out."rintln-8Creating 5ock8.< A A "ublic class %i#"leConstructor @ "ublic static voi! #ain-%tringNO args. @ for-int i ? '< i P ('< iKK. ne: 5ock-.< A A ///3>
Cow, when an ob0ect is created= RFSURFSTIJLT+(6PTE5?TIHU

ne: 5ock-.<
storage is allocated and the constructor is called. It is guaranteed that the ob0ect will be %ro%erly initiali1ed be"ore you can get your hands on it. RF SURFSTIJLT+(6PTE5?TI3U

Cha ter 4! Initiali?ation & Cleanu

1;;

Cote that the coding style o" #aking the "irst letter o" all #ethods lowercase does not a%%ly to constructors, since the na#e o" the constructor #ust #atch the na#e o" the class e*actl). RFSURF STIJLT+(6PTE5?TIGU Dike any #ethod, the constructor can have argu#ents to allow you to s%eci"y ho, an ob0ect is created. The above e&a#%le can easily be changed so the constructor takes an argu#ent=

//3 c'I3%i#"leConstructor .Hava // Constructors can have argu#ents. class 5ock @ 5ock -int i. @ %yste#.out."rintln8Creating 5ock nu#ber 8 K i.< A A "ublic class %i#"leConstructor @ "ublic static voi! #ain-%tringNO args. @ for-int i ? '< i P ('< iKK. ne: 5ock -i.< A A ///3>
+onstructor argu#ents %rovide you with a way to %rovide %ara#eters "or the initiali1ation o" an ob0ect. Eor e&a#%le, i" the class Tree has a constructor that takes a single integer argu#ent denoting the height o" the tree, you would create a Tree ob0ect like this= RFSURF STIJLT+(6PTE5?TIIU

Tree t ? ne: Tree-( .<

// ( -foot tree

I" TreeAintB is your only constructor, then the co#%iler won t let you create a Tree ob0ect any other way. RFSURFSTIJLT+(6PTE5?TI2U +onstructors eli#inate a large class o" %roble#s and #ake the code easier to read. In the %receding code "rag#ent, "or e&a#%le, you don t see an e&%licit call to so#e initiali7eA B #ethod that is conce%tually se%arate "ro# de"inition. In Java, de"inition and initiali1ation are uni"ied conce%ts 9you can t have one without the other. RFSURFSTIJLT+(6PTE5?TIM@U

2==

The constructor is an unusual ty%e o" #ethod because it has no return value. This is distinctly di""erent "ro# a voi' return value, in which the #ethod returns nothing but you still have the o%tion to #ake it return so#ething else. +onstructors return nothing and you don t have an o%tion. I" there was a return value, and i" you could select your own, the co#%iler would so#ehow need to know what to do with that return value. RFSURFSTIJLT+(6PTE5?TIMMU

Method overloading
)ne o" the i#%ortant "eatures in any %rogra##ing language is the use o" na#es. :hen you create an ob0ect, you give a na#e to a region o" storage. 6 #ethod is a na#e "or an action. By using na#es to describe your syste#, you create a %rogra# that is easier "or %eo%le to understand and change. It s a lot like writing %rose9the goal is to co##unicate with your readers. RFSURFSTIJLT+(6PTE5?TIMKU /ou re"er to all ob0ects and #ethods by using na#es. :ell'chosen na#es #ake it easier "or you and others to understand your code. RFSURF STIJLT+(6PTE5?TIMLU 6 %roble# arises when #a%%ing the conce%t o" nuance in hu#an language onto a %rogra##ing language. )"ten, the sa#e word e&%resses a nu#ber o" di""erent #eanings9it s overloaded. This is use"ul, es%ecially when it co#es to trivial di""erences. /ou say !wash the shirt,$ !wash the car,$ and !wash the dog.$ It would be silly to be "orced to say, !shirt:ash the shirt,$ !car:ash the car,$ and !dog:ash the dog$ 0ust so the listener doesn t need to #ake any distinction about the action %er"or#ed. Most hu#an languages are redundant, so even i" you #iss a "ew words, you can still deter#ine the #eaning. :e don t need uniAue identi"iers9we can deduce #eaning "ro# conte&t. RFSURFSTIJLT+(6PTE5?TIM?U Most %rogra##ing languages *+ in %articular, reAuire you to have a uniAue identi"ier "or each "unction. So you could not have one "unction called printA B "or %rinting integers and another called printA B "or %rinting "loats9each "unction reAuires a uniAue na#e. RFSURF STIJLT+(6PTE5?TIMHU

Cha ter 4! Initiali?ation & Cleanu

2=1

In Java *and +<<,, another "actor "orces the overloading o" #ethod na#es= the constructor. Because the constructor s na#e is %redeter#ined by the na#e o" the class, there can be only one constructor na#e. But what i" you want to create an ob0ect in #ore than one wayO Eor e&a#%le, su%%ose you build a class that can initiali1e itsel" in a standard way or by reading in"or#ation "ro# a "ile. /ou need two constructors, one that takes no argu#ents *the de$ault constructor, also called the no/arg constructor,, and one that takes a )tring as an argu#ent, which is the na#e o" the "ile "ro# which to initiali1e the ob0ect. Both are constructors, so they #ust have the sa#e na#e9the na#e o" the class. Thus, method overloading is essential to allow the sa#e #ethod na#e to be used with di""erent argu#ent ty%es. 6nd although #ethod overloading is a #ust "or constructors, it s a general convenience and can be used with any #ethod. RFSURFSTIJLT+(6PTE5?TIM3U (ere s an e&a#%le that shows both overloaded constructors and overloaded ordinary #ethods=

//3 c'I3Gverloa!ing.Hava // De#onstration of both constructor // an! or!inary #etho! overloa!ing. i#"ort Hava.util.B< class Tree @ int height< Tree-. @ "rt-8Planting a see!ling8.< height ? '< A Tree-int i. @ "rt-8Creating ne: Tree that is 8 K i K 8 feet tall8.< height ? i< A voi! info-. @ "rt-8Tree is 8 K height K 8 feet tall8.< A voi! info-%tring s. @ "rt-s K 83 Tree is 8

2=2

K height K 8 feet tall8.< A static voi! "rt-%tring s. @ %yste#.out."rintln-s.< A A "ublic class Gverloa!ing @ "ublic static voi! #ain-%tringNO args. @ for-int i ? '< i P ,< iKK. @ Tree t ? ne: Tree-i.< t.info-.< t.info-8overloa!e! #etho!8.< A // Gverloa!e! constructor3 ne: Tree-.< A A ///3>
6 Tree ob0ect can be created either as a seedling, with no argu#ent, or as a %lant grown in a nursery, with an e&isting height. To su%%ort this, there are two constructors, one that takes no argu#ents *we call constructors that take no argu#ents de$ault constructors@, and one that takes the e&isting height. RFSURFSTIJLT+(6PTE5?TIMGU /ou #ight also want to call the infoA B #ethod in #ore than one way. Eor e&a#%le, with a )tring argu#ent i" you have an e&tra #essage you want %rinted, and without i" you have nothing #ore to say. It would see# strange to give two se%arate na#es to what is obviously the sa#e conce%t. Eortunately, #ethod overloading allows you to use the sa#e na#e "or both. RFSURFSTIJLT+(6PTE5?TIMIU

Distinguishing overloaded methods


I" the #ethods have the sa#e na#e, how can Java know which #ethod you #eanO There s a si#%le rule= each overloaded #ethod #ust take a uniAue list o" argu#ent ty%es. RFSURFSTIJLT+(6PTE5?TIM2U
@ In so#e o" the Java literature "ro# Sun they instead re"er to these with the clu#sy but descri%tive na#e !no'arg constructors.$ The ter# !de"ault constructor$ has been in use "or #any years and so I will use that.

Cha ter 4! Initiali?ation & Cleanu

2=3

I" you think about this "or a second, it #akes sense= how else could a %rogra##er tell the di""erence between two #ethods that have the sa#e na#e, other than by the ty%es o" their argu#entsO RFSURF STIJLT+(6PTE5?TIK@U Even di""erences in the ordering o" argu#ents are su""icient to distinguish two #ethods= *6lthough you don t nor#ally want to take this a%%roach, as it %roduces di""icult'to'#aintain code., RFSURF STIJLT+(6PTE5?TIKMU

//3 c'I3Gverloa!ingGr!er.Hava // Gverloa!ing base! on the or!er of // the argu#ents. "ublic class Gverloa!ingGr!er @ static voi! "rint-%tring s, int i. @ %yste#.out."rintln8%tring3 8 K s K 8, int3 8 K i.< A static voi! "rint-int i, %tring s. @ %yste#.out."rintln8int3 8 K i K 8, %tring3 8 K s.< A "ublic static voi! #ain-%tringNO args. @ "rint-8%tring first8, ((.< "rint-CC, 8$nt first8.< A A ///3>
The two printA B #ethods have identical argu#ents, but the order is di""erent, and that s what #akes the# distinct. RFSURF STIJLT+(6PTE5?TIKKU

Overloading with .rimitives


6 %ri#itive can be auto#atically %ro#oted "ro# a s#aller ty%e to a larger one and this can be slightly con"using in co#bination with overloading. The "ollowing e&a#%le de#onstrates what ha%%ens when a %ri#itive is handed to an overloaded #ethod=

2=4

//3 c'I3Pri#itiveGverloa!ing.Hava // Pro#otion of "ri#itives an! overloa!ing. "ublic class Pri#itiveGverloa!ing @ // boolean can2t be auto#atically converte! static voi! "rt-%tring s. @ %yste#.out."rintln-s.< A voi! voi! voi! voi! voi! voi! voi! voi! voi! voi! voi! voi! voi! voi! voi! voi! voi! voi! voi! voi! voi! voi! f(-char 6. @ "rt-8f(-char.8.< A f(-byte 6. @ "rt-8f(-byte.8.< A f(-short 6. @ "rt-8f(-short.8.< A f(-int 6. @ "rt-8f(-int.8.< A f(-long 6. @ "rt-8f(-long.8.< A f(-float 6. @ "rt-8f(-float.8.< A f(-!ouble 6. @ "rt-8f(-!ouble.8.< A f f f f f f -byte 6. @ "rt-8f -byte.8.< A -short 6. @ "rt-8f -short.8.< A -int 6. @ "rt-8f -int.8.< A -long 6. @ "rt-8f -long.8.< A -float 6. @ "rt-8f -float.8.< A -!ouble 6. @ "rt-8f -!ouble.8.< A

f)-short 6. @ "rt-8f)-short.8.< A f)-int 6. @ "rt-8f)-int.8.< A f)-long 6. @ "rt-8f)-long.8.< A f)-float 6. @ "rt-8f)-float.8.< A f)-!ouble 6. @ "rt-8f)-!ouble.8.< A fI-int 6. @ "rt-8fI-int.8.< A fI-long 6. @ "rt-8fI-long.8.< A fI-float 6. @ "rt-8fI-float.8.< A fI-!ouble 6. @ "rt-8fI-!ouble.8.< A

voi! f,-long 6. @ "rt-8f,-long.8.< A voi! f,-float 6. @ "rt-8f,-float.8.< A voi! f,-!ouble 6. @ "rt-8f,-!ouble.8.< A voi! f+-float 6. @ "rt-8f+-float.8.< A voi! f+-!ouble 6. @ "rt-8f+-!ouble.8.< A

Cha ter 4! Initiali?ation & Cleanu

2=5

voi! f*-!ouble 6. @ "rt-8f*-!ouble.8.< A voi! testConstWal-. @ "rt-8Testing :ith ,8.< f(-,.<f -,.<f)-,.<fI-,.<f,-,.<f+-,.<f*-,.< A voi! testChar-. @ char 6 ? 262< "rt-8char argu#ent38.< f(-6.<f -6.<f)-6.<fI-6.<f,-6.<f+-6.<f*-6.< A voi! testByte-. @ byte 6 ? '< "rt-8byte argu#ent38.< f(-6.<f -6.<f)-6.<fI-6.<f,-6.<f+-6.<f*-6.< A voi! test%hort-. @ short 6 ? '< "rt-8short argu#ent38.< f(-6.<f -6.<f)-6.<fI-6.<f,-6.<f+-6.<f*-6.< A voi! test$nt-. @ int 6 ? '< "rt-8int argu#ent38.< f(-6.<f -6.<f)-6.<fI-6.<f,-6.<f+-6.<f*-6.< A voi! testLong-. @ long 6 ? '< "rt-8long argu#ent38.< f(-6.<f -6.<f)-6.<fI-6.<f,-6.<f+-6.<f*-6.< A voi! testLloat-. @ float 6 ? '< "rt-8float argu#ent38.< f(-6.<f -6.<f)-6.<fI-6.<f,-6.<f+-6.<f*-6.< A voi! testDouble-. @ !ouble 6 ? '< "rt-8!ouble argu#ent38.< f(-6.<f -6.<f)-6.<fI-6.<f,-6.<f+-6.<f*-6.<

2=7

A "ublic static voi! #ain-%tringNO args. @ Pri#itiveGverloa!ing " ? ne: Pri#itiveGverloa!ing-.< ".testConstWal-.< ".testChar-.< ".testByte-.< ".test%hort-.< ".test$nt-.< ".testLong-.< ".testLloat-.< ".testDouble-.< A A ///3>
I" you view the out%ut o" this %rogra#, you ll see that the constant value H is treated as an int, so i" an overloaded #ethod is available that takes an int it is used. In all other cases, i" you have a data ty%e that is s#aller than the argu#ent in the #ethod, that data ty%e is %ro#oted. char %roduces a slightly di""erent e""ect, since i" it doesn t "ind an e&act char #atch, it is %ro#oted to int. RFSURFSTIJLT+(6PTE5?TIKLU :hat ha%%ens i" your argu#ent is bigger than the argu#ent e&%ected by the overloaded #ethodO 6 #odi"ication o" the above %rogra# gives the answer=

//3 c'I3De#otion.Hava // De#otion of "ri#itives an! overloa!ing. "ublic class De#otion @ static voi! "rt-%tring s. @ %yste#.out."rintln-s.< A voi! voi! voi! voi! voi! voi! voi! f(-char 6. @ "rt-8f(-char.8.< A f(-byte 6. @ "rt-8f(-byte.8.< A f(-short 6. @ "rt-8f(-short.8.< A f(-int 6. @ "rt-8f(-int.8.< A f(-long 6. @ "rt-8f(-long.8.< A f(-float 6. @ "rt-8f(-float.8.< A f(-!ouble 6. @ "rt-8f(-!ouble.8.< A

Cha ter 4! Initiali?ation & Cleanu

2=8

voi! voi! voi! voi! voi! voi! voi! voi! voi! voi! voi! voi! voi! voi! voi!

f f f f f f

-char 6. @ "rt-8f -char.8.< A -byte 6. @ "rt-8f -byte.8.< A -short 6. @ "rt-8f -short.8.< A -int 6. @ "rt-8f -int.8.< A -long 6. @ "rt-8f -long.8.< A -float 6. @ "rt-8f -float.8.< A

f)-char 6. @ "rt-8f)-char.8.< A f)-byte 6. @ "rt-8f)-byte.8.< A f)-short 6. @ "rt-8f)-short.8.< A f)-int 6. @ "rt-8f)-int.8.< A f)-long 6. @ "rt-8f)-long.8.< A fI-char 6. @ "rt-8fI-char.8.< A fI-byte 6. @ "rt-8fI-byte.8.< A fI-short 6. @ "rt-8fI-short.8.< A fI-int 6. @ "rt-8fI-int.8.< A

voi! f,-char 6. @ "rt-8f,-char.8.< A voi! f,-byte 6. @ "rt-8f,-byte.8.< A voi! f,-short 6. @ "rt-8f,-short.8.< A voi! f+-char 6. @ "rt-8f+-char.8.< A voi! f+-byte 6. @ "rt-8f+-byte.8.< A voi! f*-char 6. @ "rt-8f*-char.8.< A voi! testDouble-. @ !ouble 6 ? '< "rt-8!ouble argu#ent38.< f(-6.<f --float.6.<f)--long.6.<fI--int.6.< f,--short.6.<f+--byte.6.<f*--char.6.< A "ublic static voi! #ain-%tringNO args. @ De#otion " ? ne: De#otion-.< ".testDouble-.< A A ///3>

2=:

(ere, the #ethods take narrower %ri#itive values. I" your argu#ent is wider then you #ust cast to the necessary ty%e using the ty%e na#e in %arentheses. I" you don t do this, the co#%iler will issue an error #essage. RFSURFSTIJLT+(6PTE5?TIK?U /ou should be aware that this is a narro,ing conversionD which #eans you #ight lose in"or#ation during the cast. This is why the co#%iler "orces you to do it9to "lag the narrowing conversion. RFSURF STIJLT+(6PTE5?TIKHU

Overloading on return values


It is co##on to wonder !:hy only class na#es and #ethod argu#ent listsO :hy not distinguish between #ethods based on their return valuesO $ Eor e&a#%le, these two #ethods, which have the sa#e na#e and argu#ents, are easily distinguished "ro# each other= RFSURF STIJLT+(6PTE5?TIK3U

voi! f-. @A int f-. @A


This works "ine when the co#%iler can uneAuivocally deter#ine the #eaning "ro# the conte&t, as in int 4 P fA B. (owever, you can call a #ethod and ignore the return value; this is o"ten re"erred to as calling a method $or its side e$$ect since you don t care about the return value but instead want the other e""ects o" the #ethod call. So i" you call the #ethod this way= RFSURFSTIJLT+(6PTE5?TIKGU

f-.<
how can Java deter#ine which fA B should be calledO 6nd how could so#eone reading the code see itO Because o" this sort o" %roble#, you cannot use return value ty%es to distinguish overloaded #ethods. RFSURF STIJLT+(6PTE5?TIKIU

Default constructors
6s #entioned %reviously, a de"ault constructor *a.k.a. a !no'arg$ constructor, is one without argu#ents, used to create a !vanilla ob0ect.$ I" you create a class that has no constructors, the co#%iler will

Cha ter 4! Initiali?ation & Cleanu

2=;

auto#atically create a de"ault constructor "or you. Eor e&a#%le= RFSURF STIJLT+(6PTE5?TIK2U

//3 c'I3DefaultConstructor.Hava class Bir! @ int i< A "ublic class DefaultConstructor @ "ublic static voi! #ain-%tringNO args. @ Bir! nc ? ne: Bir!-.< // !efault4 A A ///3>
The line RFSURFSTIJLT+(6PTE5?TIL@U

ne: Bir!-.<
creates a new ob0ect and calls the de"ault constructor, even though one was not e&%licitly de"ined. :ithout it we would have no #ethod to call to build our ob0ect. (owever, i" you de"ine any constructors *with or without argu#ents,, the co#%iler will not synthesi1e one "or you= RFSURF STIJLT+(6PTE5?TILMU

class Bush @ Bush-int i. @A Bush-!ouble !. @A A


Cow i" you say= RFSURFSTIJLT+(6PTE5?TILKU

ne: Bush-.<
the co#%iler will co#%lain that it cannot "ind a constructor that #atches. It s as i" when you don t %ut in any constructors, the co#%iler says !/ou are bound to need some constructor, so let #e #ake one "or you.$ But i" you write a constructor, the co#%iler says !/ou ve written a constructor so you know what you re doing; i" you didn t %ut in a de"ault it s because you #eant to leave it out.$ RFSURFSTIJLT+(6PTE5?TILLU

21=

#he this ke:word


I" you have two ob0ects o" the sa#e ty%e called a and b, you #ight wonder how it is that you can call a #ethod fA B "or both those ob0ects= RFSURF STIJLT+(6PTE5?TIL?U

class Banana @ voi! f-int i. @ /B ... B/ A A Banana a ? ne: Banana-., b ? ne: Banana-.< a.f-(.< b.f- .<
I" there s only one #ethod called fA B, how can that #ethod know whether it s being called "or the ob0ect a or bO RFSURFSTIJLT+(6PTE5?TILHU To allow you to write the code in a convenient ob0ect'oriented synta& in which you !send a #essage to an ob0ect,$ the co#%iler does so#e undercover work "or you. There s a secret "irst argu#ent %assed to the #ethod fA B, and that argu#ent is the re"erence to the ob0ect that s being #ani%ulated. So the two #ethod calls above beco#e so#ething like= RF SURFSTIJLT+(6PTE5?TIL3U

Banana.f-a,(.< Banana.f-b, .<


This is internal and you can t write these e&%ressions and get the co#%iler to acce%t the#, but it gives you an idea o" what s ha%%ening. RFSURF STIJLT+(6PTE5?TILGU Su%%ose you re inside a #ethod and you d like to get the re"erence to the current ob0ect. Since that re"erence is %assed secretl) by the co#%iler, there s no identi"ier "or it. (owever, "or this %ur%ose there s a keyword= this. The this keyword9which can be used only inside a #ethod9 %roduces the re"erence to the ob0ect the #ethod has been called "or. /ou can treat this re"erence 0ust like any other ob0ect re"erence. >ee% in #ind that i" you re calling a #ethod o" your class "ro# within another #ethod o" your class, you don t need to use this; you si#%ly call the #ethod. The current this re"erence is auto#atically used "or the other #ethod. Thus you can say= RFSURFSTIJLT+(6PTE5?TILIU

class 0"ricot @ voi! "ick-. @ /B ... B/ A

Cha ter 4! Initiali?ation & Cleanu

211

voi! "it-. @ "ick-.< /B ... B/ A A


Inside pitA B, you could say this!pickA B but there s no need to. The co#%iler does it "or you auto#atically. The this keyword is used only "or those s%ecial cases in which you need to e&%licitly use the re"erence to the current ob0ect. Eor e&a#%le, it s o"ten used in ret*rn state#ents when you want to return the re"erence to the current ob0ect= RFSURF STIJLT+(6PTE5?TIL2U

//3 c'I3Leaf.Hava // %i#"le use of the 8this8 key:or!. "ublic class Leaf @ int i ? '< Leaf incre#ent-. @ iKK< return this< A voi! "rint-. @ %yste#.out."rintln-8i ? 8 K i.< A "ublic static voi! #ain-%tringNO args. @ Leaf 6 ? ne: Leaf-.< 6.incre#ent-..incre#ent-..incre#ent-.."rint-.< A A ///3>
Because incrementA B returns the re"erence to the current ob0ect via the this keyword, #ulti%le o%erations can easily be %er"or#ed on the sa#e ob0ect. RFSURFSTIJLT+(6PTE5?TI?@U

Calling constructors from constructors


:hen you write several constructors "or a class, there are ti#es when you d like to call one constructor "ro# another to avoid du%licating code. /ou can do this using the this keyword. RFSURF STIJLT+(6PTE5?TI?MU Cor#ally, when you say this, it is in the sense o" !this ob0ect$ or !the current ob0ect,$ and by itsel" it %roduces the re"erence to the current ob0ect. In a constructor, the this keyword takes on a di""erent #eaning

212

when you give it an argu#ent list= it #akes an e&%licit call to the constructor that #atches that argu#ent list. Thus you have a straight"orward way to call other constructors= RFSURF STIJLT+(6PTE5?TI?KU

//3 c'I3Llo:er.Hava // Calling constructors :ith 8this.8 "ublic class Llo:er @ int "etalCount ? '< %tring s ? ne: %tring-8null8.< Llo:er-int "etals. @ "etalCount ? "etals< %yste#.out."rintln8Constructor :/ int arg only, "etalCount? 8 K "etalCount.< A Llo:er-%tring ss. @ %yste#.out."rintln8Constructor :/ %tring arg only, s?8 K ss.< s ? ss< A Llo:er-%tring s, int "etals. @ this-"etals.< //4 this-s.< // Can2t call t:o4 this.s ? s< // 0nother use of 8this8 %yste#.out."rintln-8%tring D int args8.< A Llo:er-. @ this-8hi8, I*.< %yste#.out."rintln8!efault constructor -no args.8.< A voi! "rint-. @ //4 this-((.< // &ot insi!e non-constructor4 %yste#.out."rintln8"etalCount ? 8 K "etalCount K 8 s ? 8K s.< A "ublic static voi! #ain-%tringNO args. @ Llo:er 6 ? ne: Llo:er-.< 6."rint-.<

Cha ter 4! Initiali?ation & Cleanu

213

A A ///3>
The constructor Flo(erA)tring s, int petalsB shows that, while you can call one constructor using this, you cannot call two. In addition, the constructor call #ust be the "irst thing you do or you ll get a co#%iler error #essage. RFSURFSTIJLT+(6PTE5?TI?LU This e&a#%le also shows another way you ll see this used. Since the na#e o" the argu#ent s and the na#e o" the #e#ber data s are the sa#e, there s an a#biguity. /ou can resolve it by saying this!s to re"er to the #e#ber data. /ou ll o"ten see this "or# used in Java code, and it s used in nu#erous %laces in this book. RFSURFSTIJLT+(6PTE5?TI??U In printA B you can see that the co#%iler won t let you call a constructor "ro# inside any #ethod other than a constructor. RFSURF STIJLT+(6PTE5?TI?HU

#he meaning of static


:ith the this keyword in #ind, you can #ore "ully understand what it #eans to #ake a #ethod static. It #eans that there is no this "or that %articular #ethod. /ou cannot call non' static #ethods "ro# inside static #ethods @ *although the reverse is %ossible,, and you can call a static #ethod "or the class itsel", without any ob0ect. In "act, that s %ri#arily what a static #ethod is "or. It s as i" you re creating the eAuivalent o" a global "unction *"ro# +,. E&ce%t global "unctions are not %er#itted in Java, and %utting the static #ethod inside a class allows it access to other static #ethods and to static "ields. RFSURF STIJLT+(6PTE5?TI?3U So#e %eo%le argue that static #ethods are not ob0ect'oriented since they do have the se#antics o" a global "unction; with a static #ethod you don t send a #essage to an ob0ect, since there s no this. This is %robably a "air argu#ent, and i" you "ind yoursel" using a lot o" static #ethods you should %robably rethink your strategy. (owever, statics are %rag#atic and there are ti#es when you genuinely need the#, so whether or not
@ The one case in which this is %ossible occurs i" you %ass a re"erence to an ob0ect into the

static #ethod. Then, via the re"erence *which is now e""ectively this,, you can call non' static #ethods and access non'static "ields. But ty%ically i" you want to do so#ething like this you ll 0ust #ake an ordinary, non'static #ethod.

214

they are !%ro%er ))P$ should be le"t to the theoreticians. Indeed, even S#alltalk has the eAuivalent in its !class #ethods.$ F/GHF/

GTIJ3IC."PTE-4II48H

Cleanu.: finali?ation and garbage collection


Progra##ers know about the i#%ortance o" initiali1ation, but o"ten "orget the i#%ortance o" cleanu%. 6"ter all, who needs to clean u% an intO But with libraries, si#%ly !letting go$ o" an ob0ect once you re done with it is not always sa"e. )" course, Java has the garbage collector to reclai# the #e#ory o" ob0ects that are no longer used. Cow consider a very unusual case. Su%%ose your ob0ect allocates !s%ecial$ #e#ory without using ne(. The garbage collector knows only how to release #e#ory allocated ,ith ne(, so it won t know how to release the ob0ect s !s%ecial$ #e#ory. To handle this case, Java %rovides a #ethod called finali7eA B that you can de"ine "or your class. (ere s how it s su osed to work. :hen the garbage collector is ready to release the storage used "or your ob0ect, it will "irst call finali7eA B, and only on the ne&t garbage'collection %ass will it reclai# the ob0ect s #e#ory. So i" you choose to use finali7eA B, it gives you the ability to %er"or# so#e i#%ortant cleanu% at the time o$ garbage collection. RFSURFSTIJLT+(6PTE5?TI?IU This is a %otential %rogra##ing %it"all because so#e %rogra##ers, es%ecially +<< %rogra##ers, #ight initially #istake finali7eA B "or the destructor in +<<, which is a "unction that is always called when an ob0ect is destroyed. But it is i#%ortant to distinguish between +<< and Java here, because in +<< ob>ects al,a)s get destro)ed *in a bug'"ree %rogra#,, whereas in Java ob0ects do not always get garbage'collected. )r, %ut another way= RFSURFSTIJLT+(6PTE5?TI?2U

8arbage collection is not destruction.


I" you re#e#ber this, you will stay out o" trouble. :hat it #eans is that i" there is so#e activity that #ust be %er"or#ed be"ore you no longer need

Cha ter 4! Initiali?ation & Cleanu

215

an ob0ect, you #ust %er"or# that activity yoursel". Java has no destructor or si#ilar conce%t, so you #ust create an ordinary #ethod to %er"or# this cleanu%. Eor e&a#%le, su%%ose in the %rocess o" creating your ob0ect it draws itsel" on the screen. I" you don t e&%licitly erase its i#age "ro# the screen, it #ight never get cleaned u%. I" you %ut so#e kind o" erasing "unctionality inside finali7eA B, then i" an ob0ect is garbage'collected, the i#age will "irst be re#oved "ro# the screen, but i" it isn t, the i#age will re#ain. So a second %oint to re#e#ber is= RFSURF STIJLT+(6PTE5?TIH@U

/our ob0ects #ight not get garbage'collected.


/ou #ight "ind that the storage "or an ob0ect never gets released because your %rogra# never nears the %oint o" running out o" storage. I" your %rogra# co#%letes and the garbage collector never gets around to releasing the storage "or any o" your ob0ects, that storage will be returned to the o%erating syste# en masse as the %rogra# e&its. This is a good thing, because garbage collection has so#e overhead, and i" you never do it you never incur that e&%ense. RFSURFSTIJLT+(6PTE5?TIHMU

What is !inali0e1 2 forA


/ou #ight believe at this %oint that you should not use finali7eA B as a general'%ur%ose cleanu% #ethod. :hat good is itO RFSURF STIJLT+(6PTE5?TIHKU 6 third %oint to re#e#ber is=

8arbage collection is only about #e#ory.


That is, the sole reason "or the e&istence o" the garbage collector is to recover #e#ory that your %rogra# is no longer using. So any activity that is associated with garbage collection, #ost notably your finali7eA B #ethod, #ust also be only about #e#ory and its deallocation. RFSURF STIJLT+(6PTE5?TIHLU 7oes this #ean that i" your ob0ect contains other ob0ects finali7eA B should e&%licitly release those ob0ectsO :ell, no9the garbage collector takes care o" the release o" all ob0ect #e#ory regardless o" how the ob0ect is created. It turns out that the need "or finali7eA B is li#ited to s%ecial

217

cases, in which your ob0ect can allocate so#e storage in so#e way other than creating an ob0ect. But, you #ight observe, everything in Java is an ob0ect so how can this beO RFSURFSTIJLT+(6PTE5?TIH?U It would see# that finali7eA B is in %lace because o" the %ossibility that you ll do so#ething +'like by allocating #e#ory using a #echanis# other than the nor#al one in Java. This can ha%%en %ri#arily through native methods, which are a way to call non'Java code "ro# Java. *Cative #ethods are discussed in 6%%endi& B., + and +<< are the only languages currently su%%orted by native #ethods, but since they can call sub%rogra#s in other languages, you can e""ectively call anything. Inside the non'Java code, + s mallocA B "a#ily o" "unctions #ight be called to allocate storage, and unless you call freeA B that storage will not be released, causing a #e#ory leak. )" course, freeA B is a + and +<< "unction, so you d need to call it in a native #ethod inside your finali7e A B. RFSURFSTIJLT+(6PTE5?TIHHU 6"ter reading this, you %robably get the idea that you won t use finali7e A B #uch. /ou re correct; it is not the a%%ro%riate %lace "or nor#al cleanu% to occur. So where should nor#al cleanu% be %er"or#edO RF SURFSTIJLT+(6PTE5?TIH3U

Gou must .erform cleanu.


To clean u% an ob0ect, the user o" that ob0ect #ust call a cleanu% #ethod at the %oint the cleanu% is desired. This sounds %retty straight"orward, but it collides a bit with the +<< conce%t o" the destructor. In +<<, all ob0ects are destroyed. )r rather, all ob0ects should be destroyed. I" the +<< ob0ect is created as a local *i.e., on the stack9not %ossible in Java,, then the destruction ha%%ens at the closing curly brace o" the sco%e in which the ob0ect was created. I" the ob0ect was created using ne( *like in Java, the destructor is called when the %rogra##er calls the +<< o%erator 'elete *which doesn t e&ist in Java,. I" the +<< %rogra##er "orgets to call 'elete, the destructor is never called and you have a #e#ory leak, %lus the other %arts o" the ob0ect never get cleaned u%. This kind o" bug can be very di""icult to track down. RFSURF STIJLT+(6PTE5?TIHGU

Cha ter 4! Initiali?ation & Cleanu

218

In contrast, Java doesn t allow you to create local ob0ects9you #ust always use ne(. But in Java, there s no !delete$ to call to release the ob0ect since the garbage collector releases the storage "or you. So "ro# a si#%listic stand%oint you could say that because o" garbage collection, Java has no destructor. /ou ll see as this book %rogresses, however, that the %resence o" a garbage collector does not re#ove the need "or or utility o" destructors. *6nd you should never call finali7eA B directly, so that s not an a%%ro%riate avenue "or a solution., I" you want so#e kind o" cleanu% %er"or#ed other than storage release you #ust still e&%licitly call an a%%ro%riate #ethod in Java, which is the eAuivalent o" a +<< destructor without the convenience. RFSURFSTIJLT+(6PTE5?TIHIU )ne o" the things finali7eA B can be use"ul "or is observing the %rocess o" garbage collection. The "ollowing e&a#%le shows you what s going on and su##ari1es the %revious descri%tions o" garbage collection=

//3 c'I3aarbage.Hava // De#onstration of the garbage // collector an! finaliUation class Chair @ static boolean gcrun ? false< static boolean f ? false< static int create! ? '< static int finaliUe! ? '< int i< Chair-. @ i ? KKcreate!< if-create! ?? I*. %yste#.out."rintln-8Create! I*8.< A "ublic voi! finaliUe-. @ if-4gcrun. @ // The first ti#e finaliUe-. is calle!3 gcrun ? true< %yste#.out."rintln8Beginning to finaliUe after 8 K create! K 8 Chairs have been create!8.< A if-i ?? I*. @ %yste#.out."rintln-

21:

8LinaliUing Chair SI*, 8 K 8%etting flag to sto" Chair creation8.< f ? true< A finaliUe!KK< if-finaliUe! Q? create!. %yste#.out."rintln80ll 8 K finaliUe! K 8 finaliUe!8.< A A "ublic class aarbage @ "ublic static voi! #ain-%tringNO args. @ // 0s long as the flag hasn2t been set, // #ake Chairs an! %trings3 :hile-4Chair.f. @ ne: Chair-.< ne: %tring-8To take u" s"ace8.< A %yste#.out."rintln80fter all Chairs have been create!3_n8 K 8total create! ? 8 K Chair.create! K 8, total finaliUe! ? 8 K Chair.finaliUe!.< // G"tional argu#ents force garbage // collection D finaliUation3 if-args.length Q '. @ if-argsN'O.e=uals-8gc8. XX argsN'O.e=uals-8all8.. @ %yste#.out."rintln-8gc-.38.< %yste#.gc-.< A if-argsN'O.e=uals-8finaliUe8. XX argsN'O.e=uals-8all8.. @ %yste#.out."rintln-8runLinaliUation-.38.< %yste#.runLinaliUation-.< A A %yste#.out."rintln-8bye48.< A A ///3>

Cha ter 4! Initiali?ation & Cleanu

21;

The above %rogra# creates #any -hair ob0ects, and at so#e %oint a"ter the garbage collector begins running, the %rogra# sto%s creating -hairs. Since the garbage collector can run at any ti#e, you don t know e&actly when it will start u%, so there s a "lag called gcr*n to indicate whether the garbage collector has started running yet. 6 second "lag f is a way "or -hair to tell the mainA B loo% that it should sto% #aking ob0ects. Both o" these "lags are set within finali7eA B, which is called during garbage collection. RFSURFSTIJLT+(6PTE5?TIH2U Two other static variables, create' and finali7e', kee% track o" the nu#ber o" -hairs created versus the nu#ber that get "inali1ed by the garbage collector. Einally, each -hair has its own *non' static, int i so it can kee% track o" what nu#ber it is. :hen -hair nu#ber ?G is "inali1ed, the "lag is set to tr*e to bring the %rocess o" -hair creation to a sto%. RF SURFSTIJLT+(6PTE5?TI3@U 6ll this ha%%ens in mainA B, in the loo%

:hile-4Chair.f. @ ne: Chair-.< ne: %tring-8To take u" s"ace8.< A


/ou #ight wonder how this loo% could ever "inish, since there s nothing inside the loo% that changes the value o" -hair!f. (owever, the finali7e A B %rocess will, eventually, when it "inali1es nu#ber ?G. RFSURF STIJLT+(6PTE5?TI3MU The creation o" a )tring ob0ect during each iteration is si#%ly e&tra storage being allocated to encourage the garbage collector to kick in, which it will do when it starts to get nervous about the a#ount o" #e#ory available. RFSURFSTIJLT+(6PTE5?TI3KU :hen you run the %rogra#, you %rovide a co##and'line argu#ent o" !gc,$ !"inali1e,$ or !all.$ The !gc$ argu#ent will call the )ystem!gcA B #ethod *to "orce e&ecution o" the garbage collector,. 4sing the !"inali1e$ argu#ent calls )ystem!r*nFinali7ationA B which9in theory9will cause any un"inali1ed ob0ects to be "inali1ed. 6nd !all$ causes both #ethods to be called. RFSURFSTIJLT+(6PTE5?TI3LU

22=

The behavior o" this %rogra# and the version in the "irst edition o" this book shows that the whole issue o" garbage collection and "inali1ation has been evolving, with #uch o" the evolution ha%%ening behind closed doors. In "act, by the ti#e you read this, the behavior o" the %rogra# #ay have changed once again. RFSURFSTIJLT+(6PTE5?TI3?U I" )ystem!gcA B is called, then "inali1ation ha%%ens to all the ob0ects. This was not necessarily the case with %revious i#%le#entations o" the J7>, although the docu#entation clai#ed otherwise. In addition, you ll see that it doesn t see# to #ake any di""erence whether )ystem! r*nFinali7ationA B is called. RFSURFSTIJLT+(6PTE5?TI3HU (owever, you will see that only i" )ystem!gcA B is called a"ter all the ob0ects are created and discarded will all the "inali1ers be called. I" you do not call )ystem!gcA B, then only so#e o" the ob0ects will be "inali1ed. In Java M.M, a #ethod )ystem!r*nFinali7ers.n&4itA B was introduced that caused %rogra#s to run all the "inali1ers as they e&ited, but the design turned out to be buggy and the #ethod was de%recated. This is yet another clue that the Java designers were thrashing about trying to solve the garbage collection and "inali1ation %roble#. :e can only ho%e that things have been worked out in Java K. RFSURFSTIJLT+(6PTE5?TI33U The %receding %rogra# shows that the %ro#ise that "inali1ers will always be run holds true, but only i" you e&%licitly "orce it to ha%%en yoursel". I" you don t cause )ystem!gcA B to be called, you ll get an out%ut like this=

Create! I* Beginning to finaliUe create! LinaliUing Chair SI*, creation 0fter all Chairs have total create! ? )11(, bye4

after )I1+ Chairs have been %etting flag to sto" Chair been create!3 total finaliUe! ? +1I

Thus, not all "inali1ers get called by the ti#e the %rogra# co#%letes. I" )ystem!gcA B is called, it will "inali1e and destroy all the ob0ects that are no longer in use u% to that %oint. RFSURFSTIJLT+(6PTE5?TI3GU 5e#e#ber that neither garbage collection nor "inali1ation is guaranteed. I" the Java Virtual Machine *JVM, isn t close to running out o" #e#ory,

Cha ter 4! Initiali?ation & Cleanu

221

then it will *wisely, not waste ti#e recovering #e#ory through garbage collection. RFSURFSTIJLT+(6PTE5?TI3IU

#he death condition


In general, you can t rely on finali7eA B being called, and you #ust create se%arate !cleanu%$ "unctions and call the# e&%licitly. So it a%%ears that finali7eA B is only use"ul "or obscure #e#ory cleanu% that #ost %rogra##ers will never use. (owever, there is a very interesting use o" finali7eA B which does not rely on it being called every ti#e. This is the veri"ication o" the death condition@ o" an ob0ect. RFSURF STIJLT+(6PTE5?TI32U 6t the %oint that you re no longer interested in an ob0ect9when it s ready to be cleaned u%9that ob0ect should be in a state whereby its #e#ory can be sa"ely released. Eor e&a#%le, i" the ob0ect re%resents an o%en "ile, that "ile should be closed by the %rogra##er be"ore the ob0ect is garbage' collected. I" any %ortions o" the ob0ect are not %ro%erly cleaned u%, then you have a bug in your %rogra# that could be very di""icult to "ind. The value o" finali7eA B is that it can be used to discover this condition, even i" it isn t always called. I" one o" the "inali1ations ha%%ens to reveal the bug, then you discover the %roble#, which is all you really care about. RF SURFSTIJLT+(6PTE5?TIG@U (ere s a si#%le e&a#%le o" how you #ight use it=

//3 c'I3DeathCon!ition.Hava // Ysing finaliUe-. to !etect an obHect that // hasn2t been "ro"erly cleane! u". class Book @ boolean checke!Gut ? false< Book-boolean checkGut. @ checke!Gut ? checkGut< A voi! check$n-. @ checke!Gut ? false< A
@ 6 ter# coined by Bill Venners *www.arti#a.co#, during a se#inar that he and I were giving together.

222

"ublic voi! finaliUe-. @ if-checke!Gut. %yste#.out."rintln-8Error3 checke! out8.< A A "ublic class DeathCon!ition @ "ublic static voi! #ain-%tringNO args. @ Book novel ? ne: Book-true.< // Pro"er cleanu"3 novel.check$n-.< // Dro" the reference, forget to clean u"3 ne: Book-true.< // Lorce garbage collection D finaliUation3 %yste#.gc-.< A A ///3>
The death condition is that all 2ook ob0ects are su%%osed to be checked in be"ore they are garbage'collected, but in mainA B a %rogra##er error doesn t check in one o" the books. :ithout finali7eA B to veri"y the death condition, this could be a di""icult bug to "ind. RFSURF STIJLT+(6PTE5?TIGMU Cote that )ystem!gcA B is used to "orce "inali1ation *and you should do this during %rogra# develo%#ent to s%eed debugging,. But even i" it isn t, it s highly %robable that the errant 2ook will eventually be discovered through re%eated e&ecutions o" the %rogra# *assu#ing the %rogra# allocates enough storage to cause the garbage collector to e&ecute,. RF SURFSTIJLT+(6PTE5?TIGKU

>ow a garbage collector works


I" you co#e "ro# a %rogra##ing language where allocating ob0ects on the hea% is e&%ensive, you #ay naturally assu#e that Java s sche#e o" allocating everything *e&ce%t %ri#itives, on the hea% is e&%ensive. (owever, it turns out that the garbage collector can have a signi"icant i#%act on increasing the s%eed o" ob0ect creation. This #ight sound a bit odd at "irst9that storage release a""ects storage allocation9but it s the way so#e JVMs work and it #eans that allocating storage "or hea%

Cha ter 4! Initiali?ation & Cleanu

223

ob0ects in Java can be nearly as "ast as creating storage on the stack in other languages. RFSURFSTIJLT+(6PTE5?TIGLU Eor e&a#%le, you can think o" the +<< hea% as a yard where each ob0ect stakes out its own %iece o" tur". This real estate can beco#e abandoned so#eti#e later and #ust be reused. In so#e JVMs, the Java hea% is Auite di""erent; it s #ore like a conveyor belt that #oves "orward every ti#e you allocate a new ob0ect. This #eans that ob0ect storage allocation is re#arkably ra%id. The !hea% %ointer$ is si#%ly #oved "orward into virgin territory, so it s e""ectively the sa#e as +<< s stack allocation. *)" course, there s a little e&tra overhead "or bookkee%ing but it s nothing like searching "or storage., RFSURFSTIJLT+(6PTE5?TIG?U Cow you #ight observe that the hea% isn t in "act a conveyor belt, and i" you treat it that way you ll eventually start %aging #e#ory a lot *which is a big %er"or#ance hit, and later run out. The trick is that the garbage collector ste%s in and while it collects the garbage it co#%acts all the ob0ects in the hea% so that you ve e""ectively #oved the !hea% %ointer$ closer to the beginning o" the conveyor belt and "urther away "ro# a %age "ault. The garbage collector rearranges things and #akes it %ossible "or the high's%eed, in"inite'"ree'hea% #odel to be used while allocating storage. RFSURFSTIJLT+(6PTE5?TIGHU To understand how this works, you need to get a little better idea o" the way the di""erent garbage collector *8+, sche#es work. 6 si#%le but slow 8+ techniAue is re"erence counting. This #eans that each ob0ect contains a re"erence counter, and every ti#e a re"erence is attached to an ob0ect the re"erence count is increased. Every ti#e a re"erence goes out o" sco%e or is set to n*ll, the re"erence count is decreased. Thus, #anaging re"erence counts is a s#all but constant overhead that ha%%ens throughout the li"eti#e o" your %rogra#. The garbage collector #oves through the entire list o" ob0ects and when it "inds one with a re"erence count o" 1ero it releases that storage. The one drawback is that i" ob0ects circularly re"er to each other they can have non1ero re"erence counts while still being garbage. Docating such sel"'re"erential grou%s reAuires signi"icant e&tra work "or the garbage collector. 5e"erence counting is co##only used to e&%lain one kind o" garbage collection but it doesn t see# to be used in any JVM i#%le#entations. RFSURF STIJLT+(6PTE5?TIG3U

224

In "aster sche#es, garbage collection is not based on re"erence counting. Instead, it is based on the idea that any nondead ob0ect #ust ulti#ately be traceable back to a re"erence that lives either on the stack or in static storage. The chain #ight go through several layers o" ob0ects. Thus, i" you start in the stack and the static storage area and walk through all the re"erences you ll "ind all the live ob0ects. Eor each re"erence that you "ind, you #ust trace into the ob0ect that it %oints to and then "ollow all the re"erences in that ob0ect, tracing into the ob0ects they %oint to, etc., until you ve #oved through the entire web that originated with the re"erence on the stack or in static storage. Each ob0ect that you #ove through #ust still be alive. Cote that there is no %roble# with detached sel"'re"erential grou%s9these are si#%ly not "ound, and are there"ore auto#atically garbage. RFSURFSTIJLT+(6PTE5?TIGGU In the a%%roach described here, the JVM uses an ada tive garbage' collection sche#e, and what it does with the live ob0ects that it locates de%ends on the variant currently being used. )ne o" these variants is sto /and/co ). This #eans that9"or reasons that will beco#e a%%arent9 the %rogra# is "irst sto%%ed *this is not a background collection sche#e,. Then, each live ob0ect that is "ound is co%ied "ro# one hea% to another, leaving behind all the garbage. In addition, as the ob0ects are co%ied into the new hea% they are %acked end'to'end, thus co#%acting the new hea% *and allowing new storage to si#%ly be reeled o"" the end as %reviously described,. RFSURFSTIJLT+(6PTE5?TIGIU )" course, when an ob0ect is #oved "ro# one %lace to another, all re"erences that %oint at *i.e., that re$erence, the ob0ect #ust be changed. The re"erence that goes "ro# the hea% or the static storage area to the ob0ect can be changed right away, but there can be other re"erences %ointing to this ob0ect that will be encountered later during the !walk.$ These are "i&ed u% as they are "ound *you could i#agine a table that #a%s old addresses to new ones,. RFSURFSTIJLT+(6PTE5?TIG2U There are two issues that #ake these so'called !co%y collectors$ ine""icient. The "irst is the idea that you have two hea%s and you slosh all the #e#ory back and "orth between these two se%arate hea%s, #aintaining twice as #uch #e#ory as you actually need. So#e JVMs deal with this by allocating the hea% in chunks as needed and si#%ly co%ying "ro# one chunk to another. RFSURFSTIJLT+(6PTE5?TII@U

Cha ter 4! Initiali?ation & Cleanu

225

The second issue is the co%ying. )nce your %rogra# beco#es stable it #ight be generating little or no garbage. 7es%ite that, a co%y collector will still co%y all the #e#ory "ro# one %lace to another, which is waste"ul. To %revent this, so#e JVMs detect that no new garbage is being generated and switch to a di""erent sche#e *this is the !ada%tive$ %art,. This other sche#e is called mark and s,ee , and it s what earlier versions o" Sun s JVM used all the ti#e. Eor general use, #ark and swee% is "airly slow, but when you know you re generating little or no garbage it s "ast. RFSURF STIJLT+(6PTE5?TIIMU Mark and swee% "ollows the sa#e logic o" starting "ro# the stack and static storage and tracing through all the re"erences to "ind live ob0ects. (owever, each ti#e it "inds a live ob0ect that ob0ect is #arked by setting a "lag in it, but the ob0ect isn t collected yet. )nly when the #arking %rocess is "inished does the swee% occur. 7uring the swee%, the dead ob0ects are released. (owever, no co%ying ha%%ens, so i" the collector chooses to co#%act a "rag#ented hea% it does so by shu""ling ob0ects around. RF SURFSTIJLT+(6PTE5?TIIKU The !sto%'and'co%y$ re"ers to the idea that this ty%e o" garbage collection is not done in the background; instead, the %rogra# is sto%%ed while the 8+ occurs. In the Sun literature you ll "ind #any re"erences to garbage collection as a low'%riority background %rocess, but it turns out that the 8+ was not i#%le#ented that way, at least in earlier versions o" the Sun JVM. Instead, the Sun garbage collector ran when #e#ory got low. In addition, #ark'and'swee% reAuires that the %rogra# be sto%%ed. RFSURF STIJLT+(6PTE5?TIILU 6s %reviously #entioned, in the JVM described here #e#ory is allocated in big blocks. I" you allocate a large ob0ect, it gets its own block. Strict sto%'and'co%y reAuires co%ying every live ob0ect "ro# the source hea% to a new hea% be"ore you could "ree the old one, which translates to lots o" #e#ory. :ith blocks, the 8+ can ty%ically use dead blocks to co%y ob0ects to as it collects. Each block has a generation count to kee% track o" whether it s alive. In the nor#al case, only the blocks created since the last 8+ are co#%acted; all other blocks get their generation count bu#%ed i" they have been re"erenced "ro# so#ewhere. This handles the nor#al case o" lots o" short'lived te#%orary ob0ects. Periodically, a "ull swee% is #ade9large ob0ects are still not co%ied *0ust get their generation

227

count bu#%ed, and blocks containing s#all ob0ects are co%ied and co#%acted. The JVM #onitors the e""iciency o" 8+ and i" it beco#es a waste o" ti#e because all ob0ects are long'lived then it switches to #ark' and'swee%. Si#ilarly, the JVM kee%s track o" how success"ul #ark'and' swee% is, and i" the hea% starts to beco#e "rag#ented it switches back to sto%'and'co%y. This is where the !ada%tive$ %art co#es in, so you end u% with a #outh"ul= !ada%tive generational sto%'and'co%y #ark'and'swee%.$ RFSURFSTIJLT+(6PTE5?TII?U There are a nu#ber o" additional s%eedu%s %ossible in a JVM. 6n es%ecially i#%ortant one involves the o%eration o" the loader and Just'In' Ti#e *JIT, co#%iler. :hen a class #ust be loaded *ty%ically, the "irst ti#e you want to create an ob0ect o" that class,, the !class "ile is located and the byte codes "or that class are brought into #e#ory. 6t this %oint, one a%%roach is to si#%ly JIT all the code, but this has two drawbacks= it takes a little #ore ti#e, which, co#%ounded throughout the li"e o" the %rogra#, can add u%; and it increases the si1e o" the e&ecutable *byte codes are signi"icantly #ore co#%act than e&%anded JIT code, and this #ight cause %aging, which de"initely slows down a %rogra#. 6n alternative a%%roach is la?) evaluationD which #eans that the code is not JIT co#%iled until necessary. Thus, code that never gets e&ecuted #ight never get JIT co#%iled. RFSURFSTIJLT+(6PTE5?TIIHU

Member initiali?ation
Java goes out o" its way to guarantee that variables are %ro%erly initiali1ed be"ore they are used. In the case o" variables that are de"ined locally to a #ethod, this guarantee co#es in the "or# o" a co#%ile'ti#e error. So i" you say= RFSURFSTIJLT+(6PTE5?TII3U

voi! f-. @ int i< iKK< A


you ll get an error #essage that says that i #ight not have been initiali1ed. )" course, the co#%iler could have given i a de"ault value, but it s #ore likely that this is a %rogra##er error and a de"ault value would

Cha ter 4! Initiali?ation & Cleanu

228

have covered that u%. Eorcing the %rogra##er to %rovide an initiali1ation value is #ore likely to catch a bug. RFSURFSTIJLT+(6PTE5?TIIGU I" a %ri#itive is a data #e#ber o" a class, however, things are a bit di""erent. Since any #ethod can initiali1e or use that data, it #ight not be %ractical to "orce the user to initiali1e it to its a%%ro%riate value be"ore the data is used. (owever, it s unsa"e to leave it with a garbage value, so each %ri#itive data #e#ber o" a class is guaranteed to get an initial value. Those values can be seen here= RFSURFSTIJLT+(6PTE5?TIIIU

//3 c'I3$nitialWalues.Hava // %ho:s !efault initial values. class Jeasure#ent @ boolean t< char c< byte b< short s< int i< long l< float f< !ouble !< voi! "rint-. @ %yste#.out."rintln8Data ty"e $nitial value_n8 K 8boolean 8 K t K 8_n8 K 8char N8 K c K 8O 8K -int.c K8_n8K 8byte 8 K b K 8_n8 K 8short 8 K s K 8_n8 K 8int 8 K i K 8_n8 K 8long 8 K l K 8_n8 K 8float 8 K f K 8_n8 K 8!ouble 8 K !.< A A "ublic class $nitialWalues @ "ublic static voi! #ain-%tringNO args. @ Jeasure#ent ! ? ne: Jeasure#ent-.< !."rint-.< /B $n this case you coul! also say3

22:

ne: Jeasure#ent-.."rint-.< B/ A A ///3>


The out%ut o" this %rogra# is=

Data ty"e boolean char byte short int long float !ouble

$nitial value false N O ' ' ' ' ' '.' '.'

The char value is a 1ero, which %rints as a s%ace. RFSURF STIJLT+(6PTE5?TII2U /ou ll see later that when you de"ine an ob0ect re"erence inside a class without initiali1ing it to a new ob0ect, that re"erence is given a s%ecial value o" n*ll *which is a Java keyword,. RFSURF STIJLT+(6PTE5?TI2@U /ou can see that even though the values are not s%eci"ied, they auto#atically get initiali1ed. So at least there s no threat o" working with uninitiali1ed variables. RFSURFSTIJLT+(6PTE5?TI2MU

1.ecif:ing initiali?ation
:hat ha%%ens i" you want to give a variable an initial valueO )ne direct way to do this is si#%ly to assign the value at the %oint you de"ine the variable in the class. *Cotice you cannot do this in +<<, although +<< novices always try., (ere the "ield de"initions in class 1eas*rement are changed to %rovide initial values=

class Jeasure#ent @ boolean b ? true< char c ? 262< byte B ? I*< short s ? '6ff<

Cha ter 4! Initiali?ation & Cleanu

22;

int i ? CCC< long l ? (< float f ? ).(If< !ouble ! ? ).(I(,C< //. . .


/ou can also initiali1e non%ri#itive ob0ects in this sa#e way. I" epth is a class, you can insert a variable and initiali1e it like so= RFSURF STIJLT+(6PTE5?TI2KU

class Jeasure#ent @ De"th o ? ne: De"th-.< boolean b ? true< // . . .


I" you haven t given o an initial value and you try to use it anyway, you ll get a run'ti#e error called an e*ce tion *covered in +ha%ter M@,. RFSURF STIJLT+(6PTE5?TI2LU /ou can even call a #ethod to %rovide an initiali1ation value=

class C$nit @ int i ? f-.< //... A


This #ethod can have argu#ents, o" course, but those argu#ents cannot be other class #e#bers that haven t been initiali1ed yet. Thus, you can do this= RFSURFSTIJLT+(6PTE5?TI2?U

class C$nit @ int i ? f-.< int H ? g-i.< //... A


But you cannot do this= RFSURFSTIJLT+(6PTE5?TI2HU

class C$nit @ int H ? g-i.< int i ? f-.< //... A

23=

This is one %lace in which the co#%iler, a%%ro%riately, does co#%lain about "orward re"erencing, since this has to do with the order o" initiali1ation and not the way the %rogra# is co#%iled. RFSURF STIJLT+(6PTE5?TI23U This a%%roach to initiali1ation is si#%le and straight"orward. It has the li#itation that ever) ob0ect o" ty%e 1eas*rement will get these sa#e initiali1ation values. So#eti#es this is e&actly what you need, but at other ti#es you need #ore "le&ibility. RFSURFSTIJLT+(6PTE5?TI2GU

Constructor initiali?ation
The constructor can be used to %er"or# initiali1ation, and this gives you greater "le&ibility in your %rogra##ing since you can call #ethods and %er"or# actions at run'ti#e to deter#ine the initial values. There s one thing to kee% in #ind, however= you aren t %recluding the auto#atic initiali1ation, which ha%%ens be"ore the constructor is entered. So, "or e&a#%le, i" you say=

class Counter @ int i< Counter-. @ i ? *< A // . . .


then i will "irst be initiali1ed to @, then to G. This is true with all the %ri#itive ty%es and with ob0ect re"erences, including those that are given e&%licit initiali1ation at the %oint o" de"inition. Eor this reason, the co#%iler doesn t try to "orce you to initiali1e ele#ents in the constructor at any %articular %lace, or be"ore they are used9initiali1ation is already guaranteed @. RFSURFSTIJLT+(6PTE5?TI2IU

Order of initiali?ation
:ithin a class, the order o" initiali1ation is deter#ined by the order that the variables are de"ined within the class. The variable de"initions #ay be scattered throughout and in between #ethod de"initions, but the

@ In contrast, +<< has the constructor initiali?er list that causes initiali1ation to occur be"ore entering the constructor body, and is en"orced "or ob0ects. See Thinking in C++D 2nd edition *available on this book s +7 5)M and at ,,,'0ruceEckel'com,.

Cha ter 4! Initiali?ation & Cleanu

231

variables are initiali1ed be"ore any #ethods can be called9even the constructor. Eor e&a#%le= RFSURFSTIJLT+(6PTE5?TI22U

//3 c'I3Gr!erGf$nitialiUation.Hava // De#onstrates initialiUation or!er. // \hen the constructor is calle! to create a // Tag obHect, you2ll see a #essage3 class Tag @ Tag-int #arker. @ %yste#.out."rintln-8Tag-8 K #arker K 8.8.< A A class Car! @ Tag t( ? ne: Tag-(.< // Before constructor Car!-. @ // $n!icate :e2re in the constructor3 %yste#.out."rintln-8Car!-.8.< t) ? ne: Tag-)).< // 5einitialiUe t) A Tag t ? ne: Tag- .< // 0fter constructor voi! f-. @ %yste#.out."rintln-8f-.8.< A Tag t) ? ne: Tag-).< // 0t en! A "ublic class Gr!erGf$nitialiUation @ "ublic static voi! #ain-%tringNO args. @ Car! t ? ne: Car!-.< t.f-.< // %ho:s that construction is !one A A ///3>
In -ar', the de"initions o" the Tag ob0ects are intentionally scattered about to %rove that they ll all get initiali1ed be"ore the constructor is entered or anything else can ha%%en. In addition, tJ is reinitiali1ed inside the constructor. The out%ut is= RFSURFSTIJLT+(6PTE5?TIM@@U

Tag-(. Tag- .

232

Tag-). Car!-. Tag-)). f-.


Thus, the tJ re"erence gets initiali1ed twice, once be"ore and once during the constructor call. *The "irst ob0ect is dro%%ed, so it can be garbage' collected later., This #ight not see# e""icient at "irst, but it guarantees %ro%er initiali1ation9what would ha%%en i" an overloaded constructor were de"ined that did not initiali1e tJ and there wasn t a !de"ault$ initiali1ation "or tJ in its de"initionO RFSURFSTIJLT+(6PTE5?TIM@MU

1tatic data initiali?ation


:hen the data is static the sa#e thing ha%%ens; i" it s a %ri#itive and you don t initiali1e it, it gets the standard %ri#itive initial values. I" it s a re"erence to an ob0ect, it s n*ll unless you create a new ob0ect and attach your re"erence to it. RFSURFSTIJLT+(6PTE5?TIM@KU I" you want to %lace initiali1ation at the %oint o" de"inition, it looks the sa#e as "or non' statics. There s only a single %iece o" storage "or a static, regardless o" how #any ob0ects are created. But the Auestion arises o" when the static storage gets initiali1ed. 6n e&a#%le #akes this Auestion clear= RFSURFSTIJLT+(6PTE5?TIM@LU

//3 c'I3%tatic$nitialiUation.Hava // %"ecifying initial values in a // class !efinition. class Bo:l @ Bo:l-int #arker. @ %yste#.out."rintln-8Bo:l-8 K #arker K 8.8.< A voi! f-int #arker. @ %yste#.out."rintln-8f-8 K #arker K 8.8.< A A class Table @ static Bo:l b( ? ne: Bo:l-(.< Table-. @

Cha ter 4! Initiali?ation & Cleanu

233

%yste#.out."rintln-8Table-.8.< b .f-(.< A voi! f -int #arker. @ %yste#.out."rintln-8f -8 K #arker K 8.8.< A static Bo:l b ? ne: Bo:l- .< A class Cu"boar! @ Bo:l b) ? ne: Bo:l-).< static Bo:l bI ? ne: Bo:l-I.< Cu"boar!-. @ %yste#.out."rintln-8Cu"boar!-.8.< bI.f- .< A voi! f)-int #arker. @ %yste#.out."rintln-8f)-8 K #arker K 8.8.< A static Bo:l b, ? ne: Bo:l-,.< A "ublic class %tatic$nitialiUation @ "ublic static voi! #ain-%tringNO args. @ %yste#.out."rintln8Creating ne: Cu"boar!-. in #ain8.< ne: Cu"boar!-.< %yste#.out."rintln8Creating ne: Cu"boar!-. in #ain8.< ne: Cu"boar!-.< t .f -(.< t).f)-(.< A static Table t ? ne: Table-.< static Cu"boar! t) ? ne: Cu"boar!-.< A ///3> 2o(l allows you to view the creation o" a class, and Table and -*pboar' create static #e#bers o" 2o(l scattered through their class de"initions. Cote that -*pboar' creates a non' static 2o(l bJ %rior to

234

the static de"initions. The out%ut shows what ha%%ens= RFSURF STIJLT+(6PTE5?TIM@?U

Bo:l-(. Bo:l- . Table-. f-(. Bo:l-I. Bo:l-,. Bo:l-). Cu"boar!-. f- . Creating ne: Cu"boar!-. in #ain Bo:l-). Cu"boar!-. f- . Creating ne: Cu"boar!-. in #ain Bo:l-). Cu"boar!-. f- . f -(. f)-(.
The static initiali1ation occurs only i" it s necessary. I" you don t create a Table ob0ect and you never re"er to Table!b> or Table!bI, the static 2o(l b> and bI will never be created. (owever, they are initiali1ed only when the $irst Table ob0ect is created *or the "irst static access occurs,. 6"ter that, the static ob0ects are not reinitiali1ed. RFSURF STIJLT+(6PTE5?TIM@HU The order o" initiali1ation is statics "irst, i" they haven t already been initiali1ed by a %revious ob0ect creation, and then the non' static ob0ects. /ou can see the evidence o" this in the out%ut. RFSURF STIJLT+(6PTE5?TIM@3U It s hel%"ul to su##ari1e the %rocess o" creating an ob0ect. +onsider a class called og= RFSURFSTIJLT+(6PTE5?TIM@GU

*!)

The "irst ti#e an ob0ect o" ty%e og is created, or the "irst ti#e a static #ethod or static "ield o" class og is accessed, the Java

Cha ter 4! Initiali?ation & Cleanu

235

inter%reter #ust locate og!class, which it does by searching through the class%ath. RFSURFSTIJLT+(6PTE5?TIM@IU

**)

6s og!class is loaded *creating a -lass ob0ect, which you ll learn about later,, all o" its static initiali1ers are run. Thus, static initiali1ation takes %lace only once, as the -lass ob0ect is loaded "or the "irst ti#e. RFSURFSTIJLT+(6PTE5?TIM@2U :hen you create a ne( ogA B, the construction %rocess "or a og ob0ect "irst allocates enough storage "or a og ob0ect on the hea%. RFSURFSTIJLT+(6PTE5?TIMM@U This storage is wi%ed to 1ero, auto#atically setting all the %ri#itives in that og ob0ect to their de"ault values *1ero "or nu#bers and the eAuivalent "or boolean and char, and the re"erences to n*ll. RFSURFSTIJLT+(6PTE5?TIMMMU 6ny initiali1ations that occur at the %oint o" "ield de"inition are e&ecuted. RFSURFSTIJLT+(6PTE5?TIMMKU +onstructors are e&ecuted. 6s you shall see in +ha%ter 3, this #ight actually involve a "air a#ount o" activity, es%ecially when inheritance is involved. RFSURFSTIJLT+(6PTE5?TIMMLU

*+)

*,)

*-) *4)

/0.licit static initiali?ation


Java allows you to grou% other static initiali1ations inside a s%ecial ! static construction clause$ *so#eti#es called a static block, in a class. It looks like this= RFSURFSTIJLT+(6PTE5?TIMM?U

class %"oon @ static int i< static @ i ? I*< A // . . .


It a%%ears to be a #ethod, but it s 0ust the static keyword "ollowed by a #ethod body. This code, like other static initiali1ations, is e&ecuted only once, the "irst ti#e you #ake an ob0ect o" that class or the "irst ti#e you access a static #e#ber o" that class *even i" you never #ake an ob0ect o" that class,. Eor e&a#%le= RFSURFSTIJLT+(6PTE5?TIMMHU

237

//3 c'I3E6"licit%tatic.Hava // E6"licit static initialiUation // :ith the 8static8 clause. class Cu" @ Cu"-int #arker. @ %yste#.out."rintln-8Cu"-8 K #arker K 8.8.< A voi! f-int #arker. @ %yste#.out."rintln-8f-8 K #arker K 8.8.< A A class Cu"s @ static Cu" c(< static Cu" c < static @ c( ? ne: Cu"-(.< c ? ne: Cu"- .< A Cu"s-. @ %yste#.out."rintln-8Cu"s-.8.< A A "ublic class E6"licit%tatic @ "ublic static voi! #ain-%tringNO args. @ %yste#.out."rintln-8$nsi!e #ain-.8.< Cu"s.c(.f-CC.< // -(. A // static Cu"s 6 ? ne: Cu"s-.< // - . // static Cu"s y ? ne: Cu"s-.< // - . A ///3>
The static initiali1ers "or -*ps run when either the access o" the static ob0ect c> occurs on the line #arked *M,, or i" line *M, is co##ented out and the lines #arked *K, are unco##ented. I" both *M, and *K, are co##ented out, the static initiali1ation "or -*ps never occurs. 6lso, it doesn t #atter i" one or both o" the lines #arked *K, are unco##ented; the static initiali1ation only occurs once. RFSURF STIJLT+(6PTE5?TIMM3U

Cha ter 4! Initiali?ation & Cleanu

238

2on@static instance initiali?ation


Java %rovides a si#ilar synta& "or initiali1ing non' static variables "or each ob0ect. (ere s an e&a#%le=

//3 c'I3Jugs.Hava // Java 8$nstance $nitialiUation.8 class Jug @ Jug-int #arker. @ %yste#.out."rintln-8Jug-8 K #arker K 8.8.< A voi! f-int #arker. @ %yste#.out."rintln-8f-8 K #arker K 8.8.< A A "ublic class Jugs @ Jug c(< Jug c < @ c( ? ne: Jug-(.< c ? ne: Jug- .< %yste#.out."rintln-8c( D c initialiUe!8.< A Jugs-. @ %yste#.out."rintln-8Jugs-.8.< A "ublic static voi! #ain-%tringNO args. @ %yste#.out."rintln-8$nsi!e #ain-.8.< Jugs 6 ? ne: Jugs-.< A A ///3>
/ou can see that the instance initiali1ation clause= RFSURF STIJLT+(6PTE5?TIMMGU

@ c( ? ne: Jug-(.< c ? ne: Jug- .< %yste#.out."rintln-8c( D c A initialiUe!8.<

23:

looks e&actly like the static initiali1ation clause e&ce%t "or the #issing

static keyword. This synta& is necessary to su%%ort the initiali1ation o" anon)mous inner classes *see +ha%ter I,. RFSURF
STIJLT+(6PTE5?TIMMIU

Arra: initiali?ation
Initiali1ing arrays in + is error'%rone and tedious. +<< uses aggregate initiali?ation to #ake it #uch sa"er @. Java has no !aggregates$ like +<<, since everything is an ob0ect in Java. It does have arrays, and these are su%%orted with array initiali1ation. RFSURFSTIJLT+(6PTE5?TIMM2U 6n array is si#%ly a seAuence o" either ob0ects or %ri#itives, all the sa#e ty%e and %ackaged together under one identi"ier na#e. 6rrays are de"ined and used with the sAuare'brackets inde*ing o erator ] ^. To de"ine an array you si#%ly "ollow your ty%e na#e with e#%ty sAuare brackets= RF SURFSTIJLT+(6PTE5?TIMK@U

intNO a(<
/ou can also %ut the sAuare brackets a"ter the identi"ier to %roduce e&actly the sa#e #eaning= RFSURFSTIJLT+(6PTE5?TIMKMU

int a(NO<
This con"or#s to e&%ectations "ro# + and +<< %rogra##ers. The "or#er style, however, is %robably a #ore sensible synta&, since it says that the ty%e is !an int array.$ That style will be used in this book. RFSURF STIJLT+(6PTE5?TIMKKU The co#%iler doesn t allow you to tell it how big the array is. This brings us back to that issue o" !re"erences.$ 6ll that you have at this %oint is a re"erence to an array, and there s been no s%ace allocated "or the array. To create storage "or the array you #ust write an initiali1ation e&%ression. Eor arrays, initiali1ation can a%%ear anywhere in your code, but you can also use a s%ecial kind o" initiali1ation e&%ression that #ust occur at the %oint where the array is created. This s%ecial initiali1ation is a set o"
@ See Thinking in C++D 2nd edition "or a co#%lete descri%tion o" +<< aggregate initiali1ation.

Cha ter 4! Initiali?ation & Cleanu

23;

values surrounded by curly braces. The storage allocation *the eAuivalent o" using ne(, is taken care o" by the co#%iler in this case. Eor e&a#%le= RFSURFSTIJLT+(6PTE5?TIMKLU

intNO a( ? @ (,

, ), I, , A<

So why would you ever de"ine an array re"erence without an arrayO RF SURFSTIJLT+(6PTE5?TIMK?U

intNO a <
:ell, it s %ossible to assign one array to another in Java, so you can say= RFSURFSTIJLT+(6PTE5?TIMKHU

? a(<

:hat you re really doing is co%ying a re"erence, as de#onstrated here= RF SURFSTIJLT+(6PTE5?TIMK3U

//3 c'I30rrays.Hava // 0rrays of "ri#itives. "ublic class 0rrays @ "ublic static voi! #ain-%tringNO args. @ intNO a( ? @ (, , ), I, , A< intNO a < a ? a(< for-int i ? '< i P a .length< iKK. a NiOKK< for-int i ? '< i P a(.length< iKK. %yste#.out."rintln8a(N8 K i K 8O ? 8 K a(NiO.< A A ///3>
/ou can see that a> is given an initiali1ation value while aI is not; aI is assigned later9in this case, to another array. RFSURF STIJLT+(6PTE5?TIMKGU There s so#ething new here= all arrays have an intrinsic #e#ber *whether they re arrays o" ob0ects or arrays o" %ri#itives, that you can Auery9but not change9to tell you how #any ele#ents there are in the array. This #e#ber is length. Since arrays in Java, like + and +<<, start

24=

counting "ro# ele#ent 1ero, the largest ele#ent you can inde& is length 6 >. I" you go out o" bounds, + and +<< Auietly acce%t this and allow you to sto#% all over your #e#ory, which is the source o" #any in"a#ous bugs. (owever, Java %rotects you against such %roble#s by causing a run'ti#e error *an e*ce tion, the sub0ect o" +ha%ter M@, i" you ste% out o" bounds. )" course, checking every array access costs ti#e and code and there s no way to turn it o"", which #eans that array accesses #ight be a source o" ine""iciency in your %rogra# i" they occur at a critical 0uncture. Eor Internet security and %rogra##er %roductivity, the Java designers thought that this was a worthwhile trade'o"". RFSURF STIJLT+(6PTE5?TIMKIU :hat i" you don t know how #any ele#ents you re going to need in your array while you re writing the %rogra#O /ou si#%ly use ne( to create the ele#ents in the array. (ere, ne( works even though it s creating an array o" %ri#itives * ne( won t create a nonarray %ri#itive,= RFSURF STIJLT+(6PTE5?TIMK2U

//3 c'I30rray&e:.Hava // Creating arrays :ith ne:. i#"ort Hava.util.B< "ublic class 0rray&e: @ static 5an!o# ran! ? ne: 5an!o#-.< static int "5an!-int #o!. @ return Jath.abs-ran!.ne6t$nt-.. V #o! K (< A "ublic static voi! #ain-%tringNO args. @ intNO a< a ? ne: intN"5an!- '.O< %yste#.out."rintln8length of a ? 8 K a.length.< for-int i ? '< i P a.length< iKK. %yste#.out."rintln8aN8 K i K 8O ? 8 K aNiO.< A A ///3>
Since the si1e o" the array is chosen at rando# *using the p$an'A B #ethod,, it s clear that array creation is actually ha%%ening at run'ti#e. In addition, you ll see "ro# the out%ut o" this %rogra# that array ele#ents

Cha ter 4! Initiali?ation & Cleanu

241

o" %ri#itive ty%es are auto#atically initiali1ed to !e#%ty$ values. *Eor nu#erics and char, this is 1ero, and "or boolean, it s false., RFSURF STIJLT+(6PTE5?TIML@U )" course, the array could also have been de"ined and initiali1ed in the sa#e state#ent=

intNO a ? ne: intN"5an!- '.O<


I" you re dealing with an array o" non%ri#itive ob0ects, you #ust always use ne(. (ere, the re"erence issue co#es u% again because what you create is an array o" re"erences. +onsider the wra%%er ty%e Integer, which is a class and not a %ri#itive= RFSURFSTIJLT+(6PTE5?TIMLMU

//3 c'I30rrayClassGbH.Hava // Creating an array of non"ri#itive obHects. i#"ort Hava.util.B< "ublic class 0rrayClassGbH @ static 5an!o# ran! ? ne: 5an!o#-.< static int "5an!-int #o!. @ return Jath.abs-ran!.ne6t$nt-.. V #o! K (< A "ublic static voi! #ain-%tringNO args. @ $ntegerNO a ? ne: $ntegerN"5an!- '.O< %yste#.out."rintln8length of a ? 8 K a.length.< for-int i ? '< i P a.length< iKK. @ aNiO ? ne: $nteger-"5an!-,''..< %yste#.out."rintln8aN8 K i K 8O ? 8 K aNiO.< A A A ///3>
(ere, even a"ter ne( is called to create the array= RFSURF STIJLT+(6PTE5?TIMLKU

$ntegerNO a ? ne: $ntegerN"5an!- '.O<

242

it s only an array o" re"erences, and not until the re"erence itsel" is initiali1ed by creating a new Integer ob0ect is the initiali1ation co#%lete= RFSURFSTIJLT+(6PTE5?TIMLLU

aNiO ? ne: $nteger-"5an!-,''..<


I" you "orget to create the ob0ect, however, you ll get an e&ce%tion at run' ti#e when you try to read the e#%ty array location. RFSURF STIJLT+(6PTE5?TIML?U Take a look at the "or#ation o" the )tring ob0ect inside the %rint state#ents. /ou can see that the re"erence to the Integer ob0ect is auto#atically converted to %roduce a )tring re%resenting the value inside the ob0ect. RFSURFSTIJLT+(6PTE5?TIMLHU It s also %ossible to initiali1e arrays o" ob0ects using the curly'brace' enclosed list. There are two "or#s=

//3 c'I30rray$nit.Hava // 0rray initialiUation. "ublic class 0rray$nit @ "ublic static voi! #ain-%tringNO args. @ $ntegerNO a ? @ ne: $nteger-(., ne: $nteger- ., ne: $nteger-)., A< $ntegerNO b ? ne: $ntegerNO @ ne: $nteger-(., ne: $nteger- ., ne: $nteger-)., A< A A ///3>
This is use"ul at ti#es, but it s #ore li#ited since the si1e o" the array is deter#ined at co#%ile'ti#e. The "inal co##a in the list o" initiali1ers is o%tional. *This "eature #akes "or easier #aintenance o" long lists., RF SURFSTIJLT+(6PTE5?TIML3U

Cha ter 4! Initiali?ation & Cleanu

243

The second "or# o" array initiali1ation %rovides a convenient synta& to create and call #ethods that can %roduce the sa#e e""ect as + s variable argument lists *known as !varargs$ in +,. These can include unknown Auantity o" argu#ents as well as unknown ty%es. Since all classes are ulti#ately inherited "ro# the co##on root class .b8ect *a sub0ect you will learn #ore about as this book %rogresses,, you can create a #ethod that takes an array o" .b8ect and call it like this= RFSURF STIJLT+(6PTE5?TIMLGU

//3 c'I3War0rgs.Hava // Ysing the array synta6 to create // variable argu#ent lists. class 0 @ int i< A "ublic class War0rgs @ static voi! f-GbHectNO 6. @ for-int i ? '< i P 6.length< iKK. %yste#.out."rintln-6NiO.< A "ublic static voi! #ain-%tringNO args. @ f-ne: GbHectNO @ ne: $nteger-I*., ne: War0rgs-., ne: Lloat-).(I., ne: Double-((.((. A.< f-ne: GbHectNO @8one8, 8t:o8, 8three8 A.< f-ne: GbHectNO @ne: 0-., ne: 0-., ne: 0-.A.< A A ///3>
6t this %oint, there s not #uch you can do with these unknown ob0ects, and this %rogra# uses the auto#atic )tring conversion to do so#ething use"ul with each .b8ect. In +ha%ter MK, which covers run/time t) e identi$ication *5TTI,, you ll learn how to discover the e&act ty%e o" such ob0ects so that you can do so#ething #ore interesting with the#. RFSURF STIJLT+(6PTE5?TIMLIU

Multidimensional arra:s
Java allows you to easily create #ultidi#ensional arrays=

//3 c'I3JultiDi#0rray.Hava

244

// Creating #ulti!i#ensional arrays. i#"ort Hava.util.B< "ublic class JultiDi#0rray @ static 5an!o# ran! ? ne: 5an!o#-.< static int "5an!-int #o!. @ return Jath.abs-ran!.ne6t$nt-.. V #o! K (< A static voi! "rt-%tring s. @ %yste#.out."rintln-s.< A "ublic static voi! #ain-%tringNO args. @ intNONO a( ? @ @ (, , ), A, @ I, ,, +, A, A< for-int i ? '< i P a(.length< iKK. for-int H ? '< H P a(NiO.length< HKK. "rt-8a(N8 K i K 8ON8 K H K 8O ? 8 K a(NiONHO.< // )-D array :ith fi6e! length3 intNONONO a ? ne: intN ON ONIO< for-int i ? '< i P a .length< iKK. for-int H ? '< H P a NiO.length< HKK. for-int k ? '< k P a NiONHO.length< kKK. "rt-8a N8 K i K 8ON8 K H K 8ON8 K k K 8O ? 8 K a NiONHONkO.< // )-D array :ith varie!-length vectors3 intNONONO a) ? ne: intN"5an!-*.ONONO< for-int i ? '< i P a).length< iKK. @ a)NiO ? ne: intN"5an!-,.ONO< for-int H ? '< H P a)NiO.length< HKK. a)NiONHO ? ne: intN"5an!-,.O< A for-int i ? '< i P a).length< iKK. for-int H ? '< H P a)NiO.length< HKK. for-int k ? '< k P a)NiONHO.length< kKK. "rt-8a)N8 K i K 8ON8 K

Cha ter 4! Initiali?ation & Cleanu

245

H K 8ON8 K k K 8O ? 8 K a)NiONHONkO.< // 0rray of non"ri#itive obHects3 $ntegerNONO aI ? @ @ ne: $nteger-(., ne: $nteger- .A, @ ne: $nteger-)., ne: $nteger-I.A, @ ne: $nteger-,., ne: $nteger-+.A, A< for-int i ? '< i P aI.length< iKK. for-int H ? '< H P aINiO.length< HKK. "rt-8aIN8 K i K 8ON8 K H K 8O ? 8 K aINiONHO.< $ntegerNONO a,< a, ? ne: $ntegerN)ONO< for-int i ? '< i P a,.length< iKK. @ a,NiO ? ne: $ntegerN)O< for-int H ? '< H P a,NiO.length< HKK. a,NiONHO ? ne: $nteger-iBH.< A for-int i ? '< i P a,.length< iKK. for-int H ? '< H P a,NiO.length< HKK. "rt-8a,N8 K i K 8ON8 K H K 8O ? 8 K a,NiONHO.< A A ///3>
The code used "or %rinting uses length so that it doesn t de%end on "i&ed array si1es. RFSURFSTIJLT+(6PTE5?TIML2U The "irst e&a#%le shows a #ultidi#ensional array o" %ri#itives. /ou deli#it each vector in the array with curly braces=

intNONO a( ? @ @ (, , ), A, @ I, ,, +, A, A<
Each set o" sAuare brackets #oves you into the ne&t level o" the array. RF SURFSTIJLT+(6PTE5?TIM?@U The second e&a#%le shows a three'di#ensional array allocated with ne(. (ere, the whole array is allocated at once=

247

intNONONO a

? ne: intN ON ONIO<

But the third e&a#%le shows that each vector in the arrays that #ake u% the #atri& can be o" any length=

intNONONO a) ? ne: intN"5an!-*.ONONO< for-int i ? '< i P a).length< iKK. @ a)NiO ? ne: intN"5an!-,.ONO< for-int H ? '< H P a)NiO.length< HKK. a)NiONHO ? ne: intN"5an!-,.O< A
The "irst ne( creates an array with a rando#'length "irst ele#ent and the rest undeter#ined. The second ne( inside the for loo% "ills out the ele#ents but leaves the third inde& undeter#ined until you hit the third ne(. RFSURFSTIJLT+(6PTE5?TIM?MU /ou will see "ro# the out%ut that array values are auto#atically initiali1ed to 1ero i" you don t give the# an e&%licit initiali1ation value. /ou can deal with arrays o" non%ri#itive ob0ects in a si#ilar "ashion, which is shown in the "ourth e&a#%le, de#onstrating the ability to collect #any ne( e&%ressions with curly braces=

$ntegerNONO aI ? @ @ ne: $nteger-(., ne: $nteger- .A, @ ne: $nteger-)., ne: $nteger-I.A, @ ne: $nteger-,., ne: $nteger-+.A, A<
The "i"th e&a#%le shows how an array o" non%ri#itive ob0ects can be built u% %iece by %iece=

$ntegerNONO a,< a, ? ne: $ntegerN)ONO< for-int i ? '< i P a,.length< iKK. @ a,NiO ? ne: $ntegerN)O< for-int H ? '< H P a,NiO.length< HKK. a,NiONHO ? ne: $nteger-iBH.< A
The iK8 is 0ust to %ut an interesting value into the Integer. RFSURF STIJLT+(6PTE5?TIM?KU

Cha ter 4! Initiali?ation & Cleanu

248

1ummar:
This see#ingly elaborate #echanis# "or initiali1ation, the constructor, should give you a strong hint about the critical i#%ortance %laced on initiali1ation in the language. 6s Stroustru% was designing +<<, one o" the "irst observations he #ade about %roductivity in + was that i#%ro%er initiali1ation o" variables causes a signi"icant %ortion o" %rogra##ing %roble#s. These kinds o" bugs are hard to "ind, and si#ilar issues a%%ly to i#%ro%er cleanu%. Because constructors allow you to guarantee %ro%er initiali1ation and cleanu% *the co#%iler will not allow an ob0ect to be created without the %ro%er constructor calls,, you get co#%lete control and sa"ety. RFSURFSTIJLT+(6PTE5?TIM?LU In +<<, destruction is Auite i#%ortant because ob0ects created with ne( #ust be e&%licitly destroyed. In Java, the garbage collector auto#atically releases the #e#ory "or all ob0ects, so the eAuivalent cleanu% #ethod in Java isn t necessary #uch o" the ti#e. In cases where you don t need destructor'like behavior, Java s garbage collector greatly si#%li"ies %rogra##ing, and adds #uch'needed sa"ety in #anaging #e#ory. So#e garbage collectors can even clean u% other resources like gra%hics and "ile handles. (owever, the garbage collector does add a run'ti#e cost, the e&%ense o" which is di""icult to %ut into %ers%ective because o" the overall slowness o" Java inter%reters at this writing. 6s this changes, we ll be able to discover i" the overhead o" the garbage collector will %reclude the use o" Java "or certain ty%es o" %rogra#s. *)ne o" the issues is the un%redictability o" the garbage collector., RFSURF STIJLT+(6PTE5?TIM??U Because o" the guarantee that all ob0ects will be constructed, there s actually #ore to the constructor than what is shown here. In %articular, when you create new classes using either com osition or inheritance the guarantee o" construction also holds, and so#e additional synta& is necessary to su%%ort this. /ou ll learn about co#%osition, inheritance, and how they a""ect constructors in "uture cha%ters. RFSURF STIJLT+(6PTE5?TIM?HU

24:

/0ercises
Solutions to selected e&ercises can be "ound in the electronic docu#entThe Thinking in Java "nnotated Solution @uide, available "or a s#all "ee "ro# ,,,'0ruceEckel'com.

!*) +reate a class with a de"ault constructor *one that takes no


argu#ents, that %rints a #essage. +reate an ob0ect o" this class. RF SURFSTIJLT+(6PTE5?TIM?3U

!+) 6dd an overloaded constructor to E&ercise M that takes a )tring


argu#ent and %rints it along with your #essage. RFSURF STIJLT+(6PTE5?TIM?GU

!,) +reate an array o" ob0ect re"erences o" the class you created in
E&ercise K, but don t actually create ob0ects to assign into the array. :hen you run the %rogra#, notice whether the initiali1ation #essages "ro# the constructor calls are %rinted. RF SURFSTIJLT+(6PTE5?TIM?IU

!-) +o#%lete E&ercise L by creating ob0ects to attach to the array o"


re"erences. RFSURFSTIJLT+(6PTE5?TIM?2U

!4) +reate an array o" )tring ob0ects and assign a string to each
ele#ent. Print the array using a for loo%. RFSURF STIJLT+(6PTE5?TIMH@U

!5) +reate a class called

og with an overloaded barkA B #ethod. This #ethod should be overloaded based on various %ri#itive data ty%es, and %rint di""erent ty%es o" barking, howling, etc., de%ending on which overloaded version is called. :rite a mainA B that calls all the di""erent versions. RFSURF STIJLT+(6PTE5?TIMHMU
two argu#ents *o" two di""erent ty%es,, but in reversed order relative to each other. Veri"y that this works. RFSURF STIJLT+(6PTE5?TIMHKU

!6) Modi"y E&ercise 3 so that two o" the overloaded #ethods have

*7) +reate a class without a constructor, and then create an ob0ect o"
that class in mainA B to veri"y that the de"ault constructor is auto#atically synthesi1ed. RFSURFSTIJLT+(6PTE5?TIMHLU

Cha ter 4! Initiali?ation & Cleanu

24;

*() +reate a class with two #ethods. :ithin the "irst #ethod, call the
second #ethod twice= the "irst ti#e without using this, and the second ti#e using this. RFSURFSTIJLT+(6PTE5?TIMH?U

*!) +reate a class with two *overloaded, constructors. 4sing this,


call the second constructor inside the "irst one. RFSURF STIJLT+(6PTE5?TIMHHU

**) +reate a class with a finali7eA B #ethod that %rints a #essage.


In mainA B, create an ob0ect o" your class. E&%lain the behavior o" your %rogra#. RFSURFSTIJLT+(6PTE5?TIMH3U

*+) Modi"y E&ercise MM so that your finali7eA B will always be called.


RFSURFSTIJLT+(6PTE5?TIMHGU

*,) +reate a class called Tank that can be "illed and e#%tied, and
has a death condition that it #ust be e#%ty when the ob0ect is cleaned u%. :rite a finali7eA B that veri"ies this death condition. In mainA B, test the %ossible scenarios that can occur when your Tank is used. RFSURFSTIJLT+(6PTE5?TIMHIU

*-) +reate a class containing an int and a char that are not
initiali1ed, and %rint their values to veri"y that Java %er"or#s de"ault initiali1ation. RFSURFSTIJLT+(6PTE5?TIMH2U

*4) +reate a class containing an uninitiali1ed )tring re"erence.


7e#onstrate that this re"erence is initiali1ed by Java to n*ll. RF SURFSTIJLT+(6PTE5?TIM3@U

*5) +reate a class with a )tring "ield that is initiali1ed at the %oint o"
de"inition, and another one that is initiali1ed by the constructor. :hat is the di""erence between the two a%%roachesO RFSURF STIJLT+(6PTE5?TIM3MU

*6) +reate a class with a static )tring "ield that is initiali1ed at the
%oint o" de"inition, and another one that is initiali1ed by the static block. 6dd a static #ethod that %rints both "ields and de#onstrates that they are both initiali1ed be"ore they are used. RFSURFSTIJLT+(6PTE5?TIM3KU

25=

+7) +reate a class with a )tring that is initiali1ed using !instance


initiali1ation.$ 7escribe a use "or this "eature *other than the one s%eci"ied in this book,. RFSURFSTIJLT+(6PTE5?TIM3LU

+() :rite a #ethod that creates and initiali1es a two'di#ensional


array o" 'o*ble. The si1e o" the array is deter#ined by the argu#ents o" the #ethod, and the initiali1ation values are a range deter#ined by beginning and ending values that are also argu#ents o" the #ethod. +reate a second #ethod that will %rint the array generated by the "irst #ethod. In mainA B test the #ethods by creating and %rinting several di""erent si1es o" arrays. RFSURFSTIJLT+(6PTE5?TIM3?U

+!) 5e%eat E&ercise M2 "or a three'di#ensional array. RFSURF


STIJLT+(6PTE5?TIM3HU

+*) +o##ent the line #arked *M, in &4plicit)tatic!8ava and veri"y


that the static initiali1ation clause is not called. Cow unco##ent one o" the lines #arked *K, and veri"y that the static initiali1ation clause is called. Cow unco##ent the other line #arked *K, and veri"y that static initiali1ation only occurs once. RFSURF STIJLT+(6PTE5?TIM33U

++) E&%eri#ent with "arbage!8ava by running the %rogra# using


the argu#ents !gc,$ !"inali1e,$ or !all.$ 5e%eat the %rocess and see i" you detect any %atterns in the out%ut. +hange the code so that )ystem!r*nFinali7ationA B is called be$ore )ystem!gcA B and observe the results. RFSU

Cha ter 4! Initiali?ation & Cleanu

251

,: >iding the Im.lementation


RFSTIJLT+(6PTE5HTI@U6 %ri#ary consideration in ob0ect'oriented design is !se%arating the things that change "ro# the things that stay the sa#e.$
This is %articularly i#%ortant "or libraries. The user * client rogrammer, o" that library #ust be able to rely on the %art they use, and know that they won t need to rewrite code i" a new version o" the library co#es out. )n the "li% side, the library creator #ust have the "reedo# to #ake #odi"ications and i#%rove#ents with the certainty that the client %rogra##er s code won t be a""ected by those changes. RFSURF STIJLT+(6PTE5HTIMU This can be achieved through convention. Eor e&a#%le, the library %rogra##er #ust agree to not re#ove e&isting #ethods when #odi"ying a class in the library, since that would break the client %rogra##er s code. The reverse situation is thornier, however. In the case o" a data #e#ber, how can the library creator know which data #e#bers have been accessed by client %rogra##ersO This is also true with #ethods that are only %art o" the i#%le#entation o" a class, and not #eant to be used directly by the client %rogra##er. But what i" the library creator wants to ri% out an old i#%le#entation and %ut in a new oneO +hanging any o" those #e#bers #ight break a client %rogra##er s code. Thus the library creator is in a strait 0acket and can t change anything. RFSURF STIJLT+(6PTE5HTIKU To solve this %roble#, Java %rovides access s eci$iers to allow the library creator to say what is available to the client %rogra##er and what is not. The levels o" access control "ro# !#ost access$ to !least access$ are p*blic, protecte', !"riendly$ *which has no keyword,, and private. Ero# the %revious %aragra%h you #ight think that, as a library designer, you ll want to kee% everything as !%rivate$ as %ossible, and e&%ose only

252

the #ethods that you want the client %rogra##er to use. This is e&actly right, even though it s o"ten counterintuitive "or %eo%le who %rogra# in other languages *es%ecially +, and are used to accessing everything without restriction. By the end o" this cha%ter you should be convinced o" the value o" access control in Java. RFSURFSTIJLT+(6PTE5HTILU The conce%t o" a library o" co#%onents and the control over who can access the co#%onents o" that library is not co#%lete, however. There s still the Auestion o" how the co#%onents are bundled together into a cohesive library unit. This is controlled with the package keyword in Java, and the access s%eci"iers are a""ected by whether a class is in the sa#e %ackage or in a se%arate %ackage. So to begin this cha%ter, you ll learn how library co#%onents are %laced into %ackages. Then you ll be able to understand the co#%lete #eaning o" the access s%eci"iers. RFSURF STIJLT+(6PTE5HTI?U

.ackage: the librar: unit


6 %ackage is what you get when you use the import keyword to bring in an entire library, such as

i#"ort Hava.util.B<
This brings in the entire utility library that s %art o" the standard Java distribution. Since, "or e&a#%le, the class Array+ist is in 8ava!*til, you can now either s%eci"y the "ull na#e 8ava!*til!Array+ist *which you can do without the import state#ent,, or you can si#%ly say Array+ist *because o" the import,. RFSURFSTIJLT+(6PTE5HTIHU I" you want to bring in a single class, you can na#e that class in the import state#ent

i#"ort Hava.util.0rrayList<
Cow you can use Array+ist with no Auali"ication. (owever, none o" the other classes in 8ava!*til are available. RFSURFSTIJLT+(6PTE5HTI3U

Cha ter 5! .iding the Im lementation

253

The reason "or all this i#%orting is to %rovide a #echanis# to #anage ! na#e s%aces.$ The na#es o" all your class #e#bers are insulated "ro# each other. 6 #ethod fA B inside a class A will not clash with an fA B that has the sa#e signature *argu#ent list, in class 2. But what about the class na#esO Su%%ose you create a stack class that is installed on a #achine that already has a stack class that s written by so#eone elseO :ith Java on the Internet, this can ha%%en without the user knowing it, since classes can get downloaded auto#atically in the %rocess o" running a Java %rogra#. RFSURFSTIJLT+(6PTE5HTIGU This %otential clashing o" na#es is why it s i#%ortant to have co#%lete control over the na#e s%aces in Java, and to be able to create a co#%letely uniAue na#e regardless o" the constraints o" the Internet. RF SURFSTIJLT+(6PTE5HTIIU So "ar, #ost o" the e&a#%les in this book have e&isted in a single "ile and have been designed "or local use, and haven t bothered with %ackage na#es. *In this case the class na#e is %laced in the !de"ault %ackage.$, This is certainly an o%tion, and "or si#%licity s sake this a%%roach will be used whenever %ossible throughout the rest o" this book. (owever, i" you re %lanning to create libraries or %rogra#s that are "riendly to other Java %rogra#s on the sa#e #achine, you #ust think about %reventing class na#e clashes. RFSURFSTIJLT+(6PTE5HTI2U :hen you create a source'code "ile "or Java, it s co##only called a

com ilation unit *so#eti#es a translation unit,. Each co#%ilation unit #ust have a na#e ending in !8ava, and inside the co#%ilation unit there can be a p*blic class that #ust have the sa#e na#e as the "ile *including ca%itali1ation, but e&cluding the !8ava "ilena#e e&tension,. There can be only one p*blic class in each co#%ilation unit, otherwise the co#%iler
will co#%lain. The rest o" the classes in that co#%ilation unit, i" there are any, are hidden "ro# the world outside that %ackage because they re not p*blic, and they co#%rise !su%%ort$ classes "or the #ain p*blic class. RFSURFSTIJLT+(6PTE5HTIM@U :hen you co#%ile a !8ava "ile you get an out%ut "ile with e&actly the sa#e na#e but an e&tension o" !class $or each class in the !8ava "ile. Thus you can end u% with Auite a "ew !class "iles "ro# a s#all nu#ber o" !8ava "iles. I" you ve %rogra##ed with a co#%iled language, you #ight be used

254

to the co#%iler s%itting out an inter#ediate "or# *usually an !ob0$ "ile, that is then %ackaged together with others o" its kind using a linker *to create an e&ecutable "ile, or a librarian *to create a library,. That s not how Java works. 6 working %rogra# is a bunch o" !class "iles, which can be %ackaged and co#%ressed into a J65 "ile *using Java s 8ar archiver,. The Java inter%reter is res%onsible "or "inding, loading, and inter%reting these "iles @. RFSURFSTIJLT+(6PTE5HTIMMU 6 library is also a bunch o" these class "iles. Each "ile has one class that is p*blic *you re not "orced to have a p*blic class, but it s ty%ical,, so there s one co#%onent "or each "ile. I" you want to say that all these co#%onents *that are in their own se%arate !8ava and !class "iles, belong together, that s where the package keyword co#es in. RFSURF STIJLT+(6PTE5HTIMKU :hen you say=

"ackage #y"ackage<
at the beginning o" a "ile *i" you use a package state#ent, it must a%%ear as the "irst nonco##ent in the "ile,, you re stating that this co#%ilation unit is %art o" a library na#ed mypackage. )r, %ut another way, you re saying that the p*blic class na#e within this co#%ilation unit is under the u#brella o" the na#e mypackage, and i" anyone wants to use the na#e they #ust either "ully s%eci"y the na#e or use the import keyword in co#bination with mypackage *using the choices given %reviously,. Cote that the convention "or Java %ackage na#es is to use all lowercase letters, even "or inter#ediate words. RFSURFSTIJLT+(6PTE5HTIMLU Eor e&a#%le, su%%ose the na#e o" the "ile is 1y-lass!8ava. This #eans there can be one and only one p*blic class in that "ile, and the na#e o" that class #ust be 1y-lass *including the ca%itali1ation,=

"ackage #y"ackage< "ublic class JyClass @ // . . .


Cow, i" so#eone wants to use 1y-lass or, "or that #atter, any o" the other p*blic classes in mypackage, they #ust use the import keyword
@ There s nothing in Java that "orces the use o" an inter%reter. There e&ist native'code Java co#%ilers that generate a single e&ecutable "ile.

Cha ter 5! .iding the Im lementation

255

to #ake the na#e or na#es in mypackage available. The alternative is to give the "ully Auali"ied na#e=

#y"ackage.JyClass # ? ne: #y"ackage.JyClass-.<


The import keyword can #ake this #uch cleaner=

i#"ort #y"ackage.B< // . . . JyClass # ? ne: JyClass-.<


It s worth kee%ing in #ind that what the package and import keywords allow you to do, as a library designer, is to divide u% the single global na#e s%ace so you won t have clashing na#es, no #atter how #any %eo%le get on the Internet and start writing classes in Java. RFSURF STIJLT+(6PTE5HTIM?U

Creating uni%ue .ackage names


/ou #ight observe that, since a %ackage never really gets !%ackaged$ into a single "ile, a %ackage could be #ade u% o" #any !class "iles, and things could get a bit cluttered. To %revent this, a logical thing to do is to %lace all the !class "iles "or a %articular %ackage into a single directory; that is, use the hierarchical "ile structure o" the o%erating syste# to your advantage. This is one way that Java re"erences the %roble# o" clutter; you ll see the other way later when the 8ar utility is introduced. RFSURF STIJLT+(6PTE5HTIMHU +ollecting the %ackage "iles into a single subdirectory solves two other %roble#s= creating uniAue %ackage na#es, and "inding those classes that #ight be buried in a directory structure so#e%lace. This is acco#%lished, as was introduced in +ha%ter K, by encoding the %ath o" the location o" the !class "ile into the na#e o" the package. The co#%iler en"orces this, but by convention, the "irst %art o" the package na#e is the Internet do#ain na#e o" the creator o" the class, reversed. Since Internet do#ain na#es are guaranteed to be uniAue, i$ you "ollow this convention it s guaranteed that your package na#e will be uniAue and thus you ll never have a na#e clash. *That is, until you lose the do#ain na#e to so#eone else who starts writing Java code with the sa#e %ath na#es as you did., )" course, i" you don t have your own do#ain na#e then you #ust

257

"abricate an unlikely co#bination *such as your "irst and last na#e, to create uniAue %ackage na#es. I" you ve decided to start %ublishing Java code it s worth the relatively s#all e""ort to get a do#ain na#e. RFSURF STIJLT+(6PTE5HTIM3U The second %art o" this trick is resolving the package na#e into a directory on your #achine, so when the Java %rogra# runs and it needs to load the !class "ile *which it does dyna#ically, at the %oint in the %rogra# where it needs to create an ob0ect o" that %articular class, or the "irst ti#e you access a static #e#ber o" the class,, it can locate the directory where the !class "ile resides. RFSURFSTIJLT+(6PTE5HTIMGU The Java inter%reter %roceeds as "ollows. Eirst, it "inds the environ#ent variable +D6SSP6T( *set via the o%erating syste#, so#eti#es by the installation %rogra# that installs Java or a Java'based tool on your #achine,. +D6SSP6T( contains one or #ore directories that are used as roots "or a search "or !class "iles. Starting at that root, the inter%reter will take the %ackage na#e and re%lace each dot with a slash to generate a %ath na#e "ro# the +D6SSP6T( root *so package foo!bar!ba7 beco#es fooHbarHba7 or foo5bar5ba7 or %ossibly so#ething else, de%ending on your o%erating syste#,. This is then concatenated to the various entries in the +D6SSP6T(. That s where it looks "or the !class "ile with the na#e corres%onding to the class you re trying to create. *It also searches so#e standard directories relative to where the Java inter%reter resides,. RFSURFSTIJLT+(6PTE5HTIMIU To understand this, consider #y do#ain na#e, which is br*ceeckel! com. By reversing this, com!br*ceeckel establishes #y uniAue global na#e "or #y classes. *The co#, edu, org, etc., e&tension was "or#erly ca%itali1ed in Java %ackages, but this was changed in Java K so the entire %ackage na#e is lowercase., I can "urther subdivide this by deciding that I want to create a library na#ed simple, so I ll end u% with a %ackage na#e=

"ackage co#.bruceeckel.si#"le<
Cow this %ackage na#e can be used as an u#brella na#e s%ace "or the "ollowing two "iles= RFSURFSTIJLT+(6PTE5HTIM2U

//3 co#3bruceeckel3si#"le3Wector.Hava

Cha ter 5! .iding the Im lementation

258

// Creating a "ackage. "ackage co#.bruceeckel.si#"le< "ublic class Wector @ "ublic Wector-. @ %yste#.out."rintln8co#.bruceeckel. si#"leutil.Wector8.< A A ///3>
:hen you create your own %ackages, you ll discover that the package state#ent #ust be the "irst nonco##ent code in the "ile. The second "ile looks #uch the sa#e= RFSURFSTIJLT+(6PTE5HTIK@U

//3 co#3bruceeckel3si#"le3List.Hava // Creating a "ackage. "ackage co#.bruceeckel.si#"le< "ublic class List @ "ublic List-. @ %yste#.out."rintln8co#.bruceeckel. si#"leutil.List8.< A A ///3>
Both o" these "iles are %laced in the subdirectory on #y syste#= RFSURF STIJLT+(6PTE5HTIKMU

C3_DGC_JavaT_co#_bruceeckel_si#"le
I" you walk back through this, you can see the %ackage na#e com! br*ceeckel!simple, but what about the "irst %ortion o" the %athO That s taken care o" in the +D6SSP6T( environ#ent variable, which is, on #y #achine= RFSURFSTIJLT+(6PTE5HTIKKU

CL0%%P0TM?.<D3_J0W0_L$B<C3_DGC_JavaT
/ou can see that the +D6SSP6T( can contain a nu#ber o" alternative search %aths. RFSURFSTIJLT+(6PTE5HTIKLU There s a variation when using J65 "iles, however. /ou #ust %ut the na#e o" the J65 "ile in the class%ath, not 0ust the %ath where it s located. So "or a J65 na#ed grape!8ar your class%ath would include=

25:

CL0%%P0TM?.<D3_J0W0_L$B<C3_flavors_gra"e.Har
)nce the class%ath is set u% %ro%erly, the "ollowing "ile can be %laced in any directory=

//3 c',3LibTest.Hava // Yses the library. i#"ort co#.bruceeckel.si#"le.B< "ublic class LibTest @ "ublic static voi! #ain-%tringNO args. @ Wector v ? ne: Wector-.< List l ? ne: List-.< A A ///3>
:hen the co#%iler encounters the import state#ent, it begins searching at the directories s%eci"ied by +D6SSP6T(, looking "or subdirectory co# bbruceeckelbsi#%le, then seeking the co#%iled "iles o" the a%%ro%riate na#es * Vector!class "or Vector and +ist!class "or +ist,. Cote that both the classes and the desired #ethods in Vector and +ist #ust be p*blic. RFSURFSTIJLT+(6PTE5HTIK?U Setting the +D6SSP6T( has been such a trial "or beginning Java users *it was "or #e, when I started, that Sun #ade the J7> in Java K a bit s#arter. /ou ll "ind that, when you install it, even i" you don t set a +D6SSP6T( you ll be able to co#%ile and run basic Java %rogra#s. To co#%ile and run the source'code %ackage "or this book *available on the +7 5)M %ackaged with this book, or at ,,,'0ruceEckel'com,, however, you will need to #ake so#e #odi"ications to your +D6SSP6T( *these are e&%lained in the source'code %ackage,. RFSURFSTIJLT+(6PTE5HTIKHU

Collisions
:hat ha%%ens i" two libraries are i#%orted via B and they include the sa#e na#esO Eor e&a#%le, su%%ose a %rogra# does this=

i#"ort co#.bruceeckel.si#"le.B< i#"ort Hava.util.B<


Since 8ava!*til!K also contains a Vector class, this causes a %otential collision. (owever, as long as you don t write the code that actually

Cha ter 5! .iding the Im lementation

25;

causes the collision, everything is )>9this is good because otherwise you #ight end u% doing a lot o" ty%ing to %revent collisions that would never ha%%en. RFSURFSTIJLT+(6PTE5HTIK3U The collision does occur i" you now try to #ake a Vector=

Wector v ? ne: Wector-.<


:hich Vector class does this re"er toO The co#%iler can t know, and the reader can t know either. So the co#%iler co#%lains and "orces you to be e&%licit. I" I want the standard Java Vector, "or e&a#%le, I #ust say=

Hava.util.Wector v ? ne: Hava.util.Wector-.<


Since this *along with the +D6SSP6T(, co#%letely s%eci"ies the location o" that Vector, there s no need "or the import 8ava!*til!K state#ent unless I # using so#ething else "ro# 8ava!*til. RFSURF STIJLT+(6PTE5HTIKGU

A custom tool librar:


:ith this knowledge, you can now create your own libraries o" tools to reduce or eli#inate du%licate code. +onsider, "or e&a#%le, creating an alias "or )ystem!o*t!printlnA B to reduce ty%ing. This can be %art o" a %ackage called tools=

//3 co#3bruceeckel3tools3P.Hava // The P.rint D P.rintln shorthan!. "ackage co#.bruceeckel.tools< "ublic class P @ "ublic static voi! rint-%tring s. @ %yste#.out."rint-s.< A "ublic static voi! rintln-%tring s. @ %yste#.out."rintln-s.< A A ///3>
/ou can use this shorthand to %rint a )tring either with a newline * #! rintlnA B, or without a newline * #!rintA B,. RFSURF STIJLT+(6PTE5HTIKIU

27=

/ou can guess that the location o" this "ile #ust be in a directory that starts at one o" the +D6SSP6T( locations, then continues com5 br*ceeckel5tools. 6"ter co#%iling, the #!class "ile can be used anywhere on your syste# with an import state#ent=

//3 c',3ToolTest.Hava // Yses the tools library. i#"ort co#.bruceeckel.tools.B< "ublic class ToolTest @ "ublic static voi! #ain-%tringNO args. @ P.rintln-80vailable fro# no: on48.< P.rintln-88 K (''.< // Lorce it to be a %tring P.rintln-88 K (''L.< P.rintln-88 K ).(I(,C.< A A ///3>
Cotice that all ob0ects can easily be "orced into )tring re%resentations by %utting the# in a )tring e&%ression; in the above case, starting the e&%ression with an e#%ty )tring does the trick. But this brings u% an interesting observation. I" you call )ystem!o*t!printlnA>DDB, it works without casting it to a )tring. :ith so#e e&tra overloading, you can get the # class to do this as well *this is an e&ercise at the end o" this cha%ter,. RFSURFSTIJLT+(6PTE5HTIK2U So "ro# now on, whenever you co#e u% with a use"ul new utility, you can add it to the tools directory. *)r to your own %ersonal *til or tools directory., RFSURFSTIJLT+(6PTE5HTIL@U

Csing im.orts to change behavior


6 "eature that is #issing "ro# Java is + s conditional com ilation, which allows you to change a switch and get di""erent behavior without changing any other code. The reason such a "eature was le"t out o" Java is %robably because it is #ost o"ten used in + to solve cross'%lat"or# issues= di""erent %ortions o" the code are co#%iled de%ending on the %lat"or# that the code is being co#%iled "or. Since Java is intended to be auto#atically cross'%lat"or#, such a "eature should not be necessary. RFSURF STIJLT+(6PTE5HTILMU

Cha ter 5! .iding the Im lementation

271

(owever, there are other valuable uses "or conditional co#%ilation. 6 very co##on use is "or debugging code. The debugging "eatures are enabled during develo%#ent, and disabled in the shi%%ing %roduct. 6llen (olub * ,,,'holub'com, ca#e u% with the idea o" using %ackages to #i#ic conditional co#%ilation. (e used this to create a Java version o" + s very use"ul assertion mechanism, whereby you can say !this should be true$ or !this should be "alse$ and i" the state#ent doesn t agree with your assertion you ll "ind out about it. Such a tool is Auite hel%"ul during debugging. RFSURFSTIJLT+(6PTE5HTILKU (ere is the class that you ll use "or debugging=

//3 co#3bruceeckel3tools3!ebug30ssert.Hava // 0ssertion tool for !ebugging. "ackage co#.bruceeckel.tools.!ebug< "ublic class 0ssert @ "rivate static voi! "err-%tring #sg. @ %yste#.err."rintln-#sg.< A "ublic final static voi! isbtrue-boolean e6". @ if-4e6". "err-80ssertion faile!8.< A "ublic final static voi! isbfalse-boolean e6".@ if-e6". "err-80ssertion faile!8.< A "ublic final static voi! isbtrue-boolean e6", %tring #sg. @ if-4e6". "err-80ssertion faile!3 8 K #sg.< A "ublic final static voi! isbfalse-boolean e6", %tring #sg. @ if-e6". "err-80ssertion faile!3 8 K #sg.< A A ///3>
This class si#%ly enca%sulates Boolean tests, which %rint error #essages i" they "ail. In +ha%ter M@, you ll learn about a #ore so%histicated tool "or dealing with errors called e*ce tion handling, but the perrA B #ethod will work "ine in the #eanti#e. RFSURFSTIJLT+(6PTE5HTILLU

272

The out%ut is %rinted to the console standard error strea# by writing to )ystem!err. RFSURFSTIJLT+(6PTE5HTIL?U :hen you want to use this class, you add a line in your %rogra#=

i#"ort co#.bruceeckel.tools.!ebug.B<
To re#ove the assertions so you can shi% the code, a second Assert class is created, but in a di""erent %ackage= RFSURFSTIJLT+(6PTE5HTILHU

//3 co#3bruceeckel3tools30ssert.Hava // Turning off the assertion out"ut // so you can shi" the "rogra#. "ackage co#.bruceeckel.tools< "ublic class 0ssert @ "ublic final static voi! isbtrue-boolean e6".@A "ublic final static voi! isbfalse-boolean e6".@A "ublic final static voi! isbtrue-boolean e6", %tring #sg. @A "ublic final static voi! isbfalse-boolean e6", %tring #sg. @A A ///3>
Cow i" you change the %revious import state#ent to=

i#"ort co#.bruceeckel.tools.B<
The %rogra# will no longer %rint assertions. (ere s an e&a#%le= RFSURF STIJLT+(6PTE5HTIL3U

//3 c',3Test0ssert.Hava // De#onstrating the assertion tool. // Co##ent the follo:ing, an! unco##ent the // subse=uent line to change assertion behavior3 i#"ort co#.bruceeckel.tools.!ebug.B< // i#"ort co#.bruceeckel.tools.B< "ublic class Test0ssert @ "ublic static voi! #ain-%tringNO args. @ 0ssert.isbtrue-- K . ?? ,.< 0ssert.isbfalse--( K (. ?? .< 0ssert.isbtrue-- K . ?? ,, 8 K ?? ,8.<

Cha ter 5! .iding the Im lementation

273

0ssert.isbfalse--( K (. ?? A A ///3>

, 8( K( 4?

8.<

By changing the package that s i#%orted, you change your code "ro# the debug version to the %roduction version. This techniAue can be used "or any kind o" conditional code. RFSURFSTIJLT+(6PTE5HTILGU

ackage caveat
It s worth re#e#bering that anyti#e you create a %ackage, you i#%licitly s%eci"y a directory structure when you give the %ackage a na#e. The %ackage must live in the directory indicated by its na#e, which #ust be a directory that is searchable starting "ro# the +D6SSP6T(. E&%eri#enting with the package keyword can be a bit "rustrating at "irst, because unless you adhere to the %ackage'na#e to directory'%ath rule, you ll get a lot o" #ysterious run'ti#e #essages about not being able to "ind a %articular class, even i" that class is sitting there in the sa#e directory. I" you get a #essage like this, try co##enting out the package state#ent, and i" it runs you ll know where the %roble# lies. RFSURF STIJLT+(6PTE5HTILIU

"ava access s.ecifiers


:hen used, the Java access s%eci"iers p*blic, protecte', and private are %laced in "ront o" each de"inition "or each #e#ber in your class, whether it s a "ield or a #ethod. Each access s%eci"ier controls the access "or only that %articular de"inition. This is a distinct contrast to +<<, in which the access s%eci"ier controls all the de"initions "ollowing it until another access s%eci"ier co#es along. RFSURFSTIJLT+(6PTE5HTIL2U )ne way or another, everything has so#e kind o" access s%eci"ied "or it. In the "ollowing sections, you ll learn all about the various ty%es o" access, starting with the de"ault access. RFSURFSTIJLT+(6PTE5HTI?@U

274

J<riendl:K
:hat i" you give no access s%eci"ier at all, as in all the e&a#%les be"ore this cha%terO The de"ault access has no keyword, but it is co##only re"erred to as !"riendly.$ It #eans that all the other classes in the current %ackage have access to the "riendly #e#ber, but to all the classes outside o" this %ackage the #e#ber a%%ears to be private. Since a co#%ilation unit9a "ile9can belong only to a single %ackage, all the classes within a single co#%ilation unit are auto#atically "riendly with each other. Thus, "riendly ele#ents are also said to have ackage access. RFSURF STIJLT+(6PTE5HTI?MU Eriendly access allows you to grou% related classes together in a %ackage so that they can easily interact with each other. :hen you %ut classes together in a %ackage *thus granting #utual access to their "riendly #e#bers; e.g.i.e., #aking the# !"riends$, you !own$ the code in that %ackage. It #akes sense that only code you own should have "riendly access to other code you own. /ou could say that "riendly access gives a #eaning or a reason "or grou%ing classes together in a %ackage. In #any languages the way you organi1e your de"initions in "iles can be willy'nilly, but in Java you re co#%elled to organi1e the# in a sensible "ashion. In addition, you ll %robably want to e&clude classes that shouldn t have access to the classes being de"ined in the current %ackage. RFSURF STIJLT+(6PTE5HTI?KU The class controls which code has access to its #e#bers. There s no #agic way to !break in.$ +ode "ro# another %ackage can t show u% and say, !(i, I # a "riend o" 2ob s.$ and e&%ect to see the protecte', "riendly, and private #e#bers o" 2ob. The only way to grant access to a #e#ber is to= RFSURFSTIJLT+(6PTE5HTI?LU

*5) *6)

Make the #e#ber p*blic. Then everybody, everywhere, can access it. RFSURFSTIJLT+(6PTE5HTI??U Make the #e#ber "riendly by leaving o"" any access s%eci"ier, and %ut the other classes in the sa#e %ackage. Then the other classes can access the #e#ber. RFSURFSTIJLT+(6PTE5HTI?HU 6s you ll see in +ha%ter 3, when inheritance is introduced, an inherited class can access a protecte' #e#ber as well as a p*blic

+7)

Cha ter 5! .iding the Im lementation

275

#e#ber *but not private #e#bers,. It can access "riendly #e#bers only i" the two classes are in the sa#e %ackage. But don t worry about that now. RFSURFSTIJLT+(6PTE5HTI?3U

+()

Provide !accessorF#utator$ #ethods *also known as !getFset$ #ethods, that read and change the value. This is the #ost civili1ed a%%roach in ter#s o" ))P, and it is "unda#ental to JavaBeans, as you ll see in +ha%ter ML. RFSURFSTIJLT+(6PTE5HTI?GU

ublic: interface access


:hen you use the p*blic keyword, it #eans that the #e#ber declaration that i##ediately "ollows p*blic is available to everyone, in %articular to the client %rogra##er who uses the library. Su%%ose you de"ine a %ackage 'essert containing the "ollowing co#%ilation unit= RFSURF STIJLT+(6PTE5HTI?IU

//3 c',3!essert3Cookie.Hava // Creates a library. "ackage c',.!essert< "ublic class Cookie @ "ublic Cookie-. @ %yste#.out."rintln-8Cookie constructor8.< A voi! bite-. @ %yste#.out."rintln-8bite8.< A A ///3>
5e#e#ber, -ookie!8ava #ust reside in a subdirectory called 'essert, in a directory under cD@ *indicating +ha%ter H o" this book, that #ust be under one o" the +D6SSP6T( directories. 7on t #ake the #istake o" thinking that Java will always look at the current directory as one o" the starting %oints "or searching. I" you don t have a [! as one o" the %aths in your +D6SSP6T(, Java won t look there. RFSURF STIJLT+(6PTE5HTI?2U Cow i" you create a %rogra# that uses -ookie=

//3 c',3Dinner.Hava // Yses the library. i#"ort c',.!essert.B<

277

"ublic class Dinner @ "ublic Dinner-. @ %yste#.out."rintln-8Dinner constructor8.< A "ublic static voi! #ain-%tringNO args. @ Cookie 6 ? ne: Cookie-.< //4 6.bite-.< // Can2t access A A ///3>
you can create a -ookie ob0ect, since its constructor is p*blic and the class is p*blic. *:e ll look #ore at the conce%t o" a p*blic class later., (owever, the biteA B #e#ber is inaccessible inside inner!8ava since biteA B is "riendly only within %ackage 'essert. RFSURF STIJLT+(6PTE5HTIH@U

#he default .ackage


/ou #ight be sur%rised to discover that the "ollowing code co#%iles, even though it would a%%ear that it breaks the rules=

//3 c',3Cake.Hava // 0ccesses a class in a // se"arate co#"ilation unit. class Cake @ "ublic static voi! #ain-%tringNO args. @ Pie 6 ? ne: Pie-.< 6.f-.< A A ///3>
In a second "ile, in the sa#e directory=

//3 c',3Pie.Hava // The other class. class Pie @ voi! f-. @ %yste#.out."rintln-8Pie.f-.8.< A A ///3>

Cha ter 5! .iding the Im lementation

278

/ou #ight initially view these as co#%letely "oreign "iles, and yet -ake is able to create a #ie ob0ect and call its fA B #ethod. *Cote that you #ust have [. in your +D6SSP6T( in order "or the "iles to co#%ile., /ou d ty%ically think that #ie and fA B are "riendly and there"ore not available to -ake. They are "riendly9that %art is correct. The reason that they are available in -ake!8ava is because they are in the sa#e directory and have no e&%licit %ackage na#e. Java treats "iles like this as i#%licitly %art o" the !de"ault %ackage$ "or that directory, and there"ore "riendly to all the other "iles in that directory. RFSURFSTIJLT+(6PTE5HTIHMU

rivate: :ou cant touch that!


The private keyword #eans that no one can access that #e#ber e&ce%t that %articular class, inside #ethods o" that class. )ther classes in the sa#e %ackage cannot access private #e#bers, so it s as i" you re even insulating the class against yoursel". )n the other hand, it s not unlikely that a %ackage #ight be created by several %eo%le collaborating together, so private allows you to "reely change that #e#ber without concern that it will a""ect another class in the sa#e %ackage. RFSURF STIJLT+(6PTE5HTIHKU The de"ault !"riendly$ %ackage access o"ten %rovides an adeAuate a#ount o" hiding; re#e#ber, a !"riendly$ #e#ber is inaccessible to the user o" the %ackage. This is nice, since the de"ault access is the one that you nor#ally use *and the one that you ll get i" you "orget to add any access control,. Thus, you ll ty%ically think about access "or the #e#bers that you e&%licitly want to #ake p*blic "or the client %rogra##er, and as a result, you #ight not initially think you ll use the private keyword o"ten since it s tolerable to get away without it. *This is a distinct contrast with +<<., (owever, it turns out that the consistent use o" private is very i#%ortant, es%ecially where #ultithreading is concerned. *6s you ll see in +ha%ter M?., RFSURFSTIJLT+(6PTE5HTIHLU (ere s an e&a#%le o" the use o" private=

//3 c',3$ceCrea#.Hava // De#onstrates 8"rivate8 key:or!. class %un!ae @

27:

"rivate %un!ae-. @A static %un!ae #ake0%un!ae-. @ return ne: %un!ae-.< A A "ublic class $ceCrea# @ "ublic static voi! #ain-%tringNO args. @ //4 %un!ae 6 ? ne: %un!ae-.< %un!ae 6 ? %un!ae.#ake0%un!ae-.< A A ///3>
This shows an e&a#%le in which private co#es in handy= you #ight want to control how an ob0ect is created and %revent so#eone "ro# directly accessing a %articular constructor *or all o" the#,. In the e&a#%le above, you cannot create a )*n'ae ob0ect via its constructor; instead you #ust call the makeA)*n'aeA B #ethod to do it "or you @. RFSURF STIJLT+(6PTE5HTIH?U 6ny #ethod that you re certain is only a !hel%er$ #ethod "or that class can be #ade private, to ensure that you don t accidentally use it elsewhere in the %ackage and thus %rohibit yoursel" "ro# changing or re#oving the #ethod. Making a #ethod private guarantees that you retain this o%tion. RFSURFSTIJLT+(6PTE5HTIHHU The sa#e is true "or a private "ield inside a class. 4nless you #ust e&%ose the underlying i#%le#entation *which is a #uch rarer situation than you #ight think,, you should #ake all "ields private. (owever, 0ust because a re"erence to an ob0ect is private inside a class doesnVt #ean that so#e other ob0ect canVt have a p*blic re"erence to the sa#e ob0ect. *See 6%%endi& 6 "or issues about aliasing., RFSURF STIJLT+(6PTE5HTIH3U

@ There s another e""ect in this case= Since the de"ault constructor is the only one de"ined, and it s private, it will %revent inheritance o" this class. *6 sub0ect that will be introduced in +ha%ter 3.,

Cha ter 5! .iding the Im lementation

27;

rotected: Jsort of friendl:K


The protecte' access s%eci"ier reAuires a 0u#% ahead to understand. Eirst, you should be aware that you don t need to understand this section to continue through this book u% through inheritance *+ha%ter 3,. But "or co#%leteness, here is a brie" descri%tion and e&a#%le using protecte'. RFSURFSTIJLT+(6PTE5HTIHGU The protecte' keyword deals with a conce%t called inheritance, which takes an e&isting class and adds new #e#bers to that class without touching the e&isting class, which we re"er to as the base class. /ou can also change the behavior o" e&isting #e#bers o" the class. To inherit "ro# an e&isting class, you say that your new class e4ten's an e&isting class, like this=

class Loo e6ten!s Bar @


The rest o" the class de"inition looks the sa#e. RFSURF STIJLT+(6PTE5HTIHIU I" you create a new %ackage and you inherit "ro# a class in another %ackage, the only #e#bers you have access to are the p*blic #e#bers o" the original %ackage. *)" course, i" you %er"or# the inheritance in the same %ackage, you have the nor#al %ackage access to all the !"riendly$ #e#bers., So#eti#es the creator o" the base class would like to take a %articular #e#ber and grant access to derived classes but not the world in general. That s what protecte' does. I" you re"er back to the "ile -ookie!8ava, the "ollowing class cannot access the !"riendly$ #e#ber=

//3 c',3ChocolateChi".Hava // Can2t access frien!ly #e#ber // in another class. i#"ort c',.!essert.B< "ublic class ChocolateChi" e6ten!s Cookie @ "ublic ChocolateChi"-. @ %yste#.out."rintln8ChocolateChi" constructor8.< A "ublic static voi! #ain-%tringNO args. @ ChocolateChi" 6 ? ne: ChocolateChi"-.<

28=

//4 6.bite-.< // Can2t access bite A A ///3>


)ne o" the interesting things about inheritance is that i" a #ethod biteA B e&ists in class -ookie, then it also e&ists in any class inherited "ro# -ookie. But since biteA B is !"riendly$ in a "oreign %ackage, it s unavailable to us in this one. )" course, you could #ake it p*blic, but then everyone would have access and #aybe that s not what you want. I" we change the class -ookie as "ollows=

"ublic class Cookie @ "ublic Cookie-. @ %yste#.out."rintln-8Cookie constructor8.< A "rotecte! voi! bite-. @ %yste#.out."rintln-8bite8.< A A
then biteA B still has !"riendly$ access within %ackage 'essert, but it is also accessible to anyone inheriting "ro# -ookie. (owever, it is not p*blic.

protecte' also gives %ackage access Y that is, other classes in the sa#e %ackage #ay access protecte'RFSURFSTIJLT+(6PTE5HTIH2U ele#ents.

Interface and im.lementation


6ccess control is o"ten re"erred to as im lementation hiding. :ra%%ing data and #ethods within classes in co#bination with i#%le#entation hiding is o"ten called enca sulation@. The result is a data ty%e with characteristics and behaviors. RFSURFSTIJLT+(6PTE5HTI3@U

@ (owever, %eo%le o"ten re"er to i#%le#entation hiding alone as enca%sulation.

Cha ter 5! .iding the Im lementation

281

6ccess control %uts boundaries within a data ty%e "or two i#%ortant reasons. The "irst is to establish what the client %rogra##ers can and can t use. /ou can build your internal #echanis#s into the structure without worrying that the client %rogra##ers will accidentally treat the internals as %art o" the inter"ace that they should be using. RFSURF STIJLT+(6PTE5HTI3MU This "eeds directly into the second reason, which is to se%arate the inter"ace "ro# the i#%le#entation. I" the structure is used in a set o" %rogra#s, but client %rogra##ers can t do anything but send #essages to the p*blic inter"ace, then you can change anything that s not p*blic *e.g., !"riendly,$ protecte', or private, without reAuiring #odi"ications to client code. RFSURFSTIJLT+(6PTE5HTI3KU :e re now in the world o" ob0ect'oriented %rogra##ing, where a class is actually describing !a class o" ob0ects,$ as you would describe a class o" "ishes or a class o" birds. 6ny ob0ect belonging to this class will share these characteristics and behaviors. The class is a descri%tion o" the way all ob0ects o" this ty%e will look and act. RFSURFSTIJLT+(6PTE5HTI3LU In the original ))P language, Si#ula'3G, the keyword class was used to describe a new data ty%e. The sa#e keyword has been used "or #ost ob0ect'oriented languages. This is the "ocal %oint o" the whole language= the creation o" new data ty%es that are #ore than 0ust bo&es containing data and #ethods. RFSURFSTIJLT+(6PTE5HTI3?U The class is the "unda#ental ))P conce%t in Java. It is one o" the keywords that will not be set in bold in this book9it beco#es annoying with a word re%eated as o"ten as !class.$ RFSURF STIJLT+(6PTE5HTI3HU Eor clarity, you #ight %re"er a style o" creating classes that %uts the

p*blic #e#bers at the beginning, "ollowed by the protecte', "riendly, and private #e#bers. The advantage is that the user o" the class can
then read down "ro# the to% and see "irst what s i#%ortant to the# *the p*blic #e#bers, because they can be accessed outside the "ile,, and sto% reading when they encounter the non' p*blic #e#bers, which are %art o" the internal i#%le#entation=

"ublic class 9 @

282

"ublic voi! "ub(- . "ublic voi! "ub - . "ublic voi! "ub)- . "rivate voi! "riv("rivate voi! "riv "rivate voi! "riv)"rivate int i< // . . . A

@ @ @ . . .

/B . /B . /B . @ /B @ /B @ /B

. . . . . .

. . . . . .

B/ A B/ A B/ A . B/ A . B/ A . B/ A

This will #ake it only %artially easier to read because the inter"ace and i#%le#entation are still #i&ed together. That is, you still see the source code9the i#%le#entation9because it s right there in the class. In addition, the co##ent docu#entation su%%orted by 0avadoc *described in +ha%ter K, lessens the i#%ortance o" code readability by the client %rogra##er. 7is%laying the inter"ace to the consu#er o" a class is really the 0ob o" the class bro,ser, a tool whose 0ob is to look at all the available classes and show you what you can do with the# *i.e., what #e#bers are available, in a use"ul "ashion. By the ti#e you read this, browsers should be an e&%ected %art o" any good Java develo%#ent tool. RFSURF STIJLT+(6PTE5HTI33U

Class access
In Java, the access s%eci"iers can also be used to deter#ine which classes ,ithin a library will be available to the users o" that library. I" you want a class to be available to a client %rogra##er, you %lace the p*blic keyword so#ewhere be"ore the o%ening brace o" the class body. This controls whether the client %rogra##er can even create an ob0ect o" the class. RFSURFSTIJLT+(6PTE5HTI3GU To control the access o" a class, the s%eci"ier #ust a%%ear be"ore the keyword class. Thus you can say=

"ublic class \i!get @


Cow i" the na#e o" your library is mylib any client %rogra##er can access 0i'get by saying

i#"ort #ylib.\i!get<

Cha ter 5! .iding the Im lementation

283

or

i#"ort #ylib.B<
(owever, there s an e&tra set o" constraints= RFSURF STIJLT+(6PTE5HTI3IU

+!)

There can be only one p*blic class %er co#%ilation unit *"ile,. The idea is that each co#%ilation unit has a single %ublic inter"ace re%resented by that p*blic class. It can have as #any su%%orting !"riendly$ classes as you want. I" you have #ore than one p*blic class inside a co#%ilation unit, the co#%iler will give you an error #essage. RFSURFSTIJLT+(6PTE5HTI32U The na#e o" the p*blic class #ust e&actly #atch the na#e o" the "ile containing the co#%ilation unit, including ca%itali1ation. So "or 0i'get, the na#e o" the "ile #ust be 0i'get!8ava, not (i'get! 8ava or 0I "&T!8ava. 6gain, you ll get a co#%ile'ti#e error i" they don t agree. RFSURFSTIJLT+(6PTE5HTIG@U It is %ossible, though not ty%ical, to have a co#%ilation unit with no p*blic class at all. In this case, you can na#e the "ile whatever you like. RFSURFSTIJLT+(6PTE5HTIGMU

+*)

++)

:hat i" you ve got a class inside mylib that you re 0ust using to acco#%lish the tasks %er"or#ed by 0i'get or so#e other p*blic class in mylibO /ou don t want to go to the bother o" creating docu#entation "or the client %rogra##er, and you think that so#eti#e later you #ight want to co#%letely change things and ri% out your class altogether, substituting a di""erent one. To give you this "le&ibility, you need to ensure that no client %rogra##ers beco#e de%endent on your %articular i#%le#entation details hidden inside mylib. To acco#%lish this, you 0ust leave the p*blic keyword o"" the class, in which case it beco#es "riendly. *That class can be used only within that %ackage., RFSURF STIJLT+(6PTE5HTIGKU Cote that a class cannot be private *that would #ake it accessible to no one but the class,, or protecte'@. So you have only two choices "or class access= !"riendly$ or p*blic. I" you don t want anyone else to have access
@ 6ctually, an inner class can be %rivate or %rotected, but that s a s%ecial case. These will be introduced in +ha%ter G.

284

to that class, you can #ake all the constructors private, thereby %reventing anyone but you, inside a static #e#ber o" the class, "ro# creating an ob0ect o" that class @. (ere s an e&a#%le=

//3 c',3Lunch.Hava // De#onstrates class access s"ecifiers. // Jake a class effectively "rivate // :ith "rivate constructors3 class %ou" @ "rivate %ou"-. @A // -(. 0llo: creation via static #etho!3 "ublic static %ou" #ake%ou"-. @ return ne: %ou"-.< A // - . Create a static obHect an! // return a reference u"on re=uest. // -The 8%ingleton8 "attern.3 "rivate static %ou" "s( ? ne: %ou"-.< "ublic static %ou" access-. @ return "s(< A "ublic voi! f-. @A A class %an!:ich @ // Yses Lunch voi! f-. @ ne: Lunch-.< A A // Gnly one "ublic class allo:e! "er file3 "ublic class Lunch @ voi! test-. @ // Can2t !o this4 Private constructor3 //4 %ou" "riv( ? ne: %ou"-.< %ou" "riv ? %ou".#ake%ou"-.< %an!:ich f( ? ne: %an!:ich-.< %ou".access-..f-.< A A ///3>
@ /ou can also do it by inheriting *+ha%ter 3, "ro# that class.

Cha ter 5! .iding the Im lementation

285

4% to now, #ost o" the #ethods have been returning either voi' or a %ri#itive ty%e, so the de"inition=

"ublic static %ou" access-. @ return "s(< A


#ight look a little con"using at "irst. The word be"ore the #ethod na#e * access, tells what the #ethod returns. So "ar this has #ost o"ten been voi', which #eans it returns nothing. But you can also return a re"erence to an ob0ect, which is what ha%%ens here. This #ethod returns a re"erence to an ob0ect o" class )o*p. RFSURFSTIJLT+(6PTE5HTIGLU The class )o*p shows how to %revent direct creation o" a class by #aking all the constructors private. 5e#e#ber that i" you don t e&%licitly create at least one constructor, the de"ault constructor *a constructor with no argu#ents, will be created "or you. By writing the de"ault constructor, it won t be created auto#atically. By #aking it private, no one can create an ob0ect o" that class. But now how does anyone use this classO The above e&a#%le shows two o%tions. Eirst, a static #ethod is created that creates a new )o*p and returns a re"erence to it. This could be use"ul i" you want to do so#e e&tra o%erations on the )o*p be"ore returning it, or i" you want to kee% count o" how #any )o*p ob0ects to create *%erha%s to restrict their %o%ulation,. RFSURF STIJLT+(6PTE5HTIG?U The second o%tion uses what s called a design attern, which is covered in Thinking in Patterns ,ith Java, downloadable at ,,,'0ruceEckel' com. This %articular %attern is called a !singleton$ because it allows only a single ob0ect to ever be created. The ob0ect o" class )o*p is created as a static private #e#ber o" )o*p, so there s one and only one, and you can t get at it e&ce%t through the p*blic #ethod accessA B. RFSURF STIJLT+(6PTE5HTIGHU 6s %reviously #entioned, i" you don t %ut an access s%eci"ier "or class access it de"aults to !"riendly.$ This #eans that an ob0ect o" that class can be created by any other class in the %ackage, but not outside the %ackage. *5e#e#ber, all the "iles within the sa#e directory that don t have e&%licit package declarations are i#%licitly %art o" the de"ault %ackage "or that directory., (owever, i" a static #e#ber o" that class is p*blic, the client

287

%rogra##er can still access that static #e#ber even though they cannot create an ob0ect o" that class. RFSURFSTIJLT+(6PTE5HTIG3U

1ummar:
In any relationshi% it s i#%ortant to have boundaries that are res%ected by all %arties involved. :hen you create a library, you establish a relationshi% with the user o" that library9the client %rogra##er9who is another %rogra##er, but one %utting together an a%%lication or using your library to build a bigger library. RFSURFSTIJLT+(6PTE5HTIGGU :ithout rules, client %rogra##ers can do anything they want with all the #e#bers o" a class, even i" you #ight %re"er they don t directly #ani%ulate so#e o" the #e#bers. Everything s naked to the world. RF SURFSTIJLT+(6PTE5HTIGIU This cha%ter looked at how classes are built to "or# libraries; "irst, the way a grou% o" classes is %ackaged within a library, and second, the way the class controls access to its #e#bers. RFSURF STIJLT+(6PTE5HTIG2U It is esti#ated that a + %rogra##ing %ro0ect begins to break down so#ewhere between H@> and M@@> lines o" code because + has a single !na#e s%ace$ so na#es begin to collide, causing an e&tra #anage#ent overhead. In Java, the package keyword, the %ackage na#ing sche#e, and the import keyword give you co#%lete control over na#es, so the issue o" na#e collision is easily avoided. RFSURF STIJLT+(6PTE5HTII@U There are two reasons "or controlling access to #e#bers. The "irst is to kee% users hands o"" tools that they shouldn t touch; tools that are necessary "or the internal #achinations o" the data ty%e, but not %art o" the inter"ace that users need to solve their %articular %roble#s. So #aking #ethods and "ields private is a service to users because they can easily see what s i#%ortant to the# and what they can ignore. It si#%li"ies their understanding o" the class. RFSURF STIJLT+(6PTE5HTIIMU

Cha ter 5! .iding the Im lementation

288

The second and #ost i#%ortant reason "or access control is to allow the library designer to change the internal workings o" the class without worrying about how it will a""ect the client %rogra##er. /ou #ight build a class one way at "irst, and then discover that restructuring your code will %rovide #uch greater s%eed. I" the inter"ace and i#%le#entation are clearly se%arated and %rotected, you can acco#%lish this without "orcing the user to rewrite their code. RFSURFSTIJLT+(6PTE5HTIIKU 6ccess s%eci"iers in Java give valuable control to the creator o" a class. The users o" the class can clearly see e&actly what they can use and what to ignore. More i#%ortant, though, is the ability to ensure that no user beco#es de%endent on any %art o" the underlying i#%le#entation o" a class. I" you know this as the creator o" the class, you can change the underlying i#%le#entation with the knowledge that no client %rogra##er will be a""ected by the changes because they can t access that %art o" the class. RFSURFSTIJLT+(6PTE5HTIILU :hen you have the ability to change the underlying i#%le#entation, you can not only i#%rove your design later, but you also have the "reedo# to #ake #istakes. Co #atter how care"ully you %lan and design you ll #ake #istakes. >nowing that it s relatively sa"e to #ake these #istakes #eans you ll be #ore e&%eri#ental, you ll learn "aster, and you ll "inish your %ro0ect sooner. RFSURFSTIJLT+(6PTE5HTII?U The %ublic inter"ace to a class is what the user does see, so that is the #ost i#%ortant %art o" the class to get !right$ during analysis and design. Even that allows you so#e leeway "or change. I" you don t get the inter"ace right the "irst ti#e, you can add #ore #ethods, as long as you don t re#ove any that client %rogra##ers have already used in their code. RFSURFSTIJLT+(6PTE5HTIIHU

/0ercises
Solutions to selected e&ercises can be "ound in the electronic docu#entThe Thinking in Java "nnotated Solution @uide, available "or a s#all "ee "ro# ,,,'0ruceEckel'com.

+,) :rite a %rogra# that creates an Array+ist ob0ect without


e&%licitly i#%orting 8ava!*til!K. RFSURF STIJLT+(6PTE5HTII3U

28:

+-) In the section labeled !%ackage= the library unit,$ turn the code
"rag#ents concerning mypackage into a co#%iling and running set o" Java "iles. RFSURFSTIJLT+(6PTE5HTIIGU

+4) In the section labeled !+ollisions,$ take the code "rag#ents and
turn the# into a %rogra#, and veri"y that collisions do in "act occur. RFSURFSTIJLT+(6PTE5HTIIIU

+5) 8enerali1e the class # de"ined in this cha%ter by adding all the
overloaded versions o" rintA B and rintlnA B necessary to handle all the di""erent basic Java ty%es. RFSURF STIJLT+(6PTE5HTII2U

+6) +hange the i#%ort state#ent in TestAssert!8ava to enable and


disable the assertion #echanis#. RFSURF STIJLT+(6PTE5HTI2@U

,7) +reate a class with p*blic, private, protecte', and !"riendly$


data #e#bers and #ethod #e#bers. +reate an ob0ect o" this class and see what kind o" co#%iler #essages you get when you try to access all the class #e#bers. Be aware that classes in the sa#e directory are %art o" the !de"ault$ %ackage. RFSURF STIJLT+(6PTE5HTI2MU

,() +reate a class with protecte' data. +reate a second class in the
sa#e "ile with a #ethod that #ani%ulates the protecte' data in the "irst class. RFSURFSTIJLT+(6PTE5HTI2KU

,!) +hange the class -ookie as s%eci"ied in the section labeled


! protecte'= [sort o" "riendly. $ Veri"y that biteA B is not p*blic. RFSURFSTIJLT+(6PTE5HTI2LU

,*) In the section titled !+lass access$ you ll "ind code "rag#ents
describing mylib and 0i'get. +reate this library, then create a 0i'get in a class that is not %art o" the mylib %ackage. RFSURF STIJLT+(6PTE5HTI2?U

,+) +reate a new directory and edit your +D6SSP6T( to include that
new directory. +o%y the #!class "ile *%roduced by co#%iling com!br*ceeckel!tools!#!8ava, to your new directory and then change the na#es o" the "ile, the # class inside and the #ethod

Cha ter 5! .iding the Im lementation

28;

na#es. */ou #ight also want to add additional out%ut to watch how it works., +reate another %rogra# in a di""erent directory that uses your new class. RFSURFSTIJLT+(6PTE5HTI2HU

,,) Eollowing the "or# o" the e&a#%le +*nch!8ava, create a class
called -onnection1anager that #anages a "i&ed array o" -onnection ob0ects. The client %rogra##er #ust not be able to e&%licitly create -onnection ob0ects, but can only get the# via a static #ethod in -onnection1anager. :hen the -onnection1anager runs out o" ob0ects, it returns a n*ll re"erence. Test the classes in mainA B. RFSURF STIJLT+(6PTE5HTI23U

,-) +reate the "ollowing "ile in the c@HFlocal directory *%resu#ably in


your +D6SSP6T(,=

///3 c',3local3Package!Class.Hava "ackage c',.local< class Package!Class @ "ublic Package!Class-. @ %yste#.out."rintln8Creating a "ackage! class8.< A A ///3>
Then create the "ollowing "ile in a directory other than c@H=

///3 c',3foreign3Loreign.Hava "ackage c',.foreign< i#"ort c',.local.B< "ublic class Loreign @ "ublic static voi! #ain -%tringNO args. @ Package!Class "c ? ne: Package!Class-.< A A ///3>
E&%lain why the co#%iler generates an error. :ould #aking the Foreign class %art o" the cD@!local %ackage change anythingO RF SU

2:=

-: $eusing Classes
RFSTIJLT+(6PTE53TI@U)ne o" the #ost co#%elling "eatures about Java is code reuse. But to be revolutionary, you ve got to be able to do a lot #ore than co%y code and change it.
That s the a%%roach used in %rocedural languages like +, and it hasn t worked very well. Dike everything in Java, the solution revolves around the class. /ou reuse code by creating new classes, but instead o" creating the# "ro# scratch, you use e&isting classes that so#eone has already built and debugged. RFSURFSTIJLT+(6PTE53TIMU The trick is to use the classes without soiling the e&isting code. In this cha%ter you ll see two ways to acco#%lish this. The "irst is Auite straight"orward= /ou si#%ly create ob0ects o" your e&isting class inside the new class. This is called com ositionD because the new class is co#%osed o" ob0ects o" e&isting classes. /ou re si#%ly reusing the "unctionality o" the code, not its "or#. RFSURFSTIJLT+(6PTE53TIKU The second a%%roach is #ore subtle. It creates a new class as a t) e o$ an e&isting class. /ou literally take the "or# o" the e&isting class and add code to it without #odi"ying the e&isting class. This #agical act is called inheritance, and the co#%iler does #ost o" the work. Inheritance is one o" the cornerstones o" ob0ect'oriented %rogra##ing, and has additional i#%lications that will be e&%lored in +ha%ter G. RFSURF STIJLT+(6PTE53TILU It turns out that #uch o" the synta& and behavior are si#ilar "or both co#%osition and inheritance *which #akes sense because they are both ways o" #aking new ty%es "ro# e&isting ty%es,. In this cha%ter, you ll learn about these code reuse #echanis#s. RFSURF STIJLT+(6PTE53TI?U

2:1

Com.osition s:nta0
4ntil now, co#%osition has been used Auite "reAuently. /ou si#%ly %lace ob0ect re"erences inside new classes. Eor e&a#%le, su%%ose you d like an ob0ect that holds several )tring ob0ects, a cou%le o" %ri#itives, and an ob0ect o" another class. Eor the non%ri#itive ob0ects, you %ut re"erences inside your new class, but you de"ine the %ri#itives directly=

//3 c'+3%"rinkler%yste#.Hava // Co#"osition for co!e reuse. class \ater%ource @ "rivate %tring s< \ater%ource-. @ %yste#.out."rintln-8\ater%ource-.8.< s ? ne: %tring-8Constructe!8.< A "ublic %tring to%tring-. @ return s< A A "ublic class %"rinkler%yste# @ "rivate %tring valve(, valve , valve), valveI< \ater%ource source< int i< float f< voi! "rint-. @ %yste#.out."rintln-8valve( ? 8 K valve(.< %yste#.out."rintln-8valve ? 8 K valve .< %yste#.out."rintln-8valve) ? 8 K valve).< %yste#.out."rintln-8valveI ? 8 K valveI.< %yste#.out."rintln-8i ? 8 K i.< %yste#.out."rintln-8f ? 8 K f.< %yste#.out."rintln-8source ? 8 K source.< A "ublic static voi! #ain-%tringNO args. @ %"rinkler%yste# 6 ? ne: %"rinkler%yste#-.< 6."rint-.< A A ///3>

2:2

Thinking in Java

,,,'0ruceEckel'com

)ne o" the #ethods de"ined in 0ater)o*rce is s%ecial= to)tringA B. /ou will learn later that every non%ri#itive ob0ect has a to)tringA B #ethod, and it s called in s%ecial situations when the co#%iler wants a )tring but it s got one o" these ob0ects. So in the e&%ression=

%yste#.out."rintln-8source ? 8 K source.<
the co#%iler sees you trying to add a )tring ob0ect *c so*rce P c, to a 0ater)o*rce. This doesn t #ake sense to it, because you can only !add$ a )tring to another )tring, so it says !I ll turn so*rce into a )tring by calling to)tringA B.$ 6"ter doing this it can co#bine the two )trings and %ass the resulting )tring to )ystem!o*t!printlnA B. 6ny ti#e you want to allow this behavior with a class you create you need only write a to)tringA B #ethod. RFSURFSTIJLT+(6PTE53TIHU 6t "irst glance, you #ight assu#e9Java being as sa"e and care"ul as it is9 that the co#%iler would auto#atically construct ob0ects "or each o" the re"erences in the above code; "or e&a#%le, calling the de"ault constructor "or 0ater)o*rce to initiali1e so*rce. The out%ut o" the %rint state#ent is in "act=

valve( ? valve ? valve) ? valveI ? i ? ' f ? '.' source ?

null null null null null

Pri#itives that are "ields in a class are auto#atically initiali1ed to 1ero, as noted in +ha%ter K. But the ob0ect re"erences are initiali1ed to n*ll, and i" you try to call #ethods "or any o" the# you ll get an e&ce%tion. It s actually %retty good *and use"ul, that you can still %rint the# out without throwing an e&ce%tion. RFSURFSTIJLT+(6PTE53TI3U It #akes sense that the co#%iler doesn t 0ust create a de"ault ob0ect "or every re"erence because that would incur unnecessary overhead in #any cases. I" you want the re"erences initiali1ed, you can do it= RFSURF STIJLT+(6PTE53TIGU

2:3

+,)

6t the %oint the ob0ects are de"ined. This #eans that they ll always be initiali1ed be"ore the constructor is called. RFSURF STIJLT+(6PTE53TIIU In the constructor "or that class. RFSURFSTIJLT+(6PTE53TI2U 5ight be"ore you actually need to use the ob0ect. This is o"ten called la?) initiali?ation. It can reduce overhead in situations where the ob0ect doesn t need to be created every ti#e. RFSURF STIJLT+(6PTE53TIM@U

+-) +4)

6ll three a%%roaches are shown here= RFSURFSTIJLT+(6PTE53TIMMU

//3 c'+3Bath.Hava // Constructor initialiUation :ith co#"osition. class %oa" @ "rivate %tring s< %oa"-. @ %yste#.out."rintln-8%oa"-.8.< s ? ne: %tring-8Constructe!8.< A "ublic %tring to%tring-. @ return s< A A "ublic class Bath @ "rivate %tring // $nitialiUing at "oint of !efinition3 s( ? ne: %tring-8Ma""y8., s ? 8Ma""y8, s), sI< %oa" castille< int i< float toy< Bath-. @ %yste#.out."rintln-8$nsi!e Bath-.8.< s) ? ne: %tring-8Joy8.< i ? I*< toy ? ).(If< castille ? ne: %oa"-.< A

2:4

Thinking in Java

,,,'0ruceEckel'com

voi! "rint-. @ // Delaye! initialiUation3 if-sI ?? null. sI ? ne: %tring-8Joy8.< %yste#.out."rintln-8s( ? 8 K s(.< %yste#.out."rintln-8s ? 8 K s .< %yste#.out."rintln-8s) ? 8 K s).< %yste#.out."rintln-8sI ? 8 K sI.< %yste#.out."rintln-8i ? 8 K i.< %yste#.out."rintln-8toy ? 8 K toy.< %yste#.out."rintln-8castille ? 8 K castille.< A "ublic static voi! #ain-%tringNO args. @ Bath b ? ne: Bath-.< b."rint-.< A A ///3>
Cote that in the 2ath constructor a state#ent is e&ecuted be"ore any o" the initiali1ations take %lace. :hen you don t initiali1e at the %oint o" de"inition, there s still no guarantee that you ll %er"or# any initiali1ation be"ore you send a #essage to an ob0ect re"erence9e&ce%t "or the inevitable run'ti#e e&ce%tion. RFSURFSTIJLT+(6PTE53TIMKU (ere s the out%ut "or the %rogra#=

$nsi!e Bath-. %oa"-. s( ? Ma""y s ? Ma""y s) ? Joy sI ? Joy i ? I* toy ? ).(I castille ? Constructe!
:hen printA B is called it "ills in sQ so that all the "ields are %ro%erly initiali1ed by the ti#e they are used. RFSURFSTIJLT+(6PTE53TIMLU

2:5

Inheritance s:nta0
Inheritance is an integral %art o" Java *and ))P languages in general,. It turns out that you re always doing inheritance when you create a class, because unless you e&%licitly inherit "ro# so#e other class, you i#%licitly inherit "ro# Java s standard root class .b8ect. RFSURF STIJLT+(6PTE53TIM?U The synta& "or co#%osition is obvious, but to %er"or# inheritance there s a distinctly di""erent "or#. :hen you inherit, you say !This new class is like that old class.$ /ou state this in code by giving the na#e o" the class as usual, but be"ore the o%ening brace o" the class body, %ut the keyword e4ten's "ollowed by the na#e o" the base class. :hen you do this, you auto#atically get all the data #e#bers and #ethods in the base class. (ere s an e&a#%le= RFSURFSTIJLT+(6PTE53TIMHU

//3 c'+3Detergent.Hava // $nheritance synta6 D "ro"erties. class Cleanser @ "rivate %tring s ? ne: %tring-8Cleanser8.< "ublic voi! a""en!-%tring a. @ s K? a< A "ublic voi! !ilute-. @ a""en!-8 !ilute-.8.< A "ublic voi! a""ly-. @ a""en!-8 a""ly-.8.< A "ublic voi! scrub-. @ a""en!-8 scrub-.8.< A "ublic voi! "rint-. @ %yste#.out."rintln-s.< A "ublic static voi! #ain-%tringNO args. @ Cleanser 6 ? ne: Cleanser-.< 6.!ilute-.< 6.a""ly-.< 6.scrub-.< 6."rint-.< A A "ublic class Detergent e6ten!s Cleanser @ // Change a #etho!3 "ublic voi! scrub-. @ a""en!-8 Detergent.scrub-.8.< su"er.scrub-.< // Call base-class version A // 0!! #etho!s to the interface3

2:7

Thinking in Java

,,,'0ruceEckel'com

"ublic voi! foa#-. @ a""en!-8 foa#-.8.< A // Test the ne: class3 "ublic static voi! #ain-%tringNO args. @ Detergent 6 ? ne: Detergent-.< 6.!ilute-.< 6.a""ly-.< 6.scrub-.< 6.foa#-.< 6."rint-.< %yste#.out."rintln-8Testing base class38.< Cleanser.#ain-args.< A A ///3>
This de#onstrates a nu#ber o" "eatures. Eirst, in the -leanser appen' A B #ethod, )trings are concatenated to s using the LP o%erator, which is one o" the o%erators *along with [L , that the Java designers !overloaded$ to work with )trings. RFSURFSTIJLT+(6PTE53TIM3U Second, both -leanser and etergent contain a mainA B #ethod. /ou can create a mainA B "or each one o" your classes, and it s o"ten reco##ended to code this way so that your test code is wra%%ed in with the class. Even i" you have a lot o" classes in a %rogra#, only the mainA B "or the class invoked on the co##and line will be called. *6s long as mainA B is p*blic, it doesn t #atter whether the class that it s %art o" is p*blic., So in this case, when you say 8ava etergent, etergent! mainA B will be called. But you can also say 8ava -leanser to invoke -leanser!mainA B, even though -leanser is not a p*blic class. This techniAue o" %utting a mainA B in each class allows easy unit testing "or each class. 6nd you don t need to re#ove the mainA B when you re "inished testing; you can leave it in "or later testing. RFSURF STIJLT+(6PTE53TIMGU (ere, you can see that etergent!mainA B calls -leanser!mainA B e&%licitly, %assing it the sa#e argu#ents "ro# the co##and line *however, you could %ass it any )tring array,. RFSURF STIJLT+(6PTE53TIMIU It s i#%ortant that all o" the #ethods in -leanser are p*blic. 5e#e#ber that i" you leave o"" any access s%eci"ier the #e#ber de"aults

2:8

to !"riendly,$ which allows access only to %ackage #e#bers. Thus, ,ithin this ackage, anyone could use those #ethods i" there were no access s%eci"ier. etergent would have no trouble, "or e&a#%le. (owever, i" a class "ro# so#e other %ackage were to inherit "ro# -leanser it could access only p*blic #e#bers. So to %lan "or inheritance, as a general rule #ake all "ields private and all #ethods p*blic. * protecte' #e#bers also allow access by derived classes; you ll learn about this later., )" course, in %articular cases you #ust #ake ad0ust#ents, but this is a use"ul guideline. RFSURFSTIJLT+(6PTE53TIM2U Cote that -leanser has a set o" #ethods in its inter"ace= appen'A B, 'il*teA B, applyA B, scr*bA B, and printA B. Because etergent is derived $rom -leanser *via the e4ten's keyword, it auto#atically gets all these #ethods in its inter"ace, even though you don t see the# all e&%licitly de"ined in etergent. /ou can think o" inheritance, then, as reusing the inter$ace' *The i#%le#entation also co#es with it, but that %art isn t the %ri#ary %oint., RFSURFSTIJLT+(6PTE53TIK@U 6s seen in scr*bA B, it s %ossible to take a #ethod that s been de"ined in the base class and #odi"y it. In this case, you #ight want to call the #ethod "ro# the base class inside the new version. But inside scr*bA B you cannot si#%ly call scr*bA B, since that would %roduce a recursive call, which isn t what you want. To solve this %roble# Java has the keyword s*per that re"ers to the !su%erclass$ that the current class has been inherited "ro#. Thus the e&%ression s*per!scr*bA B calls the base' class version o" the #ethod scr*bA B. RFSURFSTIJLT+(6PTE53TIKMU :hen inheriting you re not restricted to using the #ethods o" the base class. /ou can also add new #ethods to the derived class e&actly the way you %ut any #ethod in a class= 0ust de"ine it. The #ethod foamA B is an e&a#%le o" this. RFSURFSTIJLT+(6PTE53TIKKU In etergent!mainA B you can see that "or a etergent ob0ect you can call all the #ethods that are available in -leanser as well as in etergent *i.e., foamA B,. RFSURFSTIJLT+(6PTE53TIKLU

2::

Thinking in Java

,,,'0ruceEckel'com

Initiali?ing the base class


Since there are now two classes involved9the base class and the derived class9instead o" 0ust one, it can be a bit con"using to try to i#agine the resulting ob0ect %roduced by a derived class. Ero# the outside, it looks like the new class has the sa#e inter"ace as the base class and #aybe so#e additional #ethods and "ields. But inheritance doesn t 0ust co%y the inter"ace o" the base class. :hen you create an ob0ect o" the derived class, it contains within it a subob>ect o" the base class. This subob0ect is the sa#e as i" you had created an ob0ect o" the base class by itsel". It s 0ust that, "ro# the outside, the subob0ect o" the base class is wra%%ed within the derived'class ob0ect. RFSURFSTIJLT+(6PTE53TIK?U )" course, it s essential that the base'class subob0ect be initiali1ed correctly and there s only one way to guarantee that= %er"or# the initiali1ation in the constructor, by calling the base'class constructor, which has all the a%%ro%riate knowledge and %rivileges to %er"or# the base'class initiali1ation. Java auto#atically inserts calls to the base'class constructor in the derived'class constructor. The "ollowing e&a#%le shows this working with three levels o" inheritance=

//3 c'+3Cartoon.Hava // Constructor calls !uring inheritance. class 0rt @ 0rt-. @ %yste#.out."rintln-80rt constructor8.< A A class Dra:ing e6ten!s 0rt @ Dra:ing-. @ %yste#.out."rintln-8Dra:ing constructor8.< A A "ublic class Cartoon e6ten!s Dra:ing @ Cartoon-. @ %yste#.out."rintln-8Cartoon constructor8.< A

2:;

"ublic static voi! #ain-%tringNO args. @ Cartoon 6 ? ne: Cartoon-.< A A ///3>


The out%ut "or this %rogra# shows the auto#atic calls=

0rt constructor Dra:ing constructor Cartoon constructor


/ou can see that the construction ha%%ens "ro# the base !outward,$ so the base class is initiali1ed be"ore the derived'class constructors can access it. RFSURFSTIJLT+(6PTE53TIKHU Even i" you don t create a constructor "or -artoonA B, the co#%iler will synthesi1e a de"ault constructor "or you that calls the base class constructor. RFSURFSTIJLT+(6PTE53TIK3U

Constructors with arguments


The above e&a#%le has de"ault constructors; that is, they don t have any argu#ents. It s easy "or the co#%iler to call these because there s no Auestion about what argu#ents to %ass. I" your class doesn t have de"ault argu#ents, or i" you want to call a base'class constructor that has an argu#ent, you #ust e&%licitly write the calls to the base'class constructor using the s*per keyword and the a%%ro%riate argu#ent list=

//3 c'+3Chess.Hava // $nheritance, constructors an! argu#ents. class aa#e @ aa#e-int i. @ %yste#.out."rintln-8aa#e constructor8.< A A class Boar!aa#e e6ten!s aa#e @ Boar!aa#e-int i. @ su"er-i.< %yste#.out."rintln-8Boar!aa#e constructor8.< A

2;=

Thinking in Java

,,,'0ruceEckel'com

A "ublic class Chess e6ten!s Boar!aa#e @ Chess-. @ su"er-((.< %yste#.out."rintln-8Chess constructor8.< A "ublic static voi! #ain-%tringNO args. @ Chess 6 ? ne: Chess-.< A A ///3>
I" you don t call the base'class constructor in 2oar'"ameA B, the co#%iler will co#%lain that it can t "ind a constructor o" the "or# "ame A B. In addition, the call to the base'class constructor must be the "irst thing you do in the derived'class constructor. *The co#%iler will re#ind you i" you get it wrong., RFSURFSTIJLT+(6PTE53TIKGU

Catching base constructor e0ce.tions


6s 0ust noted, the co#%iler "orces you to %lace the base'class constructor call "irst in the body o" the derived'class constructor. This #eans nothing else can a%%ear be"ore it. 6s you ll see in +ha%ter M@, this also %revents a derived'class constructor "ro# catching any e&ce%tions that co#e "ro# a base class. This can be inconvenient at ti#es. RFSURF STIJLT+(6PTE53TIKIU

Combining com.osition and inheritance


It is very co##on to use co#%osition and inheritance together. The "ollowing e&a#%le shows the creation o" a #ore co#%le& class, using both inheritance and co#%osition, along with the necessary constructor initiali1ation=

//3 c'+3Place%etting.Hava // Co#bining co#"osition D inheritance.

2;1

class Plate @ Plate-int i. @ %yste#.out."rintln-8Plate constructor8.< A A class DinnerPlate e6ten!s Plate @ DinnerPlate-int i. @ su"er-i.< %yste#.out."rintln8DinnerPlate constructor8.< A A class Ytensil @ Ytensil-int i. @ %yste#.out."rintln-8Ytensil constructor8.< A A class %"oon e6ten!s Ytensil @ %"oon-int i. @ su"er-i.< %yste#.out."rintln-8%"oon constructor8.< A A class Lork e6ten!s Ytensil @ Lork-int i. @ su"er-i.< %yste#.out."rintln-8Lork constructor8.< A A class `nife e6ten!s Ytensil @ `nife-int i. @ su"er-i.< %yste#.out."rintln-8`nife constructor8.< A A

2;2

Thinking in Java

,,,'0ruceEckel'com

// 0 cultural :ay of !oing so#ething3 class Custo# @ Custo#-int i. @ %yste#.out."rintln-8Custo# constructor8.< A A "ublic class Place%etting e6ten!s Custo# @ %"oon s"< Lork frk< `nife kn< DinnerPlate "l< Place%etting-int i. @ su"er-i K (.< s" ? ne: %"oon-i K .< frk ? ne: Lork-i K ).< kn ? ne: `nife-i K I.< "l ? ne: DinnerPlate-i K ,.< %yste#.out."rintln8Place%etting constructor8.< A "ublic static voi! #ain-%tringNO args. @ Place%etting 6 ? ne: Place%etting-C.< A A ///3>
:hile the co#%iler "orces you to initiali1e the base classes, and reAuires that you do it right at the beginning o" the constructor, it doesn t watch over you to #ake sure that you initiali1e the #e#ber ob0ects, so you #ust re#e#ber to %ay attention to that. RFSURFSTIJLT+(6PTE53TIK2U

'uaranteeing .ro.er cleanu.


Java doesn t have the +<< conce%t o" a destructor, a #ethod that is auto#atically called when an ob0ect is destroyed. The reason is %robably that in Java the %ractice is si#%ly to "orget about ob0ects rather than to destroy the#, allowing the garbage collector to reclai# the #e#ory as necessary. RFSURFSTIJLT+(6PTE53TIL@U )"ten this is "ine, but there are ti#es when your class #ight %er"or# so#e activities during its li"eti#e that reAuire cleanu%. 6s #entioned in

2;3

+ha%ter ?, you can t know when the garbage collector will be called, or i" it will be called. So i" you want so#ething cleaned u% "or a class, you #ust e&%licitly write a s%ecial #ethod to do it, and #ake sure that the client %rogra##er knows that they #ust call this #ethod. )n to% o" this9as described in +ha%ter M@ *!Error (andling with E&ce%tions$,9you #ust guard against an e&ce%tion by %utting such cleanu% in a finally clause. RF SURFSTIJLT+(6PTE53TILMU +onsider an e&a#%le o" a co#%uter'aided design syste# that draws %ictures on the screen=

//3 c'+3C0D%yste#.Hava // Ensuring "ro"er cleanu". i#"ort Hava.util.B< class %ha"e @ %ha"e-int i. @ %yste#.out."rintln-8%ha"e constructor8.< A voi! cleanu"-. @ %yste#.out."rintln-8%ha"e cleanu"8.< A A class Circle e6ten!s %ha"e @ Circle-int i. @ su"er-i.< %yste#.out."rintln-8Dra:ing a Circle8.< A voi! cleanu"-. @ %yste#.out."rintln-8Erasing a Circle8.< su"er.cleanu"-.< A A class Triangle e6ten!s %ha"e @ Triangle-int i. @ su"er-i.< %yste#.out."rintln-8Dra:ing a Triangle8.< A voi! cleanu"-. @

2;4

Thinking in Java

,,,'0ruceEckel'com

%yste#.out."rintln-8Erasing a Triangle8.< su"er.cleanu"-.< A A class Line e6ten!s %ha"e @ "rivate int start, en!< Line-int start, int en!. @ su"er-start.< this.start ? start< this.en! ? en!< %yste#.out."rintln-8Dra:ing a Line3 8 K start K 8, 8 K en!.< A voi! cleanu"-. @ %yste#.out."rintln-8Erasing a Line3 8 K start K 8, 8 K en!.< su"er.cleanu"-.< A A "ublic class C0D%yste# e6ten!s %ha"e @ "rivate Circle c< "rivate Triangle t< "rivate LineNO lines ? ne: LineN('O< C0D%yste#-int i. @ su"er-i K (.< for-int H ? '< H P ('< HKK. linesNHO ? ne: Line-H, HBH.< c ? ne: Circle-(.< t ? ne: Triangle-(.< %yste#.out."rintln-8Co#bine! constructor8.< A voi! cleanu"-. @ %yste#.out."rintln-8C0D%yste#.cleanu"-.8.< // The or!er of cleanu" is the reverse // of the or!er of initialiUation t.cleanu"-.< c.cleanu"-.< for-int i ? lines.length - (< i Q? '< i--. linesNiO.cleanu"-.<

2;5

su"er.cleanu"-.< A "ublic static voi! #ain-%tringNO args. @ C0D%yste# 6 ? ne: C0D%yste#-I*.< try @ // Co!e an! e6ce"tion han!ling... A finally @ 6.cleanu"-.< A A A ///3>
Everything in this syste# is so#e kind o" )hape *which is itsel" a kind o" .b8ect since it s i#%licitly inherited "ro# the root class,. Each class rede"ines )hape s clean*pA B #ethod in addition to calling the base' class version o" that #ethod using s*per. The s%eci"ic )hape classes9 -ircle, Triangle and +ine9all have constructors that !draw,$ although any #ethod called during the li"eti#e o" the ob0ect could be res%onsible "or doing so#ething that needs cleanu%. Each class has its own clean*p A B #ethod to restore non#e#ory things back to the way they were be"ore the ob0ect e&isted. RFSURFSTIJLT+(6PTE53TILKU In mainA B, you can see two keywords that are new, and won t o""icially be introduced until +ha%ter M@= try and finally. The try keyword indicates that the block that "ollows *deli#ited by curly braces, is a guarded region, which #eans that it is given s%ecial treat#ent. )ne o" these s%ecial treat#ents is that the code in the finally clause "ollowing this guarded region is al,a)s e&ecuted, no #atter how the try block e&its. *:ith e&ce%tion handling, it s %ossible to leave a try block in a nu#ber o" nonordinary ways., (ere, the finally clause is saying !always call clean*pA B "or 4, no #atter what ha%%ens.$ These keywords will be e&%lained thoroughly in +ha%ter M@. RFSURFSTIJLT+(6PTE53TILLU Cote that in your cleanu% #ethod you #ust also %ay attention to the calling order "or the base'class and #e#ber'ob0ect cleanu% #ethods in case one subob0ect de%ends on another. In general, you should "ollow the sa#e "or# that is i#%osed by a +<< co#%iler on its destructors= Eirst %er"or# all o" the cleanu% work s%eci"ic to your class, in the reverse order o" creation. *In general, this reAuires that base'class ele#ents still be

2;7

Thinking in Java

,,,'0ruceEckel'com

viable., Then call the base'class cleanu% #ethod, as de#onstrated here. RFSURFSTIJLT+(6PTE53TIL?U There can be #any cases in which the cleanu% issue is not a %roble#; you 0ust let the garbage collector do the work. But when you #ust do it e&%licitly, diligence and attention is reAuired. RFSURF STIJLT+(6PTE53TILHU

Order of garbage collection


There s not #uch you can rely on when it co#es to garbage collection. The garbage collector #ight never be called. I" it is, it can reclai# ob0ects in any order it wants. It s best to not rely on garbage collection "or anything but #e#ory recla#ation. I" you want cleanu% to take %lace, #ake your own cleanu% #ethods and don t rely on finali7eA B. *6s #entioned in +ha%ter ?, Java can be "orced to call all the "inali1ers., RF SURFSTIJLT+(6PTE53TIL3U

2ame hiding
)nly +<< %rogra##ers #ight be sur%rised by na#e hiding, since it works di""erently in that language. I" a Java base class has a #ethod na#e that s overloaded several ti#es, rede"ining that #ethod na#e in the derived class will not hide any o" the base'class versions. Thus overloading works regardless o" whether the #ethod was de"ined at this level or in a base class=

//3 c'+3Mi!e.Hava // Gverloa!ing a base-class #etho! na#e // in a !erive! class !oes not hi!e the // base-class versions. class Mo#er @ char !oh-char c. @ %yste#.out."rintln-8!oh-char.8.< return 2!2< A float !oh-float f. @ %yste#.out."rintln-8!oh-float.8.< return (.'f<

2;8

A A class Jilhouse @A class Bart e6ten!s Mo#er @ voi! !oh-Jilhouse #. @A A "ublic class Mi!e @ "ublic static voi! #ain-%tringNO args. @ Bart b ? ne: Bart-.< b.!oh-(.< // !oh-float. use! b.!oh-262.< b.!oh-(.'f.< b.!oh-ne: Jilhouse-..< A A ///3>
6s you ll see in the ne&t cha%ter, it s "ar #ore co##on to override #ethods o" the sa#e na#e using e&actly the sa#e signature and return ty%e as in the base class. It can be con"using otherwise *which is why +<< disallows it, to %revent you "ro# #aking what is %robably a #istake,. RF SURFSTIJLT+(6PTE53TILGU

Choosing com.osition vs) inheritance


Both co#%osition and inheritance allow you to %lace subob0ects inside your new class. /ou #ight wonder about the di""erence between the two, and when to choose one over the other. RFSURFSTIJLT+(6PTE53TILIU +o#%osition is generally used when you want the "eatures o" an e&isting class inside your new class, but not its inter"ace. That is, you e#bed an ob0ect so that you can use it to i#%le#ent "unctionality in your new class, but the user o" your new class sees the inter"ace you ve de"ined "or the new class rather than the inter"ace "ro# the e#bedded ob0ect. Eor this

2;:

Thinking in Java

,,,'0ruceEckel'com

e""ect, you e#bed private ob0ects o" e&isting classes inside your new class. RFSURFSTIJLT+(6PTE53TIL2U So#eti#es it #akes sense to allow the class user to directly access the co#%osition o" your new class; that is, to #ake the #e#ber ob0ects p*blic. The #e#ber ob0ects use i#%le#entation hiding the#selves, so this is a sa"e thing to do. :hen the user knows you re asse#bling a bunch o" %arts, it #akes the inter"ace easier to understand. 6 car ob0ect is a good e&a#%le=

//3 c'+3Car.Hava // Co#"osition :ith "ublic obHects. class Engine @ "ublic voi! start-. @A "ublic voi! rev-. @A "ublic voi! sto"-. @A A class \heel @ "ublic voi! inflate-int "si. @A A class \in!o: @ "ublic voi! rollu"-. @A "ublic voi! roll!o:n-. @A A class Door @ "ublic \in!o: :in!o: ? ne: \in!o:-.< "ublic voi! o"en-. @A "ublic voi! close-. @A A "ublic class Car @ "ublic Engine engine ? ne: Engine-.< "ublic \heelNO :heel ? ne: \heelNIO< "ublic Door left ? ne: Door-., right ? ne: Door-.< // -!oor "ublic Car-. @ for-int i ? '< i P I< iKK.

2;;

:heelNiO ? ne: \heel-.< A "ublic static voi! #ain-%tringNO args. @ Car car ? ne: Car-.< car.left.:in!o:.rollu"-.< car.:heelN'O.inflate-* .< A A ///3>
Because the co#%osition o" a car is %art o" the analysis o" the %roble# *and not si#%ly %art o" the underlying design,, #aking the #e#bers p*blic assists the client %rogra##er s understanding o" how to use the class and reAuires less code co#%le&ity "or the creator o" the class. (owever, kee% in #ind that this is a s%ecial case and that in general you should #ake "ields private. RFSURFSTIJLT+(6PTE53TI?@U :hen you inherit, you take an e&isting class and #ake a s%ecial version o" it. In general, this #eans that you re taking a general'%ur%ose class and s%eciali1ing it "or a %articular need. :ith a little thought, you ll see that it would #ake no sense to co#%ose a car using a vehicle ob0ect9a car doesn t contain a vehicle, it is a vehicle. The is/a relationshi% is e&%ressed with inheritance, and the has/a relationshi% is e&%ressed with co#%osition. RFSURFSTIJLT+(6PTE53TI?MU

.rotected
Cow that you ve been introduced to inheritance, the keyword protecte' "inally has #eaning. In an ideal world, private #e#bers would always be hard'and'"ast private, but in real %ro0ects there are ti#es when you want to #ake so#ething hidden "ro# the world at large and yet allow access "or #e#bers o" derived classes. The protecte' keyword is a nod to %rag#atis#. It says !This is private as "ar as the class user is concerned, but available to anyone who inherits "ro# this class or anyone else in the sa#e package.$ That is, protecte' in Java is auto#atically !"riendly.$ RFSURFSTIJLT+(6PTE53TI?KU The best tack to take is to leave the data #e#bers private9you should always %reserve your right to change the underlying i#%le#entation. /ou

3==

Thinking in Java

,,,'0ruceEckel'com

can then allow controlled access to inheritors o" your class through protecte' #ethods=

//3 c'+3Grc.Hava // The "rotecte! key:or!. i#"ort Hava.util.B< class Willain @ "rivate int i< "rotecte! int rea!-. @ return i< "rotecte! voi! set-int ii. @ i ? "ublic Willain-int ii. @ i ? ii< "ublic int value-int #. @ return A

A ii< A A #Bi< A

"ublic class Grc e6ten!s Willain @ "rivate int H< "ublic Grc-int HH. @ su"er-HH.< H ? HH< A "ublic voi! change-int 6. @ set-6.< A A ///3>
/ou can see that changeA B has access to setA B because it s protecte'. RFSURFSTIJLT+(6PTE53TI?LU

Incremental develo.ment
)ne o" the advantages o" inheritance is that it su%%orts incremental develo ment by allowing you to introduce new code without causing bugs in e&isting code. This also isolates new bugs inside the new code. By inheriting "ro# an e&isting, "unctional class and adding data #e#bers and #ethods *and rede"ining e&isting #ethods,, you leave the e&isting code9that so#eone else #ight still be using9untouched and unbugged. I" a bug ha%%ens, you know that it s in your new code, which is #uch shorter and easier to read than i" you had #odi"ied the body o" e&isting code. RFSURFSTIJLT+(6PTE53TI??U

3=1

It s rather a#a1ing how cleanly the classes are se%arated. /ou don t even need the source code "or the #ethods in order to reuse the code. 6t #ost, you 0ust i#%ort a %ackage. *This is true "or both inheritance and co#%osition., RFSURFSTIJLT+(6PTE53TI?HU It s i#%ortant to reali1e that %rogra# develo%#ent is an incre#ental %rocess, 0ust like hu#an learning. /ou can do as #uch analysis as you want, but you still won t know all the answers when you set out on a %ro0ect. /ou ll have #uch #ore success9and #ore i##ediate "eedback9 i" you start out to !grow$ your %ro0ect as an organic, evolutionary creature, rather than constructing it all at once like a glass'bo& skyscra%er. RFSURFSTIJLT+(6PTE53TI?3U 6lthough inheritance "or e&%eri#entation can be a use"ul techniAue, at so#e %oint a"ter things stabili1e you need to take a new look at your class hierarchy with an eye to colla%sing it into a sensible structure. 5e#e#ber that underneath it all, inheritance is #eant to e&%ress a relationshi% that says !This new class is a t) e o$ that old class.$ /our %rogra# should not be concerned with %ushing bits around, but instead with creating and #ani%ulating ob0ects o" various ty%es to e&%ress a #odel in the ter#s that co#e "ro# the %roble# s%ace. RFSURFSTIJLT+(6PTE53TI?GU

C.casting
The #ost i#%ortant as%ect o" inheritance is not that it %rovides #ethods "or the new class. It s the relationshi% e&%ressed between the new class and the base class. This relationshi% can be su##ari1ed by saying !The new class is a t) e o$ the e&isting class.$ RFSURF STIJLT+(6PTE53TI?IU This descri%tion is not 0ust a "anci"ul way o" e&%laining inheritance9it s su%%orted directly by the language. 6s an e&a#%le, consider a base class called Instr*ment that re%resents #usical instru#ents, and a derived class called 0in'. Because inheritance #eans that all o" the #ethods in the base class are also available in the derived class, any #essage you can send to the base class can also be sent to the derived class. I" the Instr*ment class has a playA B #ethod, so will 0in' instru#ents. This #eans we can accurately say that a 0in' ob0ect is also a ty%e o"

3=2

Thinking in Java

,,,'0ruceEckel'com

Instr*ment. The "ollowing e&a#%le shows how the co#%iler su%%orts


this notion=

//3 c'+3\in!.Hava // $nheritance D u"casting. i#"ort Hava.util.B< class $nstru#ent @ "ublic voi! "lay-. @A static voi! tune-$nstru#ent i. @ // ... i."lay-.< A A // \in! obHects are instru#ents // because they have the sa#e interface3 "ublic class \in! e6ten!s $nstru#ent @ "ublic static voi! #ain-%tringNO args. @ \in! flute ? ne: \in!-.< $nstru#ent.tune-flute.< // Y"casting A A ///3>
:hat s interesting in this e&a#%le is the t*neA B #ethod, which acce%ts an Instr*ment re"erence. (owever, in 0in'.mainA B the t*neA B #ethod is called by giving it a 0in' re"erence. 8iven that Java is %articular about ty%e checking, it see#s strange that a #ethod that acce%ts one ty%e will readily acce%t another ty%e, until you reali1e that a 0in' ob0ect is also an Instr*ment ob0ect, and there s no #ethod that t*neA B could call "or an Instr*ment that isn t also in 0in'. Inside t*neA B, the code works "or Instr*ment and anything derived "ro# Instr*ment, and the act o" converting a 0in' re"erence into an Instr*ment re"erence is called u casting. RFSURF STIJLT+(6PTE53TI?2U

Wh: Ju.castingKA
The reason "or the ter# is historical, and based on the way class inheritance diagra#s have traditionally been drawn= with the root at the

3=3

to% o" the %age, growing downward. *)" course, you can draw your diagra#s any way you "ind hel%"ul., The inheritance diagra# "or 0in'! 8ava is then=
Instrument

Wind

+asting "ro# derived to base #oves u on the inheritance diagra#, so it s co##only re"erred to as u casting. 4%casting is always sa"e because you re going "ro# a #ore s%eci"ic ty%e to a #ore general ty%e. That is, the derived class is a su%erset o" the base class. It #ight contain #ore #ethods than the base class, but it #ust contain at least the #ethods in the base class. The only thing that can occur to the class inter"ace during the u%cast is that it can lose #ethods, not gain the#. This is why the co#%iler allows u%casting without any e&%licit casts or other s%ecial notation. RFSURFSTIJLT+(6PTE53TIH@U /ou can also %er"or# the reverse o" u%casting, called do,ncasting, but this involves a dile##a that is the sub0ect o" +ha%ter MK. RFSURF STIJLT+(6PTE53TIHMU

Com.osition vs) inheritance revisited


In ob0ect'oriented %rogra##ing, the #ost likely way that you ll create and use code is by si#%ly %ackaging data and #ethods together into a class, and using ob0ects o" that class. /ou ll also use e&isting classes to build new classes with co#%osition. Dess "reAuently, you ll use inheritance. So although inheritance gets a lot o" e#%hasis while learning ))P, it doesn t #ean that you should use it everywhere you %ossibly can. )n the contrary, you should use it s%aringly, only when it s clear that inheritance is use"ul. )ne o" the clearest ways to deter#ine whether you should use co#%osition or inheritance is to ask whether you ll ever need to u%cast "ro# your new class to the base class. I" you #ust u%cast, then inheritance is necessary, but i" you don t need to u%cast, then you should look closely at whether you need inheritance. The ne&t cha%ter *%oly#or%his#, %rovides one o" the #ost co#%elling reasons "or

3=4

Thinking in Java

,,,'0ruceEckel'com

u%casting, but i" you re#e#ber to ask !7o I need to u%castO$ you ll have a good tool "or deciding between co#%osition and inheritance. RFSURF STIJLT+(6PTE53TIHKU

#he !inal ke:word


Java s final keyword has slightly di""erent #eanings de%ending on the conte&t, but in general it says !This cannot be changed.$ /ou #ight want to %revent changes "or two reasons= design or e""iciency. Because these two reasons are Auite di""erent, it s %ossible to #isuse the final keyword. RFSURFSTIJLT+(6PTE53TIHLU The "ollowing sections discuss the three %laces where final can be used= "or data, #ethods, and classes. RFSURFSTIJLT+(6PTE53TIH?U

<inal data
Many %rogra##ing languages have a way to tell the co#%iler that a %iece o" data is !constant.$ 6 constant is use"ul "or two reasons=

+5) +6)

It can be a com ile/time constant that won t ever change. RFSURF STIJLT+(6PTE53TIHHU It can be a value initiali1ed at run'ti#e that you don t want changed. RFSURFSTIJLT+(6PTE53TIH3U

In the case o" a co#%ile'ti#e constant, the co#%iler is allowed to !"old$ the constant value into any calculations in which it s used; that is, the calculation can be %er"or#ed at co#%ile'ti#e, eli#inating so#e run'ti#e overhead. In Java, these sorts o" constants #ust be %ri#itives and are e&%ressed using the final keyword. 6 value #ust be given at the ti#e o" de"inition o" such a constant. RFSURFSTIJLT+(6PTE53TIHGU 6 "ield that is both static and final has only one %iece o" storage that cannot be changed. RFSURFSTIJLT+(6PTE53TIHIU :hen using final with ob0ect re"erences rather than %ri#itives the #eaning gets a bit con"using. :ith a %ri#itive, final #akes the value a constant, but with an ob0ect re"erence, final #akes the re$erence a

3=5

constant. )nce the re"erence is initiali1ed to an ob0ect, it can never be changed to %oint to another ob0ect. (owever, the ob0ect itsel" can be #odi"ied; Java does not %rovide a way to #ake any arbitrary ob0ect a constant. */ou can, however, write your class so that ob0ects have the e""ect o" being constant., This restriction includes arrays, which are also ob0ects. RFSURFSTIJLT+(6PTE53TIH2U (ere s an e&a#%le that de#onstrates final "ields=

//3 c'+3LinalData.Hava // The effect of final on fiel!s. class Walue @ int i ? (< "ublic Walue-int ii. @ i ? ii< A A "ublic class LinalData @ // Can be co#"ile-ti#e constants final int i( ? C< static final int W0LbT\G ? CC< // Ty"ical "ublic constant3 "ublic static final int W0LbTM5EE ? )C< // Cannot be co#"ile-ti#e constants3 final int iI ? -int.-Jath.ran!o#-.B '.< static final int i, ? -int.-Jath.ran!o#-.B '.< Walue v( ? ne: Walue-((.< final Walue v ? ne: Walue- .< static final Walue v) ? ne: Walue-)).< // 0rrays3 final intNO a ? @ (, , ), I, ,, + A< "ublic voi! "rint-%tring i!. @ %yste#.out."rintlni! K 83 8 K 8iI ? 8 K iI K 8, i, ? 8 K i,.< A "ublic static voi! #ain-%tringNO args. @ LinalData f!( ? ne: LinalData-.< //4 f!(.i(KK< // Error3 can2t change value

3=7

Thinking in Java

,,,'0ruceEckel'com

f!(.v .iKK< // GbHect isn2t constant4 f!(.v( ? ne: Walue-C.< // G` -- not final for-int i ? '< i P f!(.a.length< iKK. f!(.aNiOKK< // GbHect isn2t constant4 //4 f!(.v ? ne: Walue-'.< // Error3 Can2t //4 f!(.v) ? ne: Walue-(.< // change reference //4 f!(.a ? ne: intN)O< f!(."rint-8f!(8.< %yste#.out."rintln-8Creating ne: LinalData8.< LinalData f! ? ne: LinalData-.< f!(."rint-8f!(8.< f! ."rint-8f! 8.< A A ///3>
Since i> and VA+XT0. are final %ri#itives with co#%ile'ti#e values, they can both be used as co#%ile'ti#e constants and are not di""erent in any i#%ortant way. VA+XTH$&& is the #ore ty%ical way you ll see such constants de"ined= p*blic so they re usable outside the %ackage, static to e#%hasi1e that there s only one, and final to say that it s a constant. Cote that final static %ri#itives with constant initial values *that is, co#%ile' ti#e constants, are na#ed with all ca%itals by convention, with words se%arated by underscores *This is 0ust like + constants, which is where the convention originated., 6lso note that i@ cannot be known at co#%ile' ti#e, so it is not ca%itali1ed. RFSURFSTIJLT+(6PTE53TI3@U Just because so#ething is final doesn t #ean that its value is known at co#%ile'ti#e. This is de#onstrated by initiali1ing iQ and i@ at run'ti#e using rando#ly generated nu#bers. This %ortion o" the e&a#%le also shows the di""erence between #aking a final value static or non' static. This di""erence shows u% only when the values are initiali1ed at run'ti#e, since the co#%ile'ti#e values are treated the sa#e by the co#%iler. *6nd %resu#ably o%ti#i1ed out o" e&istence., The di""erence is shown in the out%ut "ro# one run=

f!(3 iI ? (,, i, ? C Creating ne: LinalData f!(3 iI ? (,, i, ? C f! 3 iI ? (', i, ? C

3=8

Cote that the values o" iQ "or f'> and f'I are uniAue, but the value "or i@ is not changed by creating the second Final ata ob0ect. That s because it s static and is initiali1ed once u%on loading and not each ti#e a new ob0ect is created. RFSURFSTIJLT+(6PTE53TI3MU The variables v> through vQ vJ de#onstrate the #eaning o" a final re"erence. 6s you can see in mainA B, 0ust because vI is final doesn t #ean that you can t change its value. (owever, you cannot rebind vI to a new ob0ect, %recisely because it s final. That s what final #eans "or a re"erence. /ou can also see the sa#e #eaning holds true "or an array, which is 0ust another kind o" re"erence. *There is no way that I know o" to #ake the array re"erences the#selves final., Making re"erences final see#s less use"ul than #aking %ri#itives final. RFSURF STIJLT+(6PTE53TI3KU

;lank finals
Java allows the creation o" blank $inals, which are "ields that are declared as final but are not given an initiali1ation value. In all cases, the blank "inal must be initiali1ed be"ore it is used, and the co#%iler ensures this. (owever, blank "inals %rovide #uch #ore "le&ibility in the use o" the final keyword since, "or e&a#%le, a final "ield inside a class can now be di""erent "or each ob0ect and yet it retains its i##utable Auality. (ere s an e&a#%le=

//3 c'+3BlankLinal.Hava // 8Blank8 final !ata #e#bers. class Po""et @ int i< "ublic Po""et-int ii. @ i ? ii< A A "ublic class BlankLinal @ final int i ? '< // $nitialiUe! final final int H< // Blank final final Po""et "< // Blank final reference // Blank finals JY%T be initialiUe! // in the constructor3 BlankLinal-. @

3=:

Thinking in Java

,,,'0ruceEckel'com

H ? (< // $nitialiUe blank final " ? ne: Po""et-(.< A BlankLinal-int 6. @ H ? 6< // $nitialiUe blank final " ? ne: Po""et-6.< A "ublic static voi! #ain-%tringNO args. @ BlankLinal bf ? ne: BlankLinal-.< ne: BlankLinal-I*.< A A ///3>
/ou re "orced to %er"or# assign#ents to finals either with an e&%ression at the %oint o" de"inition o" the "ield or in every constructor. This way it s guaranteed that the final "ield is always initiali1ed be"ore use. RFSURF STIJLT+(6PTE53TI3LU

<inal arguments
Java allows you to #ake argu#ents final by declaring the# as such in the argu#ent list. This #eans that inside the #ethod you cannot change what the argu#ent re"erence %oints to=

//3 c'+3Linal0rgu#ents.Hava // Ysing 8final8 :ith #etho! argu#ents. class aiU#o @ "ublic voi! s"in-. @A A "ublic class Linal0rgu#ents @ voi! :ith-final aiU#o g. @ //4 g ? ne: aiU#o-.< // $llegal -- g is final A voi! :ithout-aiU#o g. @ g ? ne: aiU#o-.< // G` -- g not final g.s"in-.< A // voi! f-final int i. @ iKK< A // Can2t change // ;ou can only rea! fro# a final "ri#itive3 int g-final int i. @ return i K (< A

3=;

"ublic static voi! #ain-%tringNO args. @ Linal0rgu#ents bf ? ne: Linal0rgu#ents-.< bf.:ithout-null.< bf.:ith-null.< A A ///3>
Cote that you can still assign a n*ll re"erence to an argu#ent that s "inal without the co#%iler catching it, 0ust like you can with a non' final argu#ent. RFSURFSTIJLT+(6PTE53TI3?U The #ethods fA B and gA B show what ha%%ens when %ri#itive argu#ents are final= you can read the argu#ent, but you canVt change it. RFSURF STIJLT+(6PTE53TI3HU

<inal methods
There are two reasons "or final #ethods. The "irst is to %ut a !lock$ on the #ethod to %revent any inheriting class "ro# changing its #eaning. This is done "or design reasons when you want to #ake sure that a #ethod s behavior is retained during inheritance and cannot be overridden. RFSURFSTIJLT+(6PTE53TI33U The second reason "or final #ethods is e""iciency. I" you #ake a #ethod final, you are allowing the co#%iler to turn any calls to that #ethod into inline calls. :hen the co#%iler sees a final #ethod call it can *at its discretion, ski% the nor#al a%%roach o" inserting code to %er"or# the #ethod call #echanis# *%ush argu#ents on the stack, ho% over to the #ethod code and e&ecute it, ho% back and clean o"" the stack argu#ents, and deal with the return value, and instead re%lace the #ethod call with a co%y o" the actual code in the #ethod body. This eli#inates the overhead o" the #ethod call. )" course, i" a #ethod is big, then your code begins to bloat and you %robably won t see any %er"or#ance gains "ro# inlining, since any i#%rove#ents will be dwar"ed by the a#ount o" ti#e s%ent inside the #ethod. It is i#%lied that the Java co#%iler is able to detect these situations and choose wisely whether to inline a final #ethod. (owever, it s better to not trust that the co#%iler is able to do this and #ake a #ethod final only i" it s Auite s#all or i" you want to e&%licitly %revent overriding. RFSURFSTIJLT+(6PTE53TI3GU

31=

Thinking in Java

,,,'0ruceEckel'com

final and .rivate


6ny private #ethods in a class are i#%licitly final. Because you can t access a private #ethod, you can t override it *even though the co#%iler doesn t give an error #essage i" you try to override it, you haven t overridden the #ethod, you ve 0ust created a new #ethod,. /ou can add the final s%eci"ier to a private #ethod but it doesn t give that #ethod any e&tra #eaning. RFSURFSTIJLT+(6PTE53TI3IU This issue can cause con"usion, because i" you try to override a private #ethod *which is i#%licitly final, it see#s to work=

//3 c'+3LinalGverri!ing$llusion.Hava // $t only looks like you can overri!e // a "rivate or "rivate final #etho!. class \ithLinals @ // $!entical to 8"rivate8 alone3 "rivate final voi! f-. @ %yste#.out."rintln-8\ithLinals.f-.8.< A // 0lso auto#atically 8final83 "rivate voi! g-. @ %yste#.out."rintln-8\ithLinals.g-.8.< A A class Gverri!ingPrivate e6ten!s \ithLinals @ "rivate final voi! f-. @ %yste#.out."rintln-8Gverri!ingPrivate.f-.8.< A "rivate voi! g-. @ %yste#.out."rintln-8Gverri!ingPrivate.g-.8.< A A class Gverri!ingPrivate e6ten!s Gverri!ingPrivate @ "ublic final voi! f-. @ %yste#.out."rintln-8Gverri!ingPrivate .f-.8.< A

311

"ublic voi! g-. @ %yste#.out."rintln-8Gverri!ingPrivate .g-.8.< A A "ublic class LinalGverri!ing$llusion @ "ublic static voi! #ain-%tringNO args. @ Gverri!ingPrivate o" ? ne: Gverri!ingPrivate -.< o" .f-.< o" .g-.< // ;ou can u"cast3 Gverri!ingPrivate o" ? o" < // But you can2t call the #etho!s3 //4 o".f-.< //4 o".g-.< // %a#e here3 \ithLinals :f ? o" < //4 :f.f-.< //4 :f.g-.< A A ///3>
!)verriding$ can only occur i" so#ething is %art o" the base'class inter"ace. That is, you #ust be able to u%cast an ob0ect to its base ty%e and call the sa#e #ethod *the %oint o" this will beco#e clear in the ne&t cha%ter,. I" a #ethod is private, it isn t %art o" the base'class inter"ace. It is 0ust so#e code that s hidden away inside the class, and it 0ust ha%%ens to have that na#e, but i" you create a p*blic, protecte' or !"riendly$ #ethod in the derived class, there s no connection to the #ethod that #ight ha%%en to have that na#e in the base class. Since a private #ethod is unreachable and e""ectively invisible, it doesn t "actor into anything e&ce%t "or the code organi1ation o" the class "or which it was de"ined. RFSURFSTIJLT+(6PTE53TI32U

<inal classes
:hen you say that an entire class is final *by %receding its de"inition with the final keyword,, you state that you don t want to inherit "ro# this class or allow anyone else to do so. In other words, "or so#e reason the

312

Thinking in Java

,,,'0ruceEckel'com

design o" your class is such that there is never a need to #ake any changes, or "or sa"ety or security reasons you don t want subclassing. 6lternatively, you #ight be dealing with an e""iciency issue, and you want to #ake sure that any activity involved with ob0ects o" this class are as e""icient as %ossible. RFSURFSTIJLT+(6PTE53TIG@U

//3 c'+3Jurassic.Hava // Jaking an entire class final. class %#allBrain @A final class Dinosaur @ int i ? *< int H ? (< %#allBrain 6 ? ne: %#allBrain-.< voi! f-. @A A //4 class Lurther e6ten!s Dinosaur @A // error3 Cannot e6ten! final class 2Dinosaur2 "ublic class Jurassic @ "ublic static voi! #ain-%tringNO args. @ Dinosaur n ? ne: Dinosaur-.< n.f-.< n.i ? I'< n.HKK< A A ///3>
Cote that the data #e#bers can be final or not, as you choose. The sa#e rules a%%ly to final "or data #e#bers regardless o" whether the class is de"ined as final. 7e"ining the class as final si#%ly %revents inheritance9 nothing #ore. (owever, because it %revents inheritance all #ethods in a final class are i#%licitly final, since there s no way to override the#. So the co#%iler has the sa#e e""iciency o%tions as it does i" you e&%licitly declare a #ethod final. RFSURFSTIJLT+(6PTE53TIGMU /ou can add the final s%eci"ier to a #ethod in a final class, but it doesn t add any #eaning. RFSURFSTIJLT+(6PTE53TIGKU

313

<inal caution
It can see# to be sensible to #ake a #ethod final while you re designing a class. /ou #ight "eel that e""iciency is very i#%ortant when using your class and that no one could %ossibly want to override your #ethods anyway. So#eti#es this is true. RFSURFSTIJLT+(6PTE53TIGLU But be care"ul with your assu#%tions. In general, it s di""icult to antici%ate how a class can be reused, es%ecially a general'%ur%ose class. I" you de"ine a #ethod as final you #ight %revent the %ossibility o" reusing your class through inheritance in so#e other %rogra##er s %ro0ect si#%ly because you couldn t i#agine it being used that way. RFSURF STIJLT+(6PTE53TIG?U The standard Java library is a good e&a#%le o" this. In %articular, the Java M.@FM.M Vector class was co##only used and #ight have been even #ore use"ul i", in the na#e o" e""iciency, all the #ethods hadn t been #ade final. It s easily conceivable that you #ight want to inherit and override with such a "unda#entally use"ul class, but the designers so#ehow decided this wasn t a%%ro%riate. This is ironic "or two reasons. Eirst, )tack is inherited "ro# Vector, which says that a )tack is a Vector, which isn t really true "ro# a logical stand%oint. Second, #any o" the #ost i#%ortant #ethods o" Vector, such as a''&lementA B and elementAtA B are synchroni7e'. 6s you will see in +ha%ter M?, this incurs a signi"icant %er"or#ance overhead that %robably wi%es out any gains %rovided by final. This lends credence to the theory that %rogra##ers are consistently bad at guessing where o%ti#i1ations should occur. It s 0ust too bad that such a clu#sy design #ade it into the standard library where we #ust all co%e with it. *Eortunately, the Java K container library re%laces Vector with Array+ist, which behaves #uch #ore civilly. 4n"ortunately, there s still %lenty o" new code being written that uses the old container library., RFSURFSTIJLT+(6PTE53TIGHU It s also interesting to note that Hashtable, another i#%ortant standard library class, does not have any final #ethods. 6s #entioned elsewhere in this book, it s Auite obvious that so#e classes were designed by co#%letely di""erent %eo%le than others. */ou ll see that the #ethod na#es in Hashtable are #uch brie"er co#%ared to those in Vector, another %iece o" evidence., This is %recisely the sort o" thing that should

314

Thinking in Java

,,,'0ruceEckel'com

not be obvious to consu#ers o" a class library. :hen things are


inconsistent it 0ust #akes #ore work "or the user. /et another %aean to the value o" design and code walkthroughs. *Cote that the Java K container library re%laces Hashtable with Hash1ap., RFSURF STIJLT+(6PTE53TIG3U

Initiali?ation and class loading


In #ore traditional languages, %rogra#s are loaded all at once as %art o" the startu% %rocess. This is "ollowed by initiali1ation, and then the %rogra# begins. The %rocess o" initiali1ation in these languages #ust be care"ully controlled so that the order o" initiali1ation o" statics doesn t cause trouble. +<<, "or e&a#%le, has %roble#s i" one static e&%ects another static to be valid be"ore the second one has been initiali1ed. RF SURFSTIJLT+(6PTE53TIGGU Java doesn t have this %roble# because it takes a di""erent a%%roach to loading. Because everything in Java is an ob0ect, #any activities beco#e easier, and this is one o" the#. 6s you will learn #ore "ully in the ne&t cha%ter, the co#%iled code "or each class e&ists in its own se%arate "ile. That "ile isn t loaded until the code is needed. In general, you can say that !+lass code is loaded at the %oint o" "irst use.$ This is o"ten not until the "irst ob0ect o" that class is constructed, but loading also occurs when a static "ield or static #ethod is accessed. RFSURF STIJLT+(6PTE53TIGIU The %oint o" "irst use is also where the static initiali1ation takes %lace. 6ll the static ob0ects and the static code block will be initiali1ed in te&tual order *that is, the order that you write the# down in the class de"inition, at the %oint o" loading. The statics, o" course, are initiali1ed only once. RF SURFSTIJLT+(6PTE53TIG2U

315

Initiali?ation with inheritance


It s hel%"ul to look at the whole initiali1ation %rocess, including inheritance, to get a "ull %icture o" what ha%%ens. +onsider the "ollowing code=

//3 c'+3Beetle.Hava // The full "rocess of initialiUation. class $nsect @ int i ? C< int H< $nsect-. @ "rt-8i ? 8 K i K 8, H ? 8 K H.< H ? )C< A static int 6( ? "rt-8static $nsect.6( initialiUe!8.< static int "rt-%tring s. @ %yste#.out."rintln-s.< return I*< A A "ublic class Beetle e6ten!s $nsect @ int k ? "rt-8Beetle.k initialiUe!8.< Beetle-. @ "rt-8k ? 8 K k.< "rt-8H ? 8 K H.< A static int 6 ? "rt-8static Beetle.6 initialiUe!8.< "ublic static voi! #ain-%tringNO args. @ "rt-8Beetle constructor8.< Beetle b ? ne: Beetle-.< A A ///3>
The out%ut "or this %rogra# is=

static $nsect.6( initialiUe! static Beetle.6 initialiUe!

317

Thinking in Java

,,,'0ruceEckel'com

Beetle constructor i ? C, H ? ' Beetle.k initialiUe! k ? I* H ? )C


The "irst thing that ha%%ens when you run Java on 2eetle is that you try to access 2eetle!mainA B *a static #ethod,, so the loader goes out and "inds the co#%iled code "or the 2eetle class *this ha%%ens to be in a "ile called 2eetle!class,. In the %rocess o" loading it, the loader notices that it has a base class *that s what the e4ten's keyword says,, which it then loads. This will ha%%en whether or not you re going to #ake an ob0ect o" that base class. *Try co##enting out the ob0ect creation to %rove it to yoursel"., RFSURFSTIJLT+(6PTE53TII@U I" the base class has a base class, that second base class would then be loaded, and so on. Ce&t, the static initiali1ation in the root base class *in this case, Insect, is %er"or#ed, and then the ne&t derived class, and so on. This is i#%ortant because the derived'class static initiali1ation #ight de%end on the base class #e#ber being initiali1ed %ro%erly. RFSURF STIJLT+(6PTE53TIIMU 6t this %oint, the necessary classes have all been loaded so the ob0ect can be created. Eirst, all the %ri#itives in this ob0ect are set to their de"ault values and the ob0ect re"erences are set to n*ll9this ha%%ens in one "ell swoo% by setting the #e#ory in the ob0ect to binary 1ero. Then the base' class constructor will be called. In this case the call is auto#atic, but you can also s%eci"y the base'class constructor call *as the "irst o%eration in the 2eetleA B constructor, using s*per. The base class construction goes through the sa#e %rocess in the sa#e order as the derived'class constructor. 6"ter the base'class constructor co#%letes, the instance variables are initiali1ed in te&tual order. Einally, the rest o" the body o" the constructor is e&ecuted. RFSURFSTIJLT+(6PTE53TIIKU

1ummar:
Both inheritance and co#%osition allow you to create a new ty%e "ro# e&isting ty%es. Ty%ically, however, you use co#%osition to reuse e&isting ty%es as %art o" the underlying i#%le#entation o" the new ty%e, and

318

inheritance when you want to reuse the inter"ace. Since the derived class has the base'class inter"ace, it can be u cast to the base, which is critical "or %oly#or%his#, as you ll see in the ne&t cha%ter. RFSURF STIJLT+(6PTE53TIILU 7es%ite the strong e#%hasis on inheritance in ob0ect'oriented %rogra##ing, when you start a design you should generally %re"er co#%osition during the "irst cut and use inheritance only when it is clearly necessary. +o#%osition tends to be #ore "le&ible. In addition, by using the added arti"ice o" inheritance with your #e#ber ty%e, you can change the e&act ty%e, and thus the behavior, o" those #e#ber ob0ects at run'ti#e. There"ore, you can change the behavior o" the co#%osed ob0ect at run'ti#e. RFSURFSTIJLT+(6PTE53TII?U 6lthough code reuse through co#%osition and inheritance is hel%"ul "or ra%id %ro0ect develo%#ent, you ll generally want to redesign your class hierarchy be"ore allowing other %rogra##ers to beco#e de%endent on it. /our goal is a hierarchy in which each class has a s%eci"ic use and is neither too big *enco#%assing so #uch "unctionality that it s unwieldy to reuse, nor annoyingly s#all *you can t use it by itsel" or without adding "unctionality,. RFSURFSTIJLT+(6PTE53TIIHU

/0ercises
Solutions to selected e&ercises can be "ound in the electronic docu#entThe Thinking in Java "nnotated Solution @uide, available "or a s#all "ee "ro# ,,,'0ruceEckel'com.

,4) +reate two classes, A and 2, with de"ault constructors *e#%ty


argu#ent lists, that announce the#selves. Inherit a new class called - "ro# A, and create a #e#ber o" class 2 inside -. 7o not create a constructor "or -. +reate an ob0ect o" class - and observe the results. RFSURFSTIJLT+(6PTE53TII3U

,5) Modi"y E&ercise M so that A and 2 have constructors with


argu#ents instead o" de"ault constructors. :rite a constructor "or - and %er"or# all initiali1ation within - s constructor. RFSURF STIJLT+(6PTE53TIIGU

31:

Thinking in Java

,,,'0ruceEckel'com

,6) +reate a si#%le class. Inside a second class, de"ine a "ield "or an
ob0ect o" the "irst class. 4se la1y initiali1ation to instantiate this ob0ect. RFSURFSTIJLT+(6PTE53TIIIU

-7) Inherit a new class "ro# class

etergent. )verride scr*bA B and add a new #ethod called sterili7eA B. RFSURF STIJLT+(6PTE53TII2U
the -artoon class. E&%lain what ha%%ens. RFSURF STIJLT+(6PTE53TI2@U

-() Take the "ile -artoon!8ava and co##ent out the constructor "or

-!) Take the "ile -hess!8ava and co##ent out the constructor "or
the -hess class. E&%lain what ha%%ens. RFSURF STIJLT+(6PTE53TI2MU

-*) Prove that de"ault constructors are created "or you by the
co#%iler. RFSURFSTIJLT+(6PTE53TI2KU

-+) Prove that the base'class constructors are *a, always called, and
*b, called be"ore derived'class constructors. RFSURF STIJLT+(6PTE53TI2LU

-,) +reate a base class with only a nonde"ault constructor, and a


derived class with both a de"ault and nonde"ault constructor. In the derived'class constructors, call the base'class constructor. RF SURFSTIJLT+(6PTE53TI2?U

--) +reate a class called $oot that contains an instance o" each o"
classes *that you also create, na#ed -omponent>, -omponentI, and -omponentJ. 7erive a class )tem "ro# $oot that also contains an instance o" each !co#%onent.$ 6ll classes should have de"ault constructors that %rint a #essage about that class. RFSURFSTIJLT+(6PTE53TI2HU

-4) Modi"y E&ercise M@ so that each class only has nonde"ault


constructors. RFSURFSTIJLT+(6PTE53TI23U

-5) 6dd a %ro%er hierarchy o" clean*pA B #ethods to all the classes
in E&ercise MM. RFSURFSTIJLT+(6PTE53TI2GU

31;

-6) +reate a class with a #ethod that is overloaded three ti#es.


Inherit a new class, add a new overloading o" the #ethod, and show that all "our #ethods are available in the derived class. RF SURFSTIJLT+(6PTE53TI2IU

47) In -ar!8ava add a serviceA B #ethod to &ngine and call this


#ethod in mainA B. RFSURFSTIJLT+(6PTE53TI22U

4() +reate a class inside a %ackage. /our class should contain a


protecte' #ethod. )utside o" the %ackage, try to call the protecte' #ethod and e&%lain the results. Cow inherit "ro# your class and call the protecte' #ethod "ro# inside a #ethod o" your
derived class. RFSURFSTIJLT+(6PTE53TIM@@U

4!) +reate a class called Amphibian. Ero# this, inherit a class


called Frog. Put a%%ro%riate #ethods in the base class. In main A B, create a Frog and u%cast it to Amphibian, and de#onstrate that all the #ethods still work. RFSURFSTIJLT+(6PTE53TIM@MU

4*) Modi"y E&ercise M3 so that Frog overrides the #ethod


de"initions "ro# the base class *%rovides new de"initions using the sa#e #ethod signatures,. Cote what ha%%ens in mainA B. RFSURF STIJLT+(6PTE53TIM@KU

4+) +reate a class with a static final "ield and a final "ield and
de#onstrate the di""erence between the two. RFSURF STIJLT+(6PTE53TIM@LU

4,) +reate a class with a blank final re"erence to an ob0ect. Per"or#


the initiali1ation o" the blank final inside a ll constructors #ethod *not the constructor, right be"ore you use it. 7e#onstrate the guarantee that the final #ust be initiali1ed be"ore use, and that it cannot be changed once initiali1ed. RFSURF STIJLT+(6PTE53TIM@?U

4-) +reate a class with a final #ethod. Inherit "ro# that class and
atte#%t to override that #ethod. RFSURF STIJLT+(6PTE53TIM@HU

32=

Thinking in Java

,,,'0ruceEckel'com

44) +reate a final class and atte#%t to inherit "ro# it. RFSURF
STIJLT+(6PTE53TIM@3U

45) Prove that class loading takes %lace only once. Prove that loading
#ay be caused by either the creation o" the "irst instance o" that class, or the access o" a static #e#ber. RFSURF STIJLT+(6PTE53TIM@GU

46) In 2eetle!8ava, inherit a s%eci"ic ty%e o" beetle "ro# class


2eetle, "ollowing the sa#e "or#at as the e&isting classes. Trace
and e&%lain the out%ut. RFSU

321

4: ol:mor.hism
RFSTIJLT+(6PTE5GTI@UPoly#or%his# is the third essential "eature o" an ob0ect'oriented %rogra##ing language, a"ter data abstraction and inheritance.
It %rovides another di#ension o" se%aration o" inter"ace "ro# i#%le#entation, to decou%le ,hat "ro# ho,. Poly#or%his# allows i#%roved code organi1ation and readability as well as the creation o" e*tensible %rogra#s that can be !grown$ not only during the original creation o" the %ro0ect but also when new "eatures are desired. RFSURF STIJLT+(6PTE5GTIMU Enca%sulation creates new data ty%es by co#bining characteristics and behaviors. I#%le#entation hiding se%arates the inter"ace "ro# the i#%le#entation by #aking the details private. This sort o" #echanical organi1ation #akes ready sense to so#eone with a %rocedural %rogra##ing background. But %oly#or%his# deals with decou%ling in ter#s o" t) es. In the last cha%ter, you saw how inheritance allows the treat#ent o" an ob0ect as its own ty%e or its base ty%e. This ability is critical because it allows #any ty%es *derived "ro# the sa#e base ty%e, to be treated as i" they were one ty%e, and a single %iece o" code to work on all those di""erent ty%es eAually. The %oly#or%hic #ethod call allows one ty%e to e&%ress its distinction "ro# another, si#ilar ty%e, as long as they re both derived "ro# the sa#e base ty%e. This distinction is e&%ressed through di""erences in behavior o" the #ethods that you can call through the base class. RFSURFSTIJLT+(6PTE5GTIKU In this cha%ter, you ll learn about %oly#or%his# *also called d)namic binding or late binding or run/time binding, starting "ro# the basics, with si#%le e&a#%les that stri% away everything but the %oly#or%hic behavior o" the %rogra#. RFSURFSTIJLT+(6PTE5GTILU

322

C.casting revisited
In +ha%ter 3 you saw how an ob0ect can be used as its own ty%e or as an ob0ect o" its base ty%e. Taking an ob0ect re"erence and treating it as a re"erence to its base ty%e is called u castingD because o" the way inheritance trees are drawn with the base class at the to%. RFSURF STIJLT+(6PTE5GTI?U /ou also saw a %roble# arise, which is e#bodied in the "ollowing=

//3 c'*3#usic3Jusic.Hava // $nheritance D u"casting. class &ote @ "rivate int value< "rivate &ote-int val. @ value ? val< A "ublic static final &ote J$DDLEbC ? ne: &ote-'., Cb%M05P ? ne: &ote-(., BbLL0T ? ne: &ote- .< A // Etc. class $nstru#ent @ "ublic voi! "lay-&ote n. @ %yste#.out."rintln-8$nstru#ent."lay-.8.< A A // \in! obHects are instru#ents // because they have the sa#e interface3 class \in! e6ten!s $nstru#ent @ // 5e!efine interface #etho!3 "ublic voi! "lay-&ote n. @ %yste#.out."rintln-8\in!."lay-.8.< A A "ublic class Jusic @ "ublic static voi! tune-$nstru#ent i. @ // ...

Cha ter 8! Pol)mor hism

323

i."lay-&ote.J$DDLEbC.< A "ublic static voi! #ain-%tringNO args. @ \in! flute ? ne: \in!-.< tune-flute.< // Y"casting A A ///3>
The #ethod 1*sic!t*neA B acce%ts an Instr*ment re"erence, but also anything derived "ro# Instr*ment. In mainA B, you can see this ha%%ening as a 0in' re"erence is %assed to t*neA B, with no cast necessary. This is acce%table; the inter"ace in Instr*ment #ust e&ist in 0in', because 0in' is inherited "ro# Instr*ment. 4%casting "ro# 0in' to Instr*ment #ay !narrow$ that inter"ace, but it cannot #ake it anything less than the "ull inter"ace to Instr*ment. RFSURF STIJLT+(6PTE5GTIHU

<orgetting the ob3ect t:.e


This %rogra# #ight see# strange to you. :hy should anyone intentionally $orget the ty%e o" an ob0ectO This is what ha%%ens when you u%cast, and it see#s like it could be #uch #ore straight"orward i" t*neA B si#%ly takes a 0in' re"erence as its argu#ent. This brings u% an essential %oint= I" you did that, you d need to write a new t*neA B "or every ty%e o" Instr*ment in your syste#. Su%%ose we "ollow this reasoning and add )tringe' and 2rass instru#ents=

//3 c'*3#usic 3Jusic .Hava // Gverloa!ing instea! of u"casting. class &ote @ "rivate int value< "rivate &ote-int val. @ value ? val< A "ublic static final &ote J$DDLEbC ? ne: &ote-'., Cb%M05P ? ne: &ote-(., BbLL0T ? ne: &ote- .< A // Etc. class $nstru#ent @

324

"ublic voi! "lay-&ote n. @ %yste#.out."rintln-8$nstru#ent."lay-.8.< A A class \in! e6ten!s $nstru#ent @ "ublic voi! "lay-&ote n. @ %yste#.out."rintln-8\in!."lay-.8.< A A class %tringe! e6ten!s $nstru#ent @ "ublic voi! "lay-&ote n. @ %yste#.out."rintln-8%tringe!."lay-.8.< A A class Brass e6ten!s $nstru#ent @ "ublic voi! "lay-&ote n. @ %yste#.out."rintln-8Brass."lay-.8.< A A "ublic class Jusic @ "ublic static voi! tune-\in! i. @ i."lay-&ote.J$DDLEbC.< A "ublic static voi! tune-%tringe! i. @ i."lay-&ote.J$DDLEbC.< A "ublic static voi! tune-Brass i. @ i."lay-&ote.J$DDLEbC.< A "ublic static voi! #ain-%tringNO args. @ \in! flute ? ne: \in!-.< %tringe! violin ? ne: %tringe!-.< Brass frenchMorn ? ne: Brass-.< tune-flute.< // &o u"casting tune-violin.< tune-frenchMorn.< A

Cha ter 8! Pol)mor hism

325

A ///3>
This works, but there s a #a0or drawback= /ou #ust write ty%e's%eci"ic #ethods "or each new Instr*ment class you add. This #eans #ore %rogra##ing in the "irst %lace, but it also #eans that i" you want to add a new #ethod like t*neA B or a new ty%e o" Instr*ment, you ve got a lot o" work to do. 6dd the "act that the co#%iler won t give you any error #essages i" you "orget to overload one o" your #ethods and the whole %rocess o" working with ty%es beco#es un#anageable. RFSURF STIJLT+(6PTE5GTI3U :ouldn t it be #uch nicer i" you could 0ust write a single #ethod that takes the base class as its argu#ent, and not any o" the s%eci"ic derived classesO That is, wouldn t it be nice i" you could "orget that there are derived classes, and write your code to talk only to the base classO RFSURF STIJLT+(6PTE5GTIGU That s e&actly what %oly#or%his# allows you to do. (owever, #ost %rogra##ers who co#e "ro# a %rocedural %rogra##ing background have a bit o" trouble with the way %oly#or%his# works. RFSURF STIJLT+(6PTE5GTIIU

#he twist
The di""iculty with 1*sic.8ava can be seen by running the %rogra#. The out%ut is 0in'!playA B. This is clearly the desired out%ut, but it doesn t see# to #ake sense that it would work that way. Dook at the t*neA B #ethod=

"ublic static voi! tune-$nstru#ent i. @ // ... i."lay-&ote.J$DDLEbC.< A


It receives an Instr*ment re"erence. So how can the co#%iler %ossibly know that this Instr*ment re"erence %oints to a 0in' in this case and not a 2rass or )tringe'O The co#%iler can t. To get a dee%er understanding o" the issue, it s hel%"ul to e&a#ine the sub0ect o" binding. RFSURFSTIJLT+(6PTE5GTI2U

327

Method@call binding
+onnecting a #ethod call to a #ethod body is called binding. :hen binding is %er"or#ed be"ore the %rogra# is run *by the co#%iler and linker, i" there is one,, it s called earl) binding. /ou #ight not have heard the ter# be"ore because it has never been an o%tion with %rocedural languages. + co#%ilers have only one kind o" #ethod call, and that s early binding. RFSURFSTIJLT+(6PTE5GTIM@U The con"using %art o" the above %rogra# revolves around early binding because the co#%iler cannot know the correct #ethod to call when it has only an Instr*ment re"erence. RFSURFSTIJLT+(6PTE5GTIMMU The solution is called late binding, which #eans that the binding occurs at run'ti#e based on the ty%e o" ob0ect. Date binding is also called d)namic binding or run/time binding. :hen a language i#%le#ents late binding, there #ust be so#e #echanis# to deter#ine the ty%e o" the ob0ect at run'ti#e and to call the a%%ro%riate #ethod. That is, the co#%iler still doesn t know the ob0ect ty%e, but the #ethod'call #echanis# "inds out and calls the correct #ethod body. The late'binding #echanis# varies "ro# language to language, but you can i#agine that so#e sort o" ty%e in"or#ation #ust be installed in the ob0ects. RFSURF STIJLT+(6PTE5GTIMKU 6ll #ethod binding in Java uses late binding unless a #ethod has been declared final. This #eans that ordinarily you don t need to #ake any decisions about whether late binding will occur9it ha%%ens auto#atically. RFSURFSTIJLT+(6PTE5GTIMLU :hy would you declare a #ethod finalO 6s noted in the last cha%ter, it %revents anyone "ro# overriding that #ethod. Perha%s #ore i#%ortant, it e""ectively !turns o""$ dyna#ic binding, or rather it tells the co#%iler that dyna#ic binding isn t necessary. This allows the co#%iler to generate slightly #ore e""icient code "or final #ethod calls. (owever, in #ost cases it won t #ake any overall %er"or#ance di""erence in your %rogra#, so it s best to only use final as a design decision, and not as an atte#%t to i#%rove %er"or#ance. RFSURFSTIJLT+(6PTE5GTIM?U

Cha ter 8! Pol)mor hism

328

roducing the right behavior


)nce you know that all #ethod binding in Java ha%%ens %oly#or%hically via late binding, you can write your code to talk to the base class and know that all the derived'class cases will work correctly using the sa#e code. )r to %ut it another way, you !send a #essage to an ob0ect and let the ob0ect "igure out the right thing to do.$ RFSURF STIJLT+(6PTE5GTIMHU The classic e&a#%le in ))P is the !sha%e$ e&a#%le. This is co##only used because it is easy to visuali1e, but un"ortunately it can con"use novice %rogra##ers into thinking that ))P is 0ust "or gra%hics %rogra##ing, which is o" course not the case. RFSURF STIJLT+(6PTE5GTIM3U The sha%e e&a#%le has a base class called )hape and various derived ty%es= -ircle, )C*are, Triangle, etc. The reason the e&a#%le works so well is that it s easy to say !a circle is a ty%e o" sha%e$ and be understood. The inheritance diagra# shows the relationshi%s=
Cast Bu.B the inheritance diagram Sha e draw89 erase89

$ircle Circle >andle draw89 erase89

S%uare draw89 erase89

&riangle draw89 erase89

The u%cast could occur in a state#ent as si#%le as=

%ha"e s ? ne: Circle-.<


(ere, a -ircle ob0ect is created and the resulting re"erence is i##ediately assigned to a )hape, which would see# to be an error

32:

*assigning one ty%e to another,; and yet it s "ine because a -ircle is a )hape by inheritance. So the co#%iler agrees with the state#ent and doesn t issue an error #essage. RFSURFSTIJLT+(6PTE5GTIMGU Su%%ose you call one o" the base'class #ethods *that have been overridden in the derived classes,=

s.!ra:-.<
6gain, you #ight e&%ect that )hape s 'ra(A B is called because this is, a"ter all, a )hape re"erence9so how could the co#%iler know to do anything elseO 6nd yet the %ro%er -ircle!'ra(A B is called because o" late binding *%oly#or%his#,. RFSURFSTIJLT+(6PTE5GTIMIU The "ollowing e&a#%le %uts it a slightly di""erent way=

//3 c'*3%ha"es.Hava // Poly#or"his# in Java. class %ha"e @ voi! !ra:-. @A voi! erase-. @A A class Circle e6ten!s %ha"e @ voi! !ra:-. @ %yste#.out."rintln-8Circle.!ra:-.8.< A voi! erase-. @ %yste#.out."rintln-8Circle.erase-.8.< A A class %=uare e6ten!s %ha"e @ voi! !ra:-. @ %yste#.out."rintln-8%=uare.!ra:-.8.< A voi! erase-. @ %yste#.out."rintln-8%=uare.erase-.8.< A A

Cha ter 8! Pol)mor hism

32;

class Triangle e6ten!s %ha"e @ voi! !ra:-. @ %yste#.out."rintln-8Triangle.!ra:-.8.< A voi! erase-. @ %yste#.out."rintln-8Triangle.erase-.8.< A A "ublic class %ha"es @ "ublic static %ha"e ran!%ha"e-. @ s:itch--int.-Jath.ran!o#-. B ).. @ !efault3 case '3 return ne: Circle-.< case (3 return ne: %=uare-.< case 3 return ne: Triangle-.< A A "ublic static voi! #ain-%tringNO args. @ %ha"eNO s ? ne: %ha"eNCO< // Lill u" the array :ith sha"es3 for-int i ? '< i P s.length< iKK. sNiO ? ran!%ha"e-.< // Jake "oly#or"hic #etho! calls3 for-int i ? '< i P s.length< iKK. sNiO.!ra:-.< A A ///3>
The base class )hape establishes the co##on inter"ace to anything inherited "ro# )hape9that is, all sha%es can be drawn and erased. The derived classes override these de"initions to %rovide uniAue behavior "or each s%eci"ic ty%e o" sha%e. RFSURFSTIJLT+(6PTE5GTIM2U The #ain class )hapes contains a static #ethod ran')hapeA B that %roduces a re"erence to a rando#ly'selected )hape ob0ect each ti#e you call it. Cote that the u%casting ha%%ens in each o" the ret*rn state#ents, each o" which take s a re"erence to a -ircle, )C*are, or Triangle and sends it out o" the #ethod as the return ty%e, )hape. So whenever you call this #ethod you never get a chance to see what s%eci"ic ty%e it is,

33=

since you always get back a %lain )hape re"erence. RFSURF STIJLT+(6PTE5GTIK@U

mainA B contains an array o" )hape re"erences "illed through calls to ran')hapeA B. 6t this %oint you know you have )hapes, but you don t
know anything #ore s%eci"ic than that *and neither does the co#%iler,. (owever, when you ste% through this array and call 'ra(A B "or each one, the correct ty%e's%eci"ic behavior #agically occurs, as you can see "ro# one out%ut e&a#%le=

Circle.!ra:-. Triangle.!ra:-. Circle.!ra:-. Circle.!ra:-. Circle.!ra:-. %=uare.!ra:-. Triangle.!ra:-. %=uare.!ra:-. %=uare.!ra:-.


)" course, since the sha%es are all chosen rando#ly each ti#e, your runs will have di""erent results. The %oint o" choosing the sha%es rando#ly is to drive ho#e the understanding that the co#%iler can have no s%ecial knowledge that allows it to #ake the correct calls at co#%ile'ti#e. 6ll the calls to 'ra(A B are #ade through dyna#ic binding. RFSURF STIJLT+(6PTE5GTIKMU

/0tensibilit:
Cow let s return to the #usical instru#ent e&a#%le. Because o" %oly#or%his#, you can add as #any new ty%es as you want to the syste# without changing the t*neA B #ethod. In a well'designed ))P %rogra#, #ost or all o" your #ethods will "ollow the #odel o" t*neA B and co##unicate only with the base'class inter"ace. Such a %rogra# is e*tensible because you can add new "unctionality by inheriting new data ty%es "ro# the co##on base class. The #ethods that #ani%ulate the base'class inter"ace will not need to be changed at all to acco##odate the new classes. RFSURFSTIJLT+(6PTE5GTIKKU

Cha ter 8! Pol)mor hism

331

+onsider what ha%%ens i" you take the instru#ent e&a#%le and add #ore #ethods in the base class and a nu#ber o" new classes. (ere s the diagra#=
Instrument void .la:89 1tring what89 void ad3ust89

Wind void .la:89 1tring what89 void ad3ust89

ercussion void .la:89 1tring what89 void ad3ust89

1tringed void .la:89 1tring what89 void ad3ust89

Woodwind void .la:89 1tring what89

;rass void .la:89 void ad3ust89

6ll these new classes work correctly with the old, unchanged t*neA B #ethod. Even i" t*neA B is in a se%arate "ile and new #ethods are added to the inter"ace o" Instr*ment, t*neA B works correctly without reco#%ilation. (ere is the i#%le#entation o" the above diagra#=

//3 c'*3#usic)3Jusic).Hava // 0n e6tensible "rogra#. i#"ort Hava.util.B< class $nstru#ent @ "ublic voi! "lay-. @ %yste#.out."rintln-8$nstru#ent."lay-.8.< A

332

"ublic %tring :hat-. @ return 8$nstru#ent8< A "ublic voi! a!Hust-. @A A class \in! e6ten!s $nstru#ent @ "ublic voi! "lay-. @ %yste#.out."rintln-8\in!."lay-.8.< A "ublic %tring :hat-. @ return 8\in!8< A "ublic voi! a!Hust-. @A A class Percussion e6ten!s $nstru#ent @ "ublic voi! "lay-. @ %yste#.out."rintln-8Percussion."lay-.8.< A "ublic %tring :hat-. @ return 8Percussion8< A "ublic voi! a!Hust-. @A A class %tringe! e6ten!s $nstru#ent @ "ublic voi! "lay-. @ %yste#.out."rintln-8%tringe!."lay-.8.< A "ublic %tring :hat-. @ return 8%tringe!8< A "ublic voi! a!Hust-. @A A class Brass e6ten!s \in! @ "ublic voi! "lay-. @ %yste#.out."rintln-8Brass."lay-.8.< A "ublic voi! a!Hust-. @ %yste#.out."rintln-8Brass.a!Hust-.8.< A A class \oo!:in! e6ten!s \in! @ "ublic voi! "lay-. @

Cha ter 8! Pol)mor hism

333

%yste#.out."rintln-8\oo!:in!."lay-.8.< A "ublic %tring :hat-. @ return 8\oo!:in!8< A A "ublic class Jusic) @ // Doesn2t care about ty"e, so ne: ty"es // a!!e! to the syste# still :ork right3 static voi! tune-$nstru#ent i. @ // ... i."lay-.< A static voi! tune0ll-$nstru#entNO e. @ for-int i ? '< i P e.length< iKK. tune-eNiO.< A "ublic static voi! #ain-%tringNO args. @ $nstru#entNO orchestra ? ne: $nstru#entN,O< int i ? '< // Y"casting !uring a!!ition to the array3 orchestraNiKKO ? ne: \in!-.< orchestraNiKKO ? ne: Percussion-.< orchestraNiKKO ? ne: %tringe!-.< orchestraNiKKO ? ne: Brass-.< orchestraNiKKO ? ne: \oo!:in!-.< tune0ll-orchestra.< A A ///3>
The new #ethods are (hatA B, which returns a )tring re"erence with a descri%tion o" the class, and a'8*stA B, which %rovides so#e way to ad0ust each instru#ent. RFSURFSTIJLT+(6PTE5GTIKLU In mainA B, when you %lace so#ething inside the Instr*ment array you auto#atically u%cast to Instr*ment. RFSURFSTIJLT+(6PTE5GTIK?U /ou can see that the t*neA B #ethod is bliss"ully ignorant o" all the code changes that have ha%%ened around it, and yet it works correctly. This is e&actly what %oly#or%his# is su%%osed to %rovide. /our code changes don t cause da#age to %arts o" the %rogra# that should not be a""ected. Put another way, %oly#or%his# is one o" the #ost i#%ortant techniAues

334

that allow the %rogra##er to !se%arate the things that change "ro# the things that stay the sa#e.$ RFSURFSTIJLT+(6PTE5GTIKHU

Overriding vs) overloading


Det s take a di""erent look at the "irst e&a#%le in this cha%ter. In the "ollowing %rogra#, the inter"ace o" the #ethod playA B is changed in the %rocess o" overriding it, which #eans that you haven t overridden the #ethod, but instead overloaded it. The co#%iler allows you to overload #ethods so it gives no co#%laint. But the behavior is %robably not what you want. (ere s the e&a#%le=

//3 c'*3\in!Error.Hava // 0cci!entally changing the interface. class &ote9 @ "ublic static final int J$DDLEbC ? ', Cb%M05P ? (, CbLL0T ? A

<

class $nstru#ent9 @ "ublic voi! "lay-int &ote9. @ %yste#.out."rintln-8$nstru#ent9."lay-.8.< A A class \in!9 e6ten!s $nstru#ent9 @ // GGP%4 Changes the #etho! interface3 "ublic voi! "lay-&ote9 n. @ %yste#.out."rintln-8\in!9."lay-&ote9 n.8.< A A "ublic class \in!Error @ "ublic static voi! tune-$nstru#ent9 i. @ // ... i."lay-&ote9.J$DDLEbC.<

Cha ter 8! Pol)mor hism

335

A "ublic static voi! #ain-%tringNO args. @ \in!9 flute ? ne: \in!9-.< tune-flute.< // &ot the !esire! behavior4 A A ///3>
There s another con"using as%ect thrown in here. In Instr*mentX, the playA B #ethod takes an int that has the identi"ier /oteX. That is, even though /oteX is a class na#e, it can also be used as an identi"ier without co#%laint. But in 0in'X, playA B takes a /oteX re"erence that has an identi"ier n! *6lthough you could even say playA/oteX /oteXB without an error., Thus it a%%ears that the %rogra##er intended to override play A B but #isty%ed the #ethod a bit. The co#%iler, however, assu#ed that an overload and not an override was intended. Cote that i" you "ollow the standard Java na#ing convention, the argu#ent identi"ier would be noteX *lowercase [n ,, which would distinguish it "ro# the class na#e. RF SURFSTIJLT+(6PTE5GTIK3U In t*ne, the Instr*mentX i is sent the playA B #essage, with one o" /oteX s #e#bers * 1I +&X-, as an argu#ent. Since /oteX contains int de"initions, this #eans that the int version o" the now' overloaded playA B #ethod is called, and since that has not been overridden the base'class version is used. RFSURF STIJLT+(6PTE5GTIKGU The out%ut is=

$nstru#ent9."lay-.
This certainly doesn t a%%ear to be a %oly#or%hic #ethod call. )nce you understand what s ha%%ening, you can "i& the %roble# "airly easily, but i#agine how di""icult it #ight be to "ind the bug i" it s buried in a %rogra# o" signi"icant si1e. RFSURFSTIJLT+(6PTE5GTIKIU

337

itfall: JoverridingK .rivate methods


The distinction between overriding and overloading described in the %revious section also a%%ears when you think you are overriding a %rivate #ethod in a derived class. (ere s so#ething you #ight innocently try to do= //3 c'*3PrivateGverri!e.Hava // 0bstract classes an! #etho!s. "ublic class PrivateGverri!e @ "rivate voi! f-. @ %yste#.out."rintln-8"rivate f-.8.< A "ublic static voi! #ain-%tring argsNO. @ PrivateGverri!e "o ? ne: Derive!-.< "o.f-.< A A class Derive! e6ten!s PrivateGverri!e @ "ublic voi! f-. @ %yste#.out."rintln-8"ublic f-.8.< A A ///3> /ou #ight reasonably e&%ect the out%ut to be !p*blic fA B$, but a private #ethod is auto#atically "inal, and is also hidden "ro# the derived class. So erive' s fA B in this case is a brand new #ethod Y it s not even overloaded since the base'class version o" fA B isn t visible in erive'. The result o" this is that only non'private #ethods #ay be overriden, but you should watch out "or the a%%earance o" overriding private #ethods, which generates no co#%iler warnings but doesn t do what you #ight e&%ect. To be clear, you should use a di""erent na#e "ro# a private base' class #ethod in your derived class.

Cha ter 8! Pol)mor hism

338

Abstract classes and methods


In all the instru#ent e&a#%les, the #ethods in the base class Instr*ment were always !du##y$ #ethods. I" these #ethods are ever called, you ve done so#ething wrong. That s because the intent o" Instr*ment is to create a common inter$ace "or all the classes derived "ro# it. RFSURFSTIJLT+(6PTE5GTIK2U The only reason to establish this co##on inter"ace is so it can be e&%ressed di""erently "or each di""erent subty%e. It establishes a basic "or#, so you can say what s in co##on with all the derived classes. 6nother way o" saying this is to call Instr*ment an abstract base class *or si#%ly an abstract class,. /ou create an abstract class when you want to #ani%ulate a set o" classes through this co##on inter"ace. 6ll derived' class #ethods that #atch the signature o" the base'class declaration will be called using the dyna#ic binding #echanis#. *(owever, as seen in the last section, i" the #ethod s na#e is the sa#e as the base class but the argu#ents are di""erent, you ve got overloading, which %robably isn t what you want., RFSURFSTIJLT+(6PTE5GTIL@U I" you have an abstract class like Instr*ment, ob0ects o" that class al#ost always have no #eaning. That is, Instr*ment is #eant to e&%ress only the inter"ace, and not a %articular i#%le#entation, so creating an Instr*ment ob0ect #akes no sense, and you ll %robably want to %revent the user "ro# doing it. This can be acco#%lished by #aking all the #ethods in Instr*ment %rint error #essages, but that delays the in"or#ation until run'ti#e and reAuires reliable e&haustive testing on the user s %art. It s always better to catch %roble#s at co#%ile'ti#e. RFSURF STIJLT+(6PTE5GTILMU Java %rovides a #echanis# "or doing this called the abstract method@. This is a #ethod that is inco#%lete; it has only a declaration and no #ethod body. (ere is the synta& "or an abstract #ethod declaration=

abstract voi! f-.<


@ Eor +<< %rogra##ers, this is the analogue o" +<< s ure virtual $unction.

33:

6 class containing abstract #ethods is called an abstract class. I" a class contains one or #ore abstract #ethods, the class #ust be Auali"ied as abstract. *)therwise, the co#%iler gives you an error #essage., RFSURF STIJLT+(6PTE5GTILKU I" an abstract class is inco#%lete, what is the co#%iler su%%osed to do when so#eone tries to #ake an ob0ect o" that classO It cannot sa"ely create an ob0ect o" an abstract class, so you get an error #essage "ro# the co#%iler. This way the co#%iler ensures the %urity o" the abstract class, and you don t need to worry about #isusing it. RFSURF STIJLT+(6PTE5GTILLU I" you inherit "ro# an abstract class and you want to #ake ob0ects o" the new ty%e, you #ust %rovide #ethod de"initions "or all the abstract #ethods in the base class. I" you don t *and you #ay choose not to,, then the derived class is also abstract and the co#%iler will "orce you to Auali"y that class with the abstract keyword. RFSURFSTIJLT+(6PTE5GTIL?U It s %ossible to create a class as abstract without including any abstract #ethods. This is use"ul when you ve got a class in which it doesn t #ake sense to have any abstract #ethods, and yet you want to %revent any instances o" that class. RFSURFSTIJLT+(6PTE5GTILHU The Instr*ment class can easily be turned into an abstract class. )nly so#e o" the #ethods will be abstract, since #aking a class abstract doesn t "orce you to #ake all the #ethods abstract. (ere s what it looks like=

Cha ter 8! Pol)mor hism

33;

abstract Instrument abstract void .la:89M 1tring what89 N DO ))) OD P abstract void ad3ust89M

e0tends Wind void .la:89 1tring what89 void ad3ust89

e0tends ercussion void .la:89 1tring what89 void ad3ust89

e0tends 1tringed void .la:89 1tring what89 void ad3ust89

e0tends Woodwind void .la:89 1tring what89

e0tends ;rass void .la:89 void ad3ust89

(ere s the orchestra e&a#%le #odi"ied to use abstract classes and #ethods=

//3 c'*3#usicI3JusicI.Hava // 0bstract classes an! #etho!s. i#"ort Hava.util.B< abstract class $nstru#ent @ int i< // storage allocate! for each "ublic abstract voi! "lay-.< "ublic %tring :hat-. @ return 8$nstru#ent8< A "ublic abstract voi! a!Hust-.< A class \in! e6ten!s $nstru#ent @

34=

"ublic voi! "lay-. @ %yste#.out."rintln-8\in!."lay-.8.< A "ublic %tring :hat-. @ return 8\in!8< A "ublic voi! a!Hust-. @A A class Percussion e6ten!s $nstru#ent @ "ublic voi! "lay-. @ %yste#.out."rintln-8Percussion."lay-.8.< A "ublic %tring :hat-. @ return 8Percussion8< A "ublic voi! a!Hust-. @A A class %tringe! e6ten!s $nstru#ent @ "ublic voi! "lay-. @ %yste#.out."rintln-8%tringe!."lay-.8.< A "ublic %tring :hat-. @ return 8%tringe!8< A "ublic voi! a!Hust-. @A A class Brass e6ten!s \in! @ "ublic voi! "lay-. @ %yste#.out."rintln-8Brass."lay-.8.< A "ublic voi! a!Hust-. @ %yste#.out."rintln-8Brass.a!Hust-.8.< A A class \oo!:in! e6ten!s \in! @ "ublic voi! "lay-. @ %yste#.out."rintln-8\oo!:in!."lay-.8.< A "ublic %tring :hat-. @ return 8\oo!:in!8< A A "ublic class JusicI @ // Doesn2t care about ty"e, so ne: ty"es

Cha ter 8! Pol)mor hism

341

// a!!e! to the syste# still :ork right3 static voi! tune-$nstru#ent i. @ // ... i."lay-.< A static voi! tune0ll-$nstru#entNO e. @ for-int i ? '< i P e.length< iKK. tune-eNiO.< A "ublic static voi! #ain-%tringNO args. @ $nstru#entNO orchestra ? ne: $nstru#entN,O< int i ? '< // Y"casting !uring a!!ition to the array3 orchestraNiKKO ? ne: \in!-.< orchestraNiKKO ? ne: Percussion-.< orchestraNiKKO ? ne: %tringe!-.< orchestraNiKKO ? ne: Brass-.< orchestraNiKKO ? ne: \oo!:in!-.< tune0ll-orchestra.< A A ///3>
/ou can see that there s really no change e&ce%t in the base class. RFSURF STIJLT+(6PTE5GTIL3U It s hel%"ul to create abstract classes and #ethods because they #ake the abstractness o" a class e&%licit, and tell both the user and the co#%iler how it was intended to be used. RFSURFSTIJLT+(6PTE5GTILGU

Constructors and .ol:mor.hism


6s usual, constructors are di""erent "ro# other kinds o" #ethods. This is also true when %oly#or%his# is involved. Even though constructors are not %oly#or%hic *although you can have a kind o" !virtual constructor,$ as you will see in +ha%ter MK,, it s i#%ortant to understand the way constructors work in co#%le& hierarchies and with %oly#or%his#. This

342

understanding will hel% you avoid un%leasant entangle#ents. RFSURF STIJLT+(6PTE5GTILIU

Order of constructor calls


The order o" constructor calls was brie"ly discussed in +ha%ter ? and again in +ha%ter 3, but that was be"ore %oly#or%his# was introduced. RFSURFSTIJLT+(6PTE5GTIL2U 6 constructor "or the base class is always called in the constructor "or a derived class, chaining u% the inheritance hierarchy so that a constructor "or every base class is called. This #akes sense because the constructor has a s%ecial 0ob= to see that the ob0ect is built %ro%erly. 6 derived class has access to its own #e#bers only, and not to those o" the base class *whose #e#bers are ty%ically private,. )nly the base'class constructor has the %ro%er knowledge and access to initiali1e its own ele#ents. There"ore, it s essential that all constructors get called, otherwise the entire ob0ect wouldn t be constructed. That s why the co#%iler en"orces a constructor call "or every %ortion o" a derived class. It will silently call the de"ault constructor i" you don t e&%licitly call a base'class constructor in the derived'class constructor body. I" there is no de"ault constructor, the co#%iler will co#%lain. *In the case where a class has no constructors, the co#%iler will auto#atically synthesi1e a de"ault constructor., RFSURF STIJLT+(6PTE5GTI?@U Det s take a look at an e&a#%le that shows the e""ects o" co#%osition, inheritance, and %oly#or%his# on the order o" construction=

//3 c'*3%an!:ich.Hava // Gr!er of constructor calls. class Jeal @ Jeal-. @ %yste#.out."rintln-8Jeal-.8.< A A class Brea! @ Brea!-. @ %yste#.out."rintln-8Brea!-.8.< A A class Cheese @

Cha ter 8! Pol)mor hism

343

Cheese-. @ %yste#.out."rintln-8Cheese-.8.< A A class Lettuce @ Lettuce-. @ %yste#.out."rintln-8Lettuce-.8.< A A class Lunch e6ten!s Jeal @ Lunch-. @ %yste#.out."rintln-8Lunch-.8.<A A class PortableLunch e6ten!s Lunch @ PortableLunch-. @ %yste#.out."rintln-8PortableLunch-.8.< A A "ublic class %an!:ich e6ten!s PortableLunch @ Brea! b ? ne: Brea!-.< Cheese c ? ne: Cheese-.< Lettuce l ? ne: Lettuce-.< %an!:ich-. @ %yste#.out."rintln-8%an!:ich-.8.< A "ublic static voi! #ain-%tringNO args. @ ne: %an!:ich-.< A A ///3>
This e&a#%le creates a co#%le& class out o" other classes, and each class has a constructor that announces itsel". The i#%ortant class is )an'(ich, which re"lects three levels o" inheritance *"our, i" you count the i#%licit inheritance "ro# .b8ect, and three #e#ber ob0ects. :hen a )an'(ich ob0ect is created in mainA B, the out%ut is=

Jeal-. Lunch-. PortableLunch-. Brea!-. Cheese-. Lettuce-.

344

%an!:ich-.
This #eans that the order o" constructor calls "or a co#%le& ob0ect is as "ollows= RFSURFSTIJLT+(6PTE5GTI?MU

,7)

The base'class constructor is called. This ste% is re%eated recursively such that the root o" the hierarchy is constructed "irst, "ollowed by the ne&t'derived class, etc., until the #ost'derived class is reached. RFSURFSTIJLT+(6PTE5GTI?KU Me#ber initiali1ers are called in the order o" declaration. RFSURF STIJLT+(6PTE5GTI?LU The body o" the derived'class constructor is called. RFSURF STIJLT+(6PTE5GTI??U

,() ,!)

The order o" the constructor calls is i#%ortant. :hen you inherit, you know all about the base class and can access any p*blic and protecte' #e#bers o" the base class. This #eans that you #ust be able to assu#e that all the #e#bers o" the base class are valid when you re in the derived class. In a nor#al #ethod, construction has already taken %lace, so all the #e#bers o" all %arts o" the ob0ect have been built. Inside the constructor, however, you #ust be able to assu#e that all #e#bers that you use have been built. The only way to guarantee this is "or the base'class constructor to be called "irst. Then when you re in the derived'class constructor, all the #e#bers you can access in the base class have been initiali1ed. !>nowing that all #e#bers are valid$ inside the constructor is also the reason that, whenever %ossible, you should initiali1e all #e#ber ob0ects *that is, ob0ects %laced in the class using co#%osition, at their %oint o" de"inition in the class *e.g., b, c, and l in the e&a#%le above,. I" you "ollow this %ractice, you will hel% ensure that all base class #e#bers and #e#ber ob0ects o" the current ob0ect have been initiali1ed. 4n"ortunately, this doesn t handle every case, as you will see in the ne&t section. RFSURF STIJLT+(6PTE5GTI?HU

Inheritance and !inali0e1 2


:hen you use co#%osition to create a new class, you never worry about "inali1ing the #e#ber ob0ects o" that class. Each #e#ber is an inde%endent ob0ect, and thus is garbage collected and "inali1ed regardless

Cha ter 8! Pol)mor hism

345

o" whether it ha%%ens to be a #e#ber o" your class. :ith inheritance, however, you #ust override finali7eA B in the derived class i" you have any s%ecial cleanu% that #ust ha%%en as %art o" garbage collection. :hen you override finali7eA B in an inherited class, it s i#%ortant to re#e#ber to call the base'class version o" finali7eA B, since otherwise the base'class "inali1ation will not ha%%en. The "ollowing e&a#%le %roves this=

//3 c'*3Lrog.Hava // Testing finaliUe :ith inheritance. class DoBaseLinaliUation @ "ublic static boolean flag ? false< A class Characteristic @ %tring s< Characteristic-%tring c. @ s ? c< %yste#.out."rintln8Creating Characteristic 8 K s.< A "rotecte! voi! finaliUe-. @ %yste#.out."rintln8finaliUing Characteristic 8 K s.< A A class LivingCreature @ Characteristic " ? ne: Characteristic-8is alive8.< LivingCreature-. @ %yste#.out."rintln-8LivingCreature-.8.< A "rotecte! voi! finaliUe-. thro:s Thro:able @ %yste#.out."rintln8LivingCreature finaliUe8.< // Call base-class version L0%T4 if-DoBaseLinaliUation.flag. su"er.finaliUe-.< A A

347

class 0ni#al e6ten!s LivingCreature @ Characteristic " ? ne: Characteristic-8has heart8.< 0ni#al-. @ %yste#.out."rintln-80ni#al-.8.< A "rotecte! voi! finaliUe-. thro:s Thro:able @ %yste#.out."rintln-80ni#al finaliUe8.< if-DoBaseLinaliUation.flag. su"er.finaliUe-.< A A class 0#"hibian e6ten!s 0ni#al @ Characteristic " ? ne: Characteristic-8can live in :ater8.< 0#"hibian-. @ %yste#.out."rintln-80#"hibian-.8.< A "rotecte! voi! finaliUe-. thro:s Thro:able @ %yste#.out."rintln-80#"hibian finaliUe8.< if-DoBaseLinaliUation.flag. su"er.finaliUe-.< A A "ublic class Lrog e6ten!s 0#"hibian @ Lrog-. @ %yste#.out."rintln-8Lrog-.8.< A "rotecte! voi! finaliUe-. thro:s Thro:able @ %yste#.out."rintln-8Lrog finaliUe8.< if-DoBaseLinaliUation.flag. su"er.finaliUe-.< A "ublic static voi! #ain-%tringNO args. @ if-args.length 4? ' DD argsN'O.e=uals-8finaliUe8.. DoBaseLinaliUation.flag ? true< else

Cha ter 8! Pol)mor hism

348

%yste#.out."rintln-8&ot finaliUing bases8.< ne: Lrog-.< // $nstantly beco#es garbage %yste#.out."rintln-8Bye48.< // Lorce finaliUers to be calle!3 %yste#.gc-.< A A ///3>
The class o2aseFinali7ation si#%ly holds a "lag that indicates to each class in the hierarchy whether to call s*per!finali7eA B. This "lag is set based on a co##and'line argu#ent, so you can view the behavior with and without base'class "inali1ation. RFSURFSTIJLT+(6PTE5GTI?3U Each class in the hierarchy also contains a #e#ber ob0ect o" class -haracteristic. /ou will see that regardless o" whether the base class "inali1ers are called, the -haracteristic #e#ber ob0ects are always "inali1ed. RFSURFSTIJLT+(6PTE5GTI?GU Each overridden finali7eA B #ust have access to at least protecte' #e#bers since the finali7eA B #ethod in class .b8ect is protecte' and the co#%iler will not allow you to reduce the access during inheritance. *! Eriendly$ is less accessible than protecte'., N5WON5

WTIJJX-HA#T&$ZXIQYO
In Frog!mainA B, the o2aseFinali7ation "lag is con"igured and a single Frog ob0ect is created. 5e#e#ber that garbage collection9and in %articular "inali1ation9#ight not ha%%en "or any %articular ob0ect, so to en"orce this, the call to )ystem!gcA B triggers garbage collection, and thus "inali1ation. :ithout base'class "inali1ation, the out%ut is=

&ot finaliUing bases Creating Characteristic is alive LivingCreature-. Creating Characteristic has heart 0ni#al-. Creating Characteristic can live in :ater 0#"hibian-. Lrog-. Bye4 Lrog finaliUe finaliUing Characteristic is alive

34:

finaliUing Characteristic has heart finaliUing Characteristic can live in :ater


/ou can see that, indeed, no "inali1ers are called "or the base classes o"

Frog *the #e#ber ob0ects are "inali1ed, as you would e&%ect,. But i" you
add the !"inali1e$ argu#ent on the co##and line, you get=

Creating Characteristic is alive LivingCreature-. Creating Characteristic has heart 0ni#al-. Creating Characteristic can live in :ater 0#"hibian-. Lrog-. bye4 Lrog finaliUe 0#"hibian finaliUe 0ni#al finaliUe LivingCreature finaliUe finaliUing Characteristic is alive finaliUing Characteristic has heart finaliUing Characteristic can live in :ater
6lthough the order the #e#ber ob0ects are "inali1ed is the sa#e order that they are created, technically the order o" "inali1ation o" ob0ects is uns%eci"ied. :ith base classes, however, you have control over the order o" "inali1ation. The best order to use is the one that s shown here, which is the reverse o" the order o" initiali1ation. Eollowing the "or# that s used in +<< "or destructors, you should %er"or# the derived'class "inali1ation "irst, then the base'class "inali1ation. That s because the derived'class "inali1ation could call so#e #ethods in the base class that reAuire that the base'class co#%onents are still alive, so you #ust not destroy the# %re#aturely. RFSURFSTIJLT+(6PTE5GTI?2U

;ehavior of .ol:mor.hic methods inside constructors


The hierarchy o" constructor calls brings u% an interesting dile##a. :hat ha%%ens i" you re inside a constructor and you call a dyna#ically bound #ethod o" the ob0ect being constructedO Inside an ordinary

Cha ter 8! Pol)mor hism

34;

#ethod you can i#agine what will ha%%en9the dyna#ically bound call is resolved at run'ti#e because the ob0ect cannot know whether it belongs to the class that the #ethod is in or so#e class derived "ro# it. Eor consistency, you #ight think this is what should ha%%en inside constructors. RFSURFSTIJLT+(6PTE5GTIH@U This is not e&actly the case. I" you call a dyna#ically bound #ethod inside a constructor, the overridden de"inition "or that #ethod is used. (owever, the e$$ect can be rather une&%ected, and can conceal so#e di""icult'to'"ind bugs. RFSURFSTIJLT+(6PTE5GTIHMU +once%tually, the constructor s 0ob is to bring the ob0ect into e&istence *which is hardly an ordinary "eat,. Inside any constructor, the entire ob0ect #ight be only %artially "or#ed9you can know only that the base' class ob0ects have been initiali1ed, but you cannot know which classes are inherited "ro# you. 6 dyna#ically bound #ethod call, however, reaches !outward$ into the inheritance hierarchy. It calls a #ethod in a derived class. I" you do this inside a constructor, you call a #ethod that #ight #ani%ulate #e#bers that haven t been initiali1ed yet9a sure reci%e "or disaster. RFSURFSTIJLT+(6PTE5GTIHKU /ou can see the %roble# in the "ollowing e&a#%le=

//3 c'*3PolyConstructors.Hava // Constructors an! "oly#or"his# // !on2t "ro!uce :hat you #ight e6"ect. abstract class aly"h @ abstract voi! !ra:-.< aly"h-. @ %yste#.out."rintln-8aly"h-. before !ra:-.8.< !ra:-.< %yste#.out."rintln-8aly"h-. after !ra:-.8.< A A class 5oun!aly"h e6ten!s aly"h @ int ra!ius ? (< 5oun!aly"h-int r. @ ra!ius ? r< %yste#.out."rintln-

35=

85oun!aly"h.5oun!aly"h-., ra!ius ? 8 K ra!ius.< A voi! !ra:-. @ %yste#.out."rintln85oun!aly"h.!ra:-., ra!ius ? 8 K ra!ius.< A A "ublic class PolyConstructors @ "ublic static voi! #ain-%tringNO args. @ ne: 5oun!aly"h-,.< A A ///3>
In "lyph, the 'ra(A B #ethod is abstract, so it is designed to be overridden. Indeed, you are "orced to override it in $o*n'"lyph. But the "lyph constructor calls this #ethod, and the call ends u% in $o*n'"lyph!'ra(A B, which would see# to be the intent. But look at the out%ut=

aly"h-. before !ra:-. 5oun!aly"h.!ra:-., ra!ius ? ' aly"h-. after !ra:-. 5oun!aly"h.5oun!aly"h-., ra!ius ? ,
:hen "lyph s constructor calls 'ra(A B, the value o" ra'i*s isn t even the de"ault initial value M. It s @. This would %robably result in either a dot or nothing at all being drawn on the screen, and you d be le"t staring, trying to "igure out why the %rogra# won t work. RFSURF STIJLT+(6PTE5GTIHLU The order o" initiali1ation described in the %revious section isn t Auite co#%lete, and that s the key to solving the #ystery. The actual %rocess o" initiali1ation is=

,*) ,+)

The storage allocated "or the ob0ect is initiali1ed to binary 1ero be"ore anything else ha%%ens. RFSURFSTIJLT+(6PTE5GTIH?U The base'class constructors are called as described %reviously. 6t this %oint, the overridden 'ra(A B #ethod is called *yes, be$ore

Cha ter 8! Pol)mor hism

351

the $o*n'"lyph constructor is called,, which discovers a ra'i*s value o" 1ero, due to ste% M. RFSURFSTIJLT+(6PTE5GTIHHU

,,) ,-)

Me#ber initiali1ers are called in the order o" declaration. RFSURF STIJLT+(6PTE5GTIH3U The body o" the derived'class constructor is called. RFSURF STIJLT+(6PTE5GTIHGU

There s an u%side to this, which is that everything is at least initiali1ed to 1ero *or whatever 1ero #eans "or that %articular data ty%e, and not 0ust le"t as garbage. This includes ob0ect re"erences that are e#bedded inside a class via co#%osition, which beco#e n*ll. So i" you "orget to initiali1e that re"erence you ll get an e&ce%tion at run'ti#e. Everything else gets 1ero, which is usually a telltale value when looking at out%ut. RFSURF STIJLT+(6PTE5GTIHIU )n the other hand, you should be %retty horri"ied at the outco#e o" this %rogra#. /ou ve done a %er"ectly logical thing, and yet the behavior is #ysteriously wrong, with no co#%laints "ro# the co#%iler. *+<< %roduces #ore rational behavior in this situation., Bugs like this could easily be buried and take a long ti#e to discover. RFSURF STIJLT+(6PTE5GTIH2U 6s a result, a good guideline "or constructors is, !7o as little as %ossible to set the ob0ect into a good state, and i" you can %ossibly avoid it, don t call any #ethods.$ The only sa"e #ethods to call inside a constructor are those that are final in the base class. *This also a%%lies to private #ethods, which are auto#atically final., These cannot be overridden and thus cannot %roduce this kind o" sur%rise. RFSURF STIJLT+(6PTE5GTI3@U

Designing with inheritance


)nce you learn about %oly#or%his#, it can see# that everything ought to be inherited because %oly#or%his# is such a clever tool. This can burden your designs; in "act i" you choose inheritance "irst when you re using an

352

e&isting class to #ake a new class, things can beco#e needlessly co#%licated. RFSURFSTIJLT+(6PTE5GTI3MU 6 better a%%roach is to choose co#%osition "irst, when it s not obvious which one you should use. +o#%osition does not "orce a design into an inheritance hierarchy. But co#%osition is also #ore "le&ible since it s %ossible to dyna#ically choose a ty%e *and thus behavior, when using co#%osition, whereas inheritance reAuires an e&act ty%e to be known at co#%ile'ti#e. The "ollowing e&a#%le illustrates this=

//3 c'*3Trans#ogrify.Hava // Dyna#ically changing the behavior of // an obHect via co#"osition. abstract class 0ctor @ abstract voi! act-.< A class Ma""y0ctor e6ten!s 0ctor @ "ublic voi! act-. @ %yste#.out."rintln-8Ma""y0ctor8.< A A class %a!0ctor e6ten!s 0ctor @ "ublic voi! act-. @ %yste#.out."rintln-8%a!0ctor8.< A A class %tage @ 0ctor a ? ne: Ma""y0ctor-.< voi! change-. @ a ? ne: %a!0ctor-.< A voi! go-. @ a.act-.< A A "ublic class Trans#ogrify @ "ublic static voi! #ain-%tringNO args. @ %tage s ? ne: %tage-.< s.go-.< // Prints 8Ma""y0ctor8 s.change-.<

Cha ter 8! Pol)mor hism

353

s.go-.< // Prints 8%a!0ctor8 A A ///3>


6 )tage ob0ect contains a re"erence to an Actor, which is initiali1ed to a HappyActor ob0ect. This #eans goA B %roduces a %articular behavior. But since a re"erence can be rebound to a di""erent ob0ect at run'ti#e, a re"erence "or a )a'Actor ob0ect can be substituted in a and then the behavior %roduced by goA B changes. Thus you gain dyna#ic "le&ibility at run'ti#e. *This is also called the State Pattern' See Thinking in Patterns ,ith Java, downloadable at ,,,'0ruceEckel'com', In contrast, you can t decide to inherit di""erently at run'ti#e; that #ust be co#%letely deter#ined at co#%ile'ti#e. RFSURFSTIJLT+(6PTE5GTI3KU 6 general guideline is !4se inheritance to e&%ress di""erences in behavior, and "ields to e&%ress variations in state.$ In the above e&a#%le, both are used= two di""erent classes are inherited to e&%ress the di""erence in the actA B #ethod, and )tage uses co#%osition to allow its state to be changed. In this case, that change in state ha%%ens to %roduce a change in behavior. RFSURFSTIJLT+(6PTE5GTI3LU

ure inheritance vs) e0tension


:hen studying inheritance, it would see# that the cleanest way to create an inheritance hierarchy is to take the !%ure$ a%%roach. That is, only #ethods that have been established in the base class or interface are to be overridden in the derived class, as seen in this diagra#=
Sha e draw89 erase89

$ircle draw89 erase89

S%uare draw89 erase89

&riangle draw89 erase89

354

This can be ter#ed a %ure !is'a$ relationshi% because the inter"ace o" a class establishes what it is. Inheritance guarantees that any derived class will have the inter"ace o" the base class and nothing less. I" you "ollow the above diagra#, derived classes will also have no more than the base class inter"ace. RFSURFSTIJLT+(6PTE5GTI3?U This can be thought o" as ure substitution, because derived class ob0ects can be %er"ectly substituted "or the base class, and you never need to know any e&tra in"or#ation about the subclasses when you re using the#=
#alks to 1ha.e BIs@aB relationshi. CircleH 1%uareH &ineH or new t:.e of 1ha.e

Message

That is, the base class can receive any #essage you can send to the derived class because the two have e&actly the sa#e inter"ace. 6ll you need to do is u%cast "ro# the derived class and never look back to see what e&act ty%e o" ob0ect you re dealing with. Everything is handled through %oly#or%his#. RFSURFSTIJLT+(6PTE5GTI3HU :hen you see it this way, it see#s like a %ure !is'a$ relationshi% is the only sensible way to do things, and any other design indicates #uddled thinking and is by de"inition broken. This too is a tra%. 6s soon as you start thinking this way, you ll turn around and discover that e&tending the inter"ace *which, un"ortunately, the keyword e4ten's see#s to encourage, is the %er"ect solution to a %articular %roble#. This could be ter#ed an !is'like'a$ relationshi% because the derived class is like the base class9it has the sa#e "unda#ental inter"ace9but it has other "eatures that reAuire additional #ethods to i#%le#ent=

Cha ter 8! Pol)mor hism

355

Cseful void f89 void g89

Assume this re.resents a big interface

MoreCseful void void void void void f89 g89 u89 v89 w89

BIs@like@aB

/0tending the interface

:hile this is also a use"ul and sensible a%%roach *de%ending on the situation, it has a drawback. The e&tended %art o" the inter"ace in the derived class is not available "ro# the base class, so once you u%cast you can t call the new #ethods=
#alks to Cseful ob3ect Cseful .art MoreCseful .art

Message

I" you re not u%casting in this case, it won t bother you, but o"ten you ll get into a situation in which you need to rediscover the e&act ty%e o" the ob0ect so you can access the e&tended #ethods o" that ty%e. The "ollowing section shows how this is done. RFSURFSTIJLT+(6PTE5GTI33U

Downcasting and run@time t:.e identification


Since you lose the s%eci"ic ty%e in"or#ation via an u cast *#oving u% the inheritance hierarchy,, it #akes sense that to retrieve the ty%e in"or#ation9that is, to #ove back down the inheritance hierarchy9you use a do,ncast. (owever, you know an u%cast is always sa"e; the base

357

class cannot have a bigger inter"ace than the derived class, there"ore every #essage you send through the base class inter"ace is guaranteed to be acce%ted. But with a downcast, you don t really know that a sha%e *"or e&a#%le, is actually a circle. It could instead be a triangle or sAuare or so#e other ty%e. RFSURFSTIJLT+(6PTE5GTI3GU
Cseful void f89 void g89

Assume this re.resents a big interface

MoreCseful void f89 void g89 void u89 void v89 void w89

BIs@like@aB

/0tending the interface

To solve this %roble# there #ust be so#e way to guarantee that a downcast is correct, so you won t accidentally cast to the wrong ty%e and then send a #essage that the ob0ect can t acce%t. This would be Auite unsa"e. RFSURFSTIJLT+(6PTE5GTI3IU In so#e languages *like +<<, you #ust %er"or# a s%ecial o%eration in order to get a ty%e'sa"e downcast, but in Java ever) cast is checked. So even though it looks like you re 0ust %er"or#ing an ordinary %arenthesi1ed cast, at run'ti#e this cast is checked to ensure that it is in "act the ty%e you think it is. I" it isn t, you get a -lass-ast&4ception. This act o" checking ty%es at run'ti#e is called run/time t) e identi$ication *5TTI,. The "ollowing e&a#%le de#onstrates the behavior o" 5TTI=

//3 c'*35TT$.Hava // Do:ncasting D 5un-ti#e Ty"e // $!entification -5TT$.. i#"ort Hava.util.B< class Yseful @

Cha ter 8! Pol)mor hism

358

"ublic voi! f-. @A "ublic voi! g-. @A A class JoreYseful e6ten!s Yseful @ "ublic voi! f-. @A "ublic voi! g-. @A "ublic voi! u-. @A "ublic voi! v-. @A "ublic voi! :-. @A A "ublic class 5TT$ @ "ublic static voi! #ain-%tringNO args. @ YsefulNO 6 ? @ ne: Yseful-., ne: JoreYseful-. A< 6N'O.f-.< 6N(O.g-.< // Co#"ile-ti#e3 #etho! not foun! in Yseful3 //4 6N(O.u-.< --JoreYseful.6N(O..u-.< // Do:ncast/5TT$ --JoreYseful.6N'O..u-.< // E6ce"tion thro:n A A ///3>
6s in the diagra#, 1oreUsef*l e&tends the inter"ace o" Usef*l. But since it s inherited, it can also be u%cast to a Usef*l. /ou can see this ha%%ening in the initiali1ation o" the array 4 in mainA B. Since both ob0ects in the array are o" class Usef*l, you can send the fA B and gA B #ethods to both, and i" you try to call *A B *which e&ists only in 1oreUsef*l, you ll get a co#%ile'ti#e error #essage. RFSURF STIJLT+(6PTE5GTI32U I" you want to access the e&tended inter"ace o" a 1oreUsef*l ob0ect, you can try to downcast. I" it s the correct ty%e, it will be success"ul. )therwise, you ll get a -lass-ast&4ception. /ou don t need to write any s%ecial code "or this e&ce%tion, since it indicates a %rogra##er error that could ha%%en anywhere in a %rogra#. RFSURF STIJLT+(6PTE5GTIG@U

35:

There s #ore to 5TTI than a si#%le cast. Eor e&a#%le, there s a way to see what ty%e you re dealing with be$ore you try to downcast it. 6ll o" +ha%ter MK is devoted to the study o" di""erent as%ects o" Java run'ti#e ty%e identi"ication. RFSURFSTIJLT+(6PTE5GTIGMU

1ummar:
Poly#or%his# #eans !di""erent "or#s.$ In ob0ect'oriented %rogra##ing, you have the sa#e "ace *the co##on inter"ace in the base class, and di""erent "or#s using that "ace= the di""erent versions o" the dyna#ically bound #ethods. RFSURFSTIJLT+(6PTE5GTIGKU /ou ve seen in this cha%ter that it s i#%ossible to understand, or even create, an e&a#%le o" %oly#or%his# without using data abstraction and inheritance. Poly#or%his# is a "eature that cannot be viewed in isolation *like a s(itch state#ent can, "or e&a#%le,, but instead works only in concert, as %art o" a !big %icture$ o" class relationshi%s. Peo%le are o"ten con"used by other, non'ob0ect'oriented "eatures o" Java, like #ethod overloading, which are so#eti#es %resented as ob0ect'oriented. 7on t be "ooled= I" it isn t late binding, it isn t %oly#or%his#. RFSURF STIJLT+(6PTE5GTIGLU To use %oly#or%his#9and thus ob0ect'oriented techniAues9e""ectively in your %rogra#s you #ust e&%and your view o" %rogra##ing to include not 0ust #e#bers and #essages o" an individual class, but also the co##onality a#ong classes and their relationshi%s with each other. 6lthough this reAuires signi"icant e""ort, it s a worthy struggle, because the results are "aster %rogra# develo%#ent, better code organi1ation, e&tensible %rogra#s, and easier code #aintenance. RFSURF STIJLT+(6PTE5GTIG?U

/0ercises
Solutions to selected e&ercises can be "ound in the electronic docu#entThe Thinking in Java "nnotated Solution @uide, available "or a s#all "ee "ro# ,,,'0ruceEckel'com.

57) 6dd a new #ethod in the base class o" )hapes!8ava that %rints a
#essage, but don t override it in the derived classes. E&%lain what

Cha ter 8! Pol)mor hism

35;

ha%%ens. Cow override it in one o" the derived classes but not the others, and see what ha%%ens. Einally, override it in all the derived classes. RFSURFSTIJLT+(6PTE5GTIGHU

5() 6dd a new ty%e o" )hape to )hapes!8ava and veri"y in mainA B
that %oly#or%his# works "or your new ty%e as it does in the old ty%es. RFSURFSTIJLT+(6PTE5GTIG3U

5!) +hange 1*sicJ!8ava so that (hatA B beco#es the root .b8ect


#ethod to)tringA B. Try %rinting the Instr*ment ob0ects using )ystem!o*t!printlnA B *without any casting,. RFSURF STIJLT+(6PTE5GTIGGU

5*) 6dd a new ty%e o" Instr*ment to 1*sicJ!8ava and veri"y that
%oly#or%his# works "or your new ty%e. RFSURF STIJLT+(6PTE5GTIGIU

5+) Modi"y 1*sicJ!8ava so that it rando#ly creates Instr*ment


ob0ects the way )hapes!8ava does. RFSURF STIJLT+(6PTE5GTIG2U

5,) +reate an inheritance hierarchy o" $o'ent= 1o*se, "erbil,


Hamster, etc. In the base class, %rovide #ethods that are co##on to all $o'ents, and override these in the derived classes
to %er"or# di""erent behaviors de%ending on the s%eci"ic ty%e o" $o'ent. +reate an array o" $o'ent, "ill it with di""erent s%eci"ic ty%es o" $o'ents, and call your base'class #ethods to see what ha%%ens. RFSURFSTIJLT+(6PTE5GTII@U

5-) Modi"y E&ercise 3 so that $o'ent is an abstract class. Make the


#ethods o" $o'ent abstract whenever %ossible. RFSURF STIJLT+(6PTE5GTIIMU

54) +reate a class as abstract without including any abstract


#ethods, and veri"y that you cannot create any instances o" that class. RFSURFSTIJLT+(6PTE5GTIIKU

55) 6dd class #ickle to )an'(ich!8ava. RFSURF


STIJLT+(6PTE5GTIILU

37=

56) Modi"y E&ercise 3 so that it de#onstrates the order o"


initiali1ation o" the base classes and derived classes. Cow add #e#ber ob0ects to both the base and derived classes, and show the order in which their initiali1ation occurs during construction. RFSURFSTIJLT+(6PTE5GTII?U

67) +reate a L'level inheritance hierarchy. Each class in the hierarchy


should have a finali7eA B #ethod, and it should %ro%erly call the base'class version o" finali7eA B. 7e#onstrate that your hierarchy works %ro%erly. RFSURFSTIJLT+(6PTE5GTIIHU

6() +reate a base class with two #ethods. In the "irst #ethod, call
the second #ethod. Inherit a class and override the second #ethod. +reate an ob0ect o" the derived class, u%cast it to the base ty%e, and call the "irst #ethod. E&%lain what ha%%ens. RFSURF STIJLT+(6PTE5GTII3U

6!) +reate a base class with an abstract printA B #ethod that is


overridden in a derived class. The overridden version o" the #ethod %rints the value o" an int variable de"ined in the derived class. 6t the %oint o" de"inition o" this variable, give it a non1ero value. In the base'class constructor, call this #ethod. In mainA B, create an ob0ect o" the derived ty%e, and then call its printA B #ethod. E&%lain the results. RFSURFSTIJLT+(6PTE5GTIIGU

6*) Eollowing the e&a#%le in Transmogrify!8ava, create a


)tarship class containing an Alert)tat*s re"erence that can
indicate three di""erent states. Include #ethods to change the states. RFSURFSTIJLT+(6PTE5GTIIIU

6+) +reate an abstract class with no #ethods. 7erive a class and


add a #ethod. +reate a static #ethod that takes a re"erence to the base class, downcasts it to the derived class, and calls the #ethod. In mainA B, de#onstrate that it works. Cow %ut the abstract declaration "or the #ethod in the base class, thus eli#inating the need "or the downcast. RFSU

Cha ter 8! Pol)mor hism

371

5: Interfaces L Inner Classes


RFSTIJLT+(6PTE5ITI@UInter"aces and inner classes %rovide #ore so%histicated ways to organi1e and control the ob0ects in your syste#.
+<<, "or e&a#%le, does not contain such #echanis#s, although the clever %rogra##er #ay si#ulate the#. The "act that they e&ist in Java indicates that they were considered i#%ortant enough to %rovide direct su%%ort through language keywords. RFSURFSTIJLT+(6PTE5ITIMU In +ha%ter G, you learned about the abstract keyword, which allows you to create one or #ore #ethods in a class that have no de"initions9you %rovide %art o" the inter"ace without %roviding a corres%onding i#%le#entation, which is created by inheritors. The interface keyword %roduces a co#%letely abstract class, one that %rovides no i#%le#entation at all. /ou ll learn that the interface is #ore than 0ust an abstract class taken to the e&tre#e, since it allows you to %er"or# a variation on +<< s !#ulti%le inheritance,$ by creating a class that can be u%cast to #ore than one base ty%e. RFSURFSTIJLT+(6PTE5ITIKU 6t "irst, inner classes look like a si#%le code'hiding #echanis#= you %lace classes inside other classes. /ou ll learn, however, that the inner class does #ore than that9it knows about and can co##unicate with the surrounding class9and that the kind o" code you can write with inner classes is #ore elegant and clear, although it is a new conce%t to #ost. It takes so#e ti#e to beco#e co#"ortable with design using inner classes. RFSURFSTIJLT+(6PTE5ITILU

372

Interfaces
The interface keyword takes the abstract conce%t one ste% "urther. /ou could think o" it as a !%ure$ abstract class. It allows the creator to establish the "or# "or a class= #ethod na#es, argu#ent lists, and return ty%es, but no #ethod bodies. 6n interface can also contain "ields, but these are i#%licitly static and final. 6n interface %rovides only a "or#, but no i#%le#entation. RFSURFSTIJLT+(6PTE5ITI?U 6n interface says= !This is what all classes that im lement this %articular inter"ace will look like.$ Thus, any code that uses a %articular interface knows what #ethods #ight be called "or that interface, and that s all. So the interface is used to establish a !%rotocol$ between classes. *So#e ob0ect'oriented %rogra##ing languages have a keyword called rotocol to do the sa#e thing., RFSURFSTIJLT+(6PTE5ITIHU To create an interface, use the interface keyword instead o" the class keyword. Dike a class, you can add the p*blic keyword be"ore the interface keyword *but only i" that interface is de"ined in a "ile o" the sa#e na#e, or leave it o"" to give !"riendly$ status so that it is only usable within the sa#e %ackage. RFSURFSTIJLT+(6PTE5ITI3U To #ake a class that con"or#s to a %articular interface *or grou% o" interfaces, use the implements keyword. /ou re saying !The interface is what it looks like but now I # going to say how it ,orks.$ )ther than that, it looks like inheritance. The diagra# "or the instru#ent e&a#%le shows this=

Cha ter :! Inter$aces & Inner Classes

373

interface Instrument void .la:89M 1tring what89M void ad3ust89M

im.lements Wind void .la:89 1tring what89 void ad3ust89

im.lements ercussion void .la:89 1tring what89 void ad3ust89

im.lements 1tringed void .la:89 1tring what89 void ad3ust89

e0tends Woodwind void .la:89 1tring what89

e0tends ;rass void .la:89 void ad3ust89

)nce you ve i#%le#ented an interface, that i#%le#entation beco#es an ordinary class that can be e&tended in the regular way. RFSURF STIJLT+(6PTE5ITIGU /ou can choose to e&%licitly declare the #ethod declarations in an

interface as p*blic. But they are p*blic even i" you don t say it. So when you implement an interface, the #ethods "ro# the interface #ust be de"ined as p*blic. )therwise they would de"ault to !"riendly,$
and you d be reducing the accessibility o" a #ethod during inheritance, which is not allowed by the Java co#%iler. RFSURF STIJLT+(6PTE5ITIIU /ou can see this in the #odi"ied version o" the Instr*ment e&a#%le. Cote that every #ethod in the interface is strictly a declaration, which is the only thing the co#%iler allows. In addition, none o" the #ethods in

374

Instr*ment are declared as p*blic, but they re auto#atically p*blic


anyway=

//3 c'13#usic,3Jusic,.Hava // $nterfaces. i#"ort Hava.util.B< interface $nstru#ent @ // Co#"ile-ti#e constant3 int i ? ,< // static D final // Cannot have #etho! !efinitions3 voi! "lay-.< // 0uto#atically "ublic %tring :hat-.< voi! a!Hust-.< A class \in! i#"le#ents $nstru#ent @ "ublic voi! "lay-. @ %yste#.out."rintln-8\in!."lay-.8.< A "ublic %tring :hat-. @ return 8\in!8< A "ublic voi! a!Hust-. @A A class Percussion i#"le#ents $nstru#ent @ "ublic voi! "lay-. @ %yste#.out."rintln-8Percussion."lay-.8.< A "ublic %tring :hat-. @ return 8Percussion8< A "ublic voi! a!Hust-. @A A class %tringe! i#"le#ents $nstru#ent @ "ublic voi! "lay-. @ %yste#.out."rintln-8%tringe!."lay-.8.< A "ublic %tring :hat-. @ return 8%tringe!8< A "ublic voi! a!Hust-. @A A class Brass e6ten!s \in! @

Cha ter :! Inter$aces & Inner Classes

375

"ublic voi! "lay-. @ %yste#.out."rintln-8Brass."lay-.8.< A "ublic voi! a!Hust-. @ %yste#.out."rintln-8Brass.a!Hust-.8.< A A class \oo!:in! e6ten!s \in! @ "ublic voi! "lay-. @ %yste#.out."rintln-8\oo!:in!."lay-.8.< A "ublic %tring :hat-. @ return 8\oo!:in!8< A A "ublic class Jusic, @ // Doesn2t care about ty"e, so ne: ty"es // a!!e! to the syste# still :ork right3 static voi! tune-$nstru#ent i. @ // ... i."lay-.< A static voi! tune0ll-$nstru#entNO e. @ for-int i ? '< i P e.length< iKK. tune-eNiO.< A "ublic static voi! #ain-%tringNO args. @ $nstru#entNO orchestra ? ne: $nstru#entN,O< int i ? '< // Y"casting !uring a!!ition to the array3 orchestraNiKKO ? ne: \in!-.< orchestraNiKKO ? ne: Percussion-.< orchestraNiKKO ? ne: %tringe!-.< orchestraNiKKO ? ne: Brass-.< orchestraNiKKO ? ne: \oo!:in!-.< tune0ll-orchestra.< A A ///3>
The rest o" the code works the sa#e. It doesn t #atter i" you are u%casting to a !regular$ class called Instr*ment, an abstract class called

377

Instr*ment, or to an interface called Instr*ment. The behavior is the sa#e. In "act, you can see in the t*neA B #ethod that there isn t any evidence about whether Instr*ment is a !regular$ class, an abstract class, or an interface. This is the intent= Each a%%roach gives the
%rogra##er di""erent control over the way ob0ects are created and used. RFSURFSTIJLT+(6PTE5ITI2U

JMulti.le inheritanceK in "ava


The interface isn t si#%ly a !#ore %ure$ "or# o" abstract class. It has a higher %ur%ose than that. Because an interface has no i#%le#entation at all9that is, there is no storage associated with an interface_there s nothing to %revent #any interfaces "ro# being co#bined. This is valuable because there are ti#es when you need to say !6n 4 is an a and a b and a c.$ In +<<, this act o" co#bining #ulti%le class inter"aces is called multi le inheritance, and it carries so#e rather sticky baggage because each class can have an i#%le#entation. In Java, you can %er"or# the sa#e act, but only one o" the classes can have an i#%le#entation, so the %roble#s seen in +<< do not occur with Java when co#bining #ulti%le inter"aces=
Abstract or Concrete ;ase Class interface ( interface !

)))

)))

interface n

;ase Class <unctions

interface ( interface !

...

interface n

In a derived class, you aren t "orced to have a base class that is either an abstract or !concrete$ *one with no abstract #ethods,. I" you do inherit "ro# a non' interface, you can inherit "ro# only one. 6ll the rest o" the base ele#ents #ust be interfaces. /ou %lace all the inter"ace na#es a"ter the implements keyword and se%arate the# with co##as. /ou can have as #any interfaces as you want9each one beco#es an inde%endent ty%e that you can u%cast to. The "ollowing e&a#%le shows a

Cha ter :! Inter$aces & Inner Classes

378

concrete class co#bined with several interfaces to %roduce a new class= RFSURFSTIJLT+(6PTE5ITIM@U

//3 c'130!venture.Hava // Julti"le interfaces. i#"ort Hava.util.B< interface CanLight @ voi! fight-.< A interface Can%:i# @ voi! s:i#-.< A interface CanLly @ voi! fly-.< A class 0ctionCharacter @ "ublic voi! fight-. @A A class Mero e6ten!s 0ctionCharacter i#"le#ents CanLight, Can%:i#, CanLly @ "ublic voi! s:i#-. @A "ublic voi! fly-. @A A "ublic class 0!venture @ static voi! t-CanLight 6. @ 6.fight-.< A static voi! u-Can%:i# 6. @ 6.s:i#-.< A static voi! v-CanLly 6. @ 6.fly-.< A static voi! :-0ctionCharacter 6. @ 6.fight-.< A "ublic static voi! #ain-%tringNO args. @ Mero h ? ne: Mero-.< t-h.< // Treat it as a CanLight u-h.< // Treat it as a Can%:i# v-h.< // Treat it as a CanLly :-h.< // Treat it as an 0ctionCharacter A

37:

A ///3>
/ou can see that Hero co#bines the concrete class Action-haracter with the inter"aces -anFight, -an)(im, and -anFly. :hen you co#bine a concrete class with inter"aces this way, the concrete class #ust co#e "irst, then the inter"aces. *The co#%iler gives an error otherwise., RFSURFSTIJLT+(6PTE5ITIMMU Cote that the signature "or fightA B is the sa#e in the interface -anFight and the class Action-haracter, and that fightA B is not %rovided with a de"inition in Hero. The rule "or an interface is that you can inherit "ro# it *as you will see shortly,, but then you ve got another interface. I" you want to create an ob0ect o" the new ty%e, it #ust be a class with all de"initions %rovided. Even though Hero does not e&%licitly %rovide a de"inition "or fightA B, the de"inition co#es along with Action-haracter so it is auto#atically %rovided and it s %ossible to create ob0ects o" Hero. RFSURFSTIJLT+(6PTE5ITIMKU In class A'vent*re, you can see that there are "our #ethods that take as argu#ents the various inter"aces and the concrete class. :hen a Hero ob0ect is created, it can be %assed to any o" these #ethods, which #eans it is being u%cast to each interface in turn. Because o" the way inter"aces are designed in Java, this works without a hitch and without any %articular e""ort on the %art o" the %rogra##er. RFSURF STIJLT+(6PTE5ITIMLU >ee% in #ind that the core reason "or inter"aces is shown in the above e&a#%le= to be able to u%cast to #ore than one base ty%e. (owever, a second reason "or using inter"aces is the sa#e as using an abstract base class= to %revent the client %rogra##er "ro# #aking an ob0ect o" this class and to establish that it is only an inter"ace. This brings u% a Auestion= Should you use an interface or an abstract classO 6n interface gives you the bene"its o" an abstract class and the bene"its o" an interface, so i" it s %ossible to create your base class without any #ethod de"initions or #e#ber variables you should always %re"er interfaces to abstract classes. In "act, i" you know so#ething is going to be a base class, your "irst choice should be to #ake it an interface, and only i" you re "orced to have #ethod de"initions or #e#ber variables should you change to an abstract class, or i" necessary a concrete class. RFSURFSTIJLT+(6PTE5ITIM?U

Cha ter :! Inter$aces & Inner Classes

37;

2ame collisions when combining interfaces


/ou can encounter a s#all %it"all when i#%le#enting #ulti%le inter"aces. In the above e&a#%le, both -anFight and Action-haracter have an identical voi' fightA B #ethod. This is no %roble# because the #ethod is identical in both cases, but what i" it s notO (ere s an e&a#%le=

//3 c'13$nterfaceCollision.Hava interface interface interface class C @ $( @ voi! f-.< A $ @ int f-int i.< A $) @ int f-.< A "ublic int f-. @ return (< A A

class C i#"le#ents $(, $ @ "ublic voi! f-. @A "ublic int f-int i. @ return (< A // overloa!e! A class C) e6ten!s C i#"le#ents $ @ "ublic int f-int i. @ return (< A // overloa!e! A class CI e6ten!s C i#"le#ents $) @ // $!entical, no "roble#3 "ublic int f-. @ return (< A A // Jetho!s !iffer only by return ty"e3 //4 class C, e6ten!s C i#"le#ents $( @A //4 interface $I e6ten!s $(, $) @A ///3>
The di""iculty occurs because overriding, i#%le#entation, and overloading get un%leasantly #i&ed together, and overloaded "unctions cannot di""er only by return ty%e. :hen the last two lines are unco##ented, the error #essages say it all=

Inter$aceCollision'>ava!23! $KA in C cannot im lement $KA in I1E attem ting to use incom atible return t) e $ound ! int re#uired! void

38=

Inter$aceCollision'>ava!24! inter$aces I3 and I1 are incom atibleE both de$ine $KAD but ,ith di$$erent return t) e
4sing the sa#e #ethod na#es in di""erent inter"aces that are intended to be co#bined generally causes con"usion in the readability o" the code, as well. Strive to avoid it. RFSURFSTIJLT+(6PTE5ITIMHU

/0tending an interface with inheritance


/ou can easily add new #ethod declarations to an interface using inheritance, and you can also co#bine several interfaces into a new interface with inheritance. In both cases you get a new interface, as seen in this e&a#%le=

//3 c'13Morror%ho:.Hava // E6ten!ing an interface :ith inheritance. interface Jonster @ voi! #enace-.< A interface DangerousJonster e6ten!s Jonster @ voi! !estroy-.< A interface Lethal @ voi! kill-.< A class DragonTilla i#"le#ents DangerousJonster @ "ublic voi! #enace-. @A "ublic voi! !estroy-. @A A interface Wa#"ire e6ten!s DangerousJonster, Lethal @ voi! !rinkBloo!-.< A

Cha ter :! Inter$aces & Inner Classes

381

"ublic class Morror%ho: @ static voi! u-Jonster b. @ b.#enace-.< A static voi! v-DangerousJonster !. @ !.#enace-.< !.!estroy-.< A "ublic static voi! #ain-%tringNO args. @ DragonTilla if ? ne: DragonTilla-.< u-if .< v-if .< A A ///3> angero*s1onster is a si#%le e&tension to 1onster that %roduces a new interface. This is i#%le#ented in ragonZilla. RFSURF STIJLT+(6PTE5ITIM3U
The synta& used in Vampire works onl) when inheriting inter"aces. Cor#ally, you can use e4ten's with only a single class, but since an interface can be #ade "ro# #ulti%le other inter"aces, e4ten's can re"er to #ulti%le base inter"aces when building a new interface. 6s you can see, the interface na#es are si#%ly se%arated with co##as. RFSURF STIJLT+(6PTE5ITIMGU

'rou.ing constants
Because any "ields you %ut into an interface are auto#atically static and final, the interface is a convenient tool "or creating grou%s o" constant values, #uch as you would with an en*m in + or +<<. Eor e&a#%le=

//3 c'13Jonths.Hava // Ysing interfaces to create grou"s of constants. "ackage c'1< "ublic interface Jonths @ int J0&Y05; ? (, LEB5Y05; ? , J05CM ? ), 0P5$L ? I, J0; ? ,, JY&E ? +, JYL; ? *, 0YaY%T ? 1, %EPTEJBE5 ? C, GCTGBE5 ? (',

382

&GWEJBE5 ? ((, DECEJBE5 ? ( < A ///3>


Cotice the Java style o" using all u%%ercase letters *with underscores to se%arate #ulti%le words in a single identi"ier, "or static finals that have constant initiali1ers. RFSURFSTIJLT+(6PTE5ITIMIU The "ields in an interface are auto#atically p*blic, so it s unnecessary to s%eci"y that. RFSURFSTIJLT+(6PTE5ITIM2U Cow you can use the constants "ro# outside the %ackage by i#%orting

cDY!K or cDY!1onths 0ust as you would with any other %ackage, and re"erencing the values with e&%ressions like 1onths!JA/UA$:. )" course, what you get is 0ust an int, so there isn t the e&tra ty%e sa"ety that +<< s en*m has, but this *co##only used, techniAue is certainly an
i#%rove#ent over hard'coding nu#bers into your %rogra#s. *That a%%roach is o"ten re"erred to as using !#agic nu#bers$ and it %roduces very di""icult'to'#aintain code., RFSURFSTIJLT+(6PTE5ITIK@U I" you do want e&tra ty%e sa"ety, you can build a class like this @=

//3 c'13Jonth .Hava // 0 #ore robust enu#eration syste#. "ackage c'1< "ublic final class Jonth @ "rivate %tring na#e< "rivate int or!er< "rivate Jonth -int or!, %tring n#. @ or!er ? or!< na#e ? n#< A "ublic %tring to%tring-. @ return na#e< A "ublic final static Jonth J0& ? ne: Jonth -(, 8January8., LEB ? ne: Jonth - , 8Lebruary8., J05 ? ne: Jonth -), 8Jarch8., 0P5 ? ne: Jonth -I, 80"ril8., J0; ? ne: Jonth -,, 8Jay8., JY& ? ne: Jonth -+, 8June8.,
@ This a%%roach was ins%ired by an e'#ail "ro# 5ich (o""arth.

Cha ter :! Inter$aces & Inner Classes

383

JYL ? ne: Jonth -*, 8July8., 0Ya ? ne: Jonth -1, 80ugust8., %EP ? ne: Jonth -C, 8%e"te#ber8., GCT ? ne: Jonth -(', 8Gctober8., &GW ? ne: Jonth -((, 8&ove#ber8., DEC ? ne: Jonth -( , 8Dece#ber8.< "ublic final static Jonth NO #onth ? @ J0&, LEB, J05, 0P5, J0;, JY&, JYL, 0Ya, %EP, GCT, &GW, DEC A< "ublic final static Jonth nu#ber-int or!. @ return #onthNor! - (O< A "ublic static voi! #ain-%tringNO args. @ Jonth # ? Jonth .J0&< %yste#.out."rintln-#.< # ? Jonth .nu#ber-( .< %yste#.out."rintln-#.< %yste#.out."rintln-# ?? Jonth .DEC.< %yste#.out."rintln-#.e=uals-Jonth .DEC..< A A ///3>//3 c'13Jonth .Hava // 0 #ore robust enu#eration syste#. "ackage c'1< "ublic final class Jonth @ "rivate %tring na#e< "rivate Jonth -%tring n#. @ na#e ? n#< A "ublic %tring to%tring-. @ return na#e< A "ublic final static Jonth J0& ? ne: Jonth -8January8., LEB ? ne: Jonth -8Lebruary8., J05 ? ne: Jonth -8Jarch8., 0P5 ? ne: Jonth -80"ril8., J0; ? ne: Jonth -8Jay8., JY& ? ne: Jonth -8June8., JYL ? ne: Jonth -8July8., 0Ya ? ne: Jonth -80ugust8., %EP ? ne: Jonth -8%e"te#ber8., GCT ? ne: Jonth -8Gctober8., &GW ? ne: Jonth -8&ove#ber8.,

384

DEC ? ne: Jonth -8Dece#ber8.< "ublic final static Jonth NO #onth ? @ J0&, J0&, LEB, J05, 0P5, J0;, JY&, JYL, 0Ya, %EP, GCT, &GW, DEC A< "ublic static voi! #ain-%tringNO args. @ Jonth # ? Jonth .J0&< %yste#.out."rintln-#.< # ? Jonth .#onthN( O< %yste#.out."rintln-#.< %yste#.out."rintln-# ?? Jonth .DEC.< %yste#.out."rintln-#.e=uals-Jonth .DEC..< A A ///3>
The class is called 1onthI, since there s already a 1onth in the standard Java library. It s a final class with a private constructor so no one can inherit "ro# it or #ake any instances o" it. The only instances are the final static ones created in the class itsel"= JA/, F&2, 1A$, etc. These ob0ects are also used in the array month, which lets you choose

#onths by nu#ber instead o" by na#e. *Cotice the e&tra JA/ in the array to %rovide an o""set by one, so that 7ece#ber is #onth MK.,iterate through an array o" 1onthI ob0ects. The n*mberA B #ethod allows you to select a 1onthI by giving its corres%onding #onth nu#ber. In main A B you can see the ty%e sa"ety= m is a 1onthI ob0ect so it can be assigned only to a 1onthI. The %revious e&a#%le 1onths!8ava %rovided only int values, so an int variable intended to re%resent a
#onth could actually be given any integer value, which wasn t very sa"e. RFSURFSTIJLT+(6PTE5ITIKMU This a%%roach also allows you to use PP or eC*alsA B interchangeably, as shown at the end o" mainA B. This works because there can be only one instance o" each value o" 1onthI. RFSURFSTIJLT+(6PTE5ITIKKU

Initiali?ing fields in interfaces


Eields de"ined in inter"aces are auto#atically static and final. These cannot be !blank "inals,$ but they can be initiali1ed with nonconstant e&%ressions. Eor e&a#%le=

Cha ter :! Inter$aces & Inner Classes

385

//3 c'135an!Wals.Hava // $nitialiUing interface fiel!s :ith // non-constant initialiUers. i#"ort Hava.util.B< "ublic interface 5an!Wals @ int rint ? -int.-Jath.ran!o#-. B ('.< long rlong ? -long.-Jath.ran!o#-. B ('.< float rfloat ? -float.-Jath.ran!o#-. B ('.< !ouble r!ouble ? Jath.ran!o#-. B ('< A ///3>
Since the "ields are static, they are initiali1ed when the class is "irst loaded, which ha%%ens when any o" the "ields are accessed "or the "irst ti#e. (ere s a si#%le test= RFSURFSTIJLT+(6PTE5ITIKLU

//3 c'13Test5an!Wals.Hava "ublic class Test5an!Wals @ "ublic static voi! #ain-%tringNO args. @ %yste#.out."rintln-5an!Wals.rint.< %yste#.out."rintln-5an!Wals.rlong.< %yste#.out."rintln-5an!Wals.rfloat.< %yste#.out."rintln-5an!Wals.r!ouble.< A A ///3>
The "ields, o" course, are not %art o" the inter"ace but instead are stored in the static storage area "or that inter"ace. RFSURF STIJLT+(6PTE5ITIK?U

2esting interfaces
Inter"aces #ay be nested within classes and within other inter"aces. This reveals a nu#ber o" very interesting "eatures=
@

//3 c'13&esting$nterfaces.Hava class 0 @ interface B @


@ Thanks to Martin 7anner "or asking this Auestion during a se#inar.

387

voi! f-.< A "ublic class B$#" i#"le#ents B @ "ublic voi! f-. @A A "rivate class B$#" i#"le#ents B @ "ublic voi! f-. @A A "ublic interface C @ voi! f-.< A class C$#" i#"le#ents C @ "ublic voi! f-. @A A "rivate class C$#" i#"le#ents C @ "ublic voi! f-. @A A "rivate interface D @ voi! f-.< A "rivate class D$#" i#"le#ents D @ "ublic voi! f-. @A A "ublic class D$#" i#"le#ents D @ "ublic voi! f-. @A A "ublic D getD-. @ return ne: D$#" -.< A "rivate D !5ef< "ublic voi! receiveD-D !. @ !5ef ? !< !5ef.f-.< A A interface E @ interface a @ voi! f-.< A // 5e!un!ant 8"ublic83 "ublic interface M @ voi! f-.<

Cha ter :! Inter$aces & Inner Classes

388

A voi! g-.< // Cannot be "rivate :ithin an interface3 //4 "rivate interface $ @A A "ublic class &esting$nterfaces @ "ublic class B$#" i#"le#ents 0.B @ "ublic voi! f-. @A A class C$#" i#"le#ents 0.C @ "ublic voi! f-. @A A // Cannot i#"le#ent a "rivate interface e6ce"t // :ithin that interface2s !efining class3 //4 class D$#" i#"le#ents 0.D @ //4 "ublic voi! f-. @A //4 A class E$#" i#"le#ents E @ "ublic voi! g-. @A A class Ea$#" i#"le#ents E.a @ "ublic voi! f-. @A A class E$#" i#"le#ents E @ "ublic voi! g-. @A class Ea i#"le#ents E.a @ "ublic voi! f-. @A A A "ublic static voi! #ain-%tringNO args. @ 0 a ? ne: 0-.< // Can2t access 0.D3 //4 0.D a! ? a.getD-.< // Doesn2t return anything but 0.D3 //4 0.D$#" !i ? a.getD-.< // Cannot access a #e#ber of the interface3 //4 a.getD-..f-.< // Gnly another 0 can !o anything :ith getD-.3 0 a ? ne: 0-.< a .receiveD-a.getD-..<

38:

A A ///3>
The synta& "or nesting an inter"ace within a class is reasonably obvious, and 0ust like non'nested inter"aces these can have p*blic or !"riendly$ visibility. /ou can also see that both p*blic and !"riendly$ nested inter"aces can be i#%le#ented as a p*blic, !"riendly,$ and private nested classes. RFSURFSTIJLT+(6PTE5ITIKHU 6s a new twist, inter"aces can also be private as seen in A! *the sa#e Auali"ication synta& is used "or nested inter"aces as "or nested classes,. :hat good is a private nested inter"aceO /ou #ight guess that it can only be i#%le#ented as a private nested class as in Imp, but A! ImpI shows that it can also be i#%le#ented as a p*blic class. (owever, A! ImpI can only be used as itsel". /ou are not allowed to #ention the "act that it i#%le#ents the private inter"ace, so i#%le#enting a private inter"ace is a way to "orce the de"inition o" the #ethods in that inter"ace without adding any ty%e in"or#ation *that is, without allowing any u%casting,. RFSURFSTIJLT+(6PTE5ITIK3U The #ethod get A B %roduces a "urther Auandary concerning the private inter"ace= it s a p*blic #ethod that returns a re"erence to a private inter"ace. :hat can you do with the return value o" this #ethodO In mainA B, you can see several atte#%ts to use the return value, all o" which "ail. The only thing that works is i" the return value is handed to an ob0ect that has %er#ission to use it9in this case, another A, via the receive'receive A B #ethod. RFSURFSTIJLT+(6PTE5ITIKGU Inter"ace & shows that inter"aces can be nested within each other. (owever, the rules about inter"aces9in %articular, that all inter"ace ele#ents #ust be p*blic9are strictly en"orced here, so an inter"ace nested within another inter"ace is auto#atically p*blic and cannot be #ade private. RFSURFSTIJLT+(6PTE5ITIKIU

/estingInterfaces shows the various ways that nested inter"aces can be


i#%le#ented. In %articular, notice that when you i#%le#ent an inter"ace, you are not reAuired to i#%le#ent any inter"aces nested within. 6lso, private inter"aces cannot be i#%le#ented outside o" their de"ining classes. RFSURFSTIJLT+(6PTE5ITIK2U

Cha ter :! Inter$aces & Inner Classes

38;

Initially, these "eatures #ay see# like they are added strictly "or syntactic consistency, but I generally "ind that once you know about a "eature, you o"ten discover %laces where it is use"ul. RFSURFSTIJLT+(6PTE5ITIL@U

Inner classes
It s %ossible to %lace a class de"inition within another class de"inition. This is called an inner class. The inner class is a valuable "eature because it allows you to grou% classes that logically belong together and to control the visibility o" one within the other. (owever, it s i#%ortant to understand that inner classes are distinctly di""erent "ro# co#%osition. RFSURFSTIJLT+(6PTE5ITILMU )"ten, while you re learning about the#, the need "or inner classes isn t i##ediately obvious. 6t the end o" this section, a"ter all o" the synta& and se#antics o" inner classes have been described, you ll "ind e&a#%les that should #ake clear the bene"its o" inner classes. RFSURF STIJLT+(6PTE5ITILKU /ou create an inner class 0ust as you d e&%ect9by %lacing the class de"inition inside a surrounding class= RFSURFSTIJLT+(6PTE5ITILLU

//3 c'13Parcel(.Hava // Creating inner classes. "ublic class Parcel( @ class Contents @ "rivate int i ? ((< "ublic int value-. @ return i< A A class Destination @ "rivate %tring label< Destination-%tring :hereTo. @ label ? :hereTo< A %tring rea!Label-. @ return label< A A // Ysing inner classes looks Hust like // using any other class, :ithin Parcel(3 "ublic voi! shi"-%tring !est. @

3:=

Contents c ? ne: Contents-.< Destination ! ? ne: Destination-!est.< %yste#.out."rintln-!.rea!Label-..< A "ublic static voi! #ain-%tringNO args. @ Parcel( " ? ne: Parcel(-.< ".shi"-8TanUania8.< A A ///3>
The inner classes, when used inside shipA B, look 0ust like the use o" any other classes. (ere, the only %ractical di""erence is that the na#es are nested within #arcel>. /ou ll see in a while that this isn t the only di""erence. RFSURFSTIJLT+(6PTE5ITIL?U More ty%ically, an outer class will have a #ethod that returns a re"erence to an inner class, like this=

//3 c'13Parcel .Hava // 5eturning a reference to an inner class. "ublic class Parcel @ class Contents @ "rivate int i ? ((< "ublic int value-. @ return i< A A class Destination @ "rivate %tring label< Destination-%tring :hereTo. @ label ? :hereTo< A %tring rea!Label-. @ return label< A A "ublic Destination to-%tring s. @ return ne: Destination-s.< A "ublic Contents cont-. @ return ne: Contents-.< A "ublic voi! shi"-%tring !est. @ Contents c ? cont-.< Destination ! ? to-!est.<

Cha ter :! Inter$aces & Inner Classes

3:1

%yste#.out."rintln-!.rea!Label-..< A "ublic static voi! #ain-%tringNO args. @ Parcel " ? ne: Parcel -.< ".shi"-8TanUania8.< Parcel = ? ne: Parcel -.< // Defining references to inner classes3 Parcel .Contents c ? =.cont-.< Parcel .Destination ! ? =.to-8Borneo8.< A A ///3>
I" you want to #ake an ob0ect o" the inner class anywhere e&ce%t "ro# within a non' static #ethod o" the outer class, you #ust s%eci"y the ty%e o" that ob0ect as OuterClass+ame'InnerClass+ame, as seen in mainA B. RFSURFSTIJLT+(6PTE5ITILHU

Inner classes and u.casting


So "ar, inner classes don t see# that dra#atic. 6"ter all, i" it s hiding you re a"ter, Java already has a %er"ectly good hiding #echanis#90ust allow the class to be !"riendly$ *visible only within a %ackage, rather than creating it as an inner class. RFSURFSTIJLT+(6PTE5ITIL3U (owever, inner classes really co#e into their own when you start u%casting to a base class, and in %articular to an interface. *The e""ect o" %roducing an inter"ace re"erence "ro# an ob0ect that i#%le#ents it is essentially the sa#e as u%casting to a base class., That s because the inner class9the i#%le#entation o" the interface9can then be co#%letely unseen and unavailable to anyone, which is convenient "or hiding the i#%le#entation. 6ll you get back is a re"erence to the base class or the interface. RFSURFSTIJLT+(6PTE5ITILGU Eirst, the co##on inter"aces will be de"ined in their own "iles so they can be used in all the e&a#%les=

//3 c'13Destination.Hava "ublic interface Destination @ %tring rea!Label-.< A ///3>

3:2

//3 c'13Contents.Hava "ublic interface Contents @ int value-.< A ///3>


Cow -ontents and estination re%resent inter"aces available to the client %rogra##er. *The interface, re#e#ber, auto#atically #akes all o" its #e#bers p*blic., RFSURFSTIJLT+(6PTE5ITILIU :hen you get back a re"erence to the base class or the interface, it s %ossible that you can t even "ind out the e&act ty%e, as shown here=

//3 c'13Parcel).Hava // 5eturning a reference to an inner class. "ublic class Parcel) @ "rivate class PContents i#"le#ents Contents @ "rivate int i ? ((< "ublic int value-. @ return i< A A "rotecte! class PDestination i#"le#ents Destination @ "rivate %tring label< "rivate PDestination-%tring :hereTo. @ label ? :hereTo< A "ublic %tring rea!Label-. @ return label< A A "ublic Destination !est-%tring s. @ return ne: PDestination-s.< A "ublic Contents cont-. @ return ne: PContents-.< A A class Test @ "ublic static voi! #ain-%tringNO args. @ Parcel) " ? ne: Parcel)-.< Contents c ? ".cont-.< Destination ! ? ".!est-8TanUania8.< // $llegal -- can2t access "rivate class3

Cha ter :! Inter$aces & Inner Classes

3:3

//4 Parcel).PContents "c ? ".ne: PContents-.< A A ///3>


Cote that since mainA B is in Test, when you want to run this %rogra# you don t e&ecute #arcelJ, but instead=

Hava Test
In the e&a#%le, mainA B #ust be in a se%arate class in order to de#onstrate the %rivateness o" the inner class #-ontents. RFSURF STIJLT+(6PTE5ITIL2U In #arcelJ, so#ething new has been added= the inner class #-ontents is private so no one but #arcelJ can access it. # estination is protecte', so no one but #arcelJ, classes in the #arcelJ %ackage *since protecte' also gives %ackage access9that is, protecte' is also !"riendly$,, and the inheritors o" #arcelJ can access # estination. This #eans that the client %rogra##er has restricted knowledge and access to these #e#bers. In "act, you can t even downcast to a private inner class *or a protecte' inner class unless you re an inheritor,, because you can t access the na#e, as you can see in class Test. Thus, the private inner class %rovides a way "or the class designer to co#%letely %revent any ty%e' coding de%endencies and to co#%letely hide details about i#%le#entation. In addition, e&tension o" an interface is useless "ro# the client %rogra##er s %ers%ective since the client %rogra##er cannot access any additional #ethods that aren t %art o" the p*blic interface class. This also %rovides an o%%ortunity "or the Java co#%iler to generate #ore e""icient code. RFSURFSTIJLT+(6PTE5ITI?@U Cor#al *non'inner, classes cannot be #ade private or protecte'_only p*blic or !"riendly.$ RFSURFSTIJLT+(6PTE5ITI?MU

Inner classes in methods and sco.es


:hat you ve seen so "ar enco#%asses the ty%ical use "or inner classes. In general, the code that you ll write and read involving inner classes will be !%lain$ inner classes that are si#%le and easy to understand. (owever, the design "or inner classes is Auite co#%lete and there are a nu#ber o"

3:4

other, #ore obscure, ways that you can use the# i" you choose= inner classes can be created within a #ethod or even an arbitrary sco%e. There are two reasons "or doing this= RFSURFSTIJLT+(6PTE5ITI?KU

,4)

6s shown %reviously, you re i#%le#enting an inter"ace o" so#e kind so that you can create and return a re"erence. RFSURF STIJLT+(6PTE5ITI?LU /ou re solving a co#%licated %roble# and you want to create a class to aid in your solution, but you don t want it %ublicly available. RFSURFSTIJLT+(6PTE5ITI??U

,5)

In the "ollowing e&a#%les, the %revious code will be #odi"ied to use= RF SURFSTIJLT+(6PTE5ITI?HU

,6) -7) -() -!) -*) -+)

6 class de"ined within a #ethod 6 class de"ined within a sco%e inside a #ethod 6n anony#ous class i#%le#enting an inter"ace 6n anony#ous class e&tending a class that has a nonde"ault constructor 6n anony#ous class that %er"or#s "ield initiali1ation 6n anony#ous class that %er"or#s construction using instance initiali1ation *anony#ous inner classes cannot have constructors,

6lthough it s an ordinary class with an i#%le#entation, 0rapping is also being used as a co##on !inter"ace$ to its derived classes=

//3 c'13\ra""ing.Hava "ublic class \ra""ing @ "rivate int i< "ublic \ra""ing-int 6. @ i ? 6< A "ublic int value-. @ return i< A A ///3>
/ou ll notice above that 0rapping has a constructor that reAuires an argu#ent, to #ake things a bit #ore interesting. RFSURF STIJLT+(6PTE5ITI?3U

Cha ter :! Inter$aces & Inner Classes

3:5

The "irst e&a#%le shows the creation o" an entire class within the sco%e o" a #ethod *instead o" the sco%e o" another class,=

//3 c'13ParcelI.Hava // &esting a class :ithin a #etho!. "ublic class ParcelI @ "ublic Destination !est-%tring s. @ class PDestination i#"le#ents Destination @ "rivate %tring label< "rivate PDestination-%tring :hereTo. @ label ? :hereTo< A "ublic %tring rea!Label-. @ return label< A A return ne: PDestination-s.< A "ublic static voi! #ain-%tringNO args. @ ParcelI " ? ne: ParcelI-.< Destination ! ? ".!est-8TanUania8.< A A ///3>
The class # estination is %art o" 'estA B rather than being %art o" #arcelQ. *6lso notice that you could use the class identi"ier # estination "or an inner class inside each class in the sa#e subdirectory without a na#e clash., There"ore, # estination cannot be accessed outside o" 'estA B. Cotice the u%casting that occurs in the return state#ent9nothing co#es out o" 'estA B e&ce%t a re"erence to estination, the base class. )" course, the "act that the na#e o" the class # estination is %laced inside 'estA B doesn t #ean that # estination is not a valid ob0ect once 'estA B returns. RFSURF STIJLT+(6PTE5ITI?GU The ne&t e&a#%le shows how you can nest an inner class within any arbitrary sco%e=

//3 c'13Parcel,.Hava // &esting a class :ithin a sco"e.

3:7

"ublic class Parcel, @ "rivate voi! internalTracking-boolean b. @ if-b. @ class Tracking%li" @ "rivate %tring i!< Tracking%li"-%tring s. @ i! ? s< A %tring get%li"-. @ return i!< A A Tracking%li" ts ? ne: Tracking%li"-8sli"8.< %tring s ? ts.get%li"-.< A // Can2t use it here4 Gut of sco"e3 //4 Tracking%li" ts ? ne: Tracking%li"-868.< A "ublic voi! track-. @ internalTracking-true.< A "ublic static voi! #ain-%tringNO args. @ Parcel, " ? ne: Parcel,-.< ".track-.< A A ///3>
The class Tracking)lip is nested inside the sco%e o" an if state#ent. This does not #ean that the class is conditionally created9it gets co#%iled along with everything else. (owever, it s not available outside the sco%e in which it is de"ined. )ther than that, it looks 0ust like an ordinary class. RFSURFSTIJLT+(6PTE5ITI?IU

Anon:mous inner classes


The ne&t e&a#%le looks a little strange=

//3 c'13Parcel+.Hava // 0 #etho! that returns an anony#ous inner class. "ublic class Parcel+ @ "ublic Contents cont-. @ return ne: Contents-. @ "rivate int i ? ((< "ublic int value-. @ return i< A

Cha ter :! Inter$aces & Inner Classes

3:8

A< // %e#icolon re=uire! in this case A "ublic static voi! #ain-%tringNO args. @ Parcel+ " ? ne: Parcel+-.< Contents c ? ".cont-.< A A ///3>
The contA B #ethod co#bines the creation o" the return value with the de"inition o" the class that re%resents that return value. In addition, the class is anony#ous9it has no na#e. To #ake #atters a bit worse, it looks like you re starting out to create a -ontents ob0ect= RFSURF STIJLT+(6PTE5ITI?2U

return ne: Contents-.


But then, be"ore you get to the se#icolon, you say, !But wait, I think I ll sli% in a class de"inition$= RFSURFSTIJLT+(6PTE5ITIH@U

return ne: Contents-. @ "rivate int i ? ((< "ublic int value-. @ return i< A A<
:hat this strange synta& #eans is= !+reate an ob0ect o" an anony#ous class that s inherited "ro# -ontents.$ The re"erence returned by the ne( e&%ression is auto#atically u%cast to a -ontents re"erence. The anony#ous inner'class synta& is a shorthand "or= RFSURF STIJLT+(6PTE5ITIHMU

class JyContents i#"le#ents Contents @ "rivate int i ? ((< "ublic int value-. @ return i< A A return ne: JyContents-.<
In the anony#ous inner class, -ontents is created using a de"ault constructor. The "ollowing code shows what to do i" your base class needs a constructor with an argu#ent= RFSURFSTIJLT+(6PTE5ITIHKU

//3 c'13Parcel*.Hava // 0n anony#ous inner class that calls // the base-class constructor.

3::

"ublic class Parcel* @ "ublic \ra""ing :ra"-int 6. @ // Base constructor call3 return ne: \ra""ing-6. @ "ublic int value-. @ return su"er.value-. B I*< A A< // %e#icolon re=uire! A "ublic static voi! #ain-%tringNO args. @ Parcel* " ? ne: Parcel*-.< \ra""ing : ? ".:ra"-('.< A A ///3>
That is, you si#%ly %ass the a%%ro%riate argu#ent to the base'class constructor, seen here as the 4 %assed in ne( 0rappingA4B. 6n anony#ous class cannot have a constructor where you would nor#ally call s*perA B. RFSURFSTIJLT+(6PTE5ITIHLU In both o" the %revious e&a#%les, the se#icolon doesn t #ark the end o" the class body *as it does in +<<,. Instead, it #arks the end o" the e&%ression that ha%%ens to contain the anony#ous class. Thus, it s identical to the use o" the se#icolon everywhere else. RFSURF STIJLT+(6PTE5ITIH?U :hat ha%%ens i" you need to %er"or# so#e kind o" initiali1ation "or an ob0ect o" an anony#ous inner classO Since it s anony#ous, there s no na#e to give the constructor9so you can t have a constructor. /ou can, however, %er"or# initiali1ation at the %oint o" de"inition o" your "ields=

//3 c'13Parcel1.Hava // 0n anony#ous inner class that "erfor#s // initialiUation. 0 briefer version // of Parcel,.Hava. "ublic class Parcel1 @ // 0rgu#ent #ust be final to use insi!e // anony#ous inner class3 "ublic Destination !est-final %tring !est. @

Cha ter :! Inter$aces & Inner Classes

3:;

return ne: Destination-. @ "rivate %tring label ? !est< "ublic %tring rea!Label-. @ return label< A A< A "ublic static voi! #ain-%tringNO args. @ Parcel1 " ? ne: Parcel1-.< Destination ! ? ".!est-8TanUania8.< A A ///3>
I" you re de"ining an anony#ous inner class and want to use an ob0ect that s de"ined outside the anony#ous inner class, the co#%iler reAuires that the outside ob0ect be final. This is why the argu#ent to 'estA B is final. I" you "orget, you ll get a co#%ile'ti#e error #essage. RFSURF STIJLT+(6PTE5ITIHHU 6s long as you re si#%ly assigning a "ield, the above a%%roach is "ine. But what i" you need to %er"or# so#e constructor'like activityO :ith instance initiali?ation, you can, in e""ect, create a constructor "or an anony#ous inner class=

//3 c'13ParcelC.Hava // Ysing 8instance initialiUation8 to "erfor# // construction on an anony#ous inner class. "ublic class ParcelC @ "ublic Destination !est-final %tring !est, final float "rice. @ return ne: Destination-. @ "rivate int cost< // $nstance initialiUation for each obHect3 @ cost ? Jath.roun!-"rice.< if-cost Q (''. %yste#.out."rintln-8Gver bu!get48.< A "rivate %tring label ? !est< "ublic %tring rea!Label-. @ return label< A A< A

3;=

"ublic static voi! #ain-%tringNO args. @ ParcelC " ? ne: ParcelC-.< Destination ! ? ".!est-8TanUania8, ('(.)C,L.< A A ///3>
Inside the instance initiali1er you can see code that couldn t be e&ecuted as %art o" a "ield initiali1er *that is, the if state#ent,. So in e""ect, an instance initiali1er is the constructor "or an anony#ous inner class. )" course, it s li#ited; you can t overload instance initiali1ers so you can have only one o" these constructors. RFSURFSTIJLT+(6PTE5ITIH3U

#he link to the outer class


So "ar, it a%%ears that inner classes are 0ust a na#e'hiding and code' organi1ation sche#e, which is hel%"ul but not totally co#%elling. (owever, there s another twist. :hen you create an inner class, an ob0ect o" that inner class has a link to the enclosing ob0ect that #ade it, and so it can access the #e#bers o" that enclosing ob0ect9 ,ithout any s%ecial Auali"ications. In addition, inner classes have access rights to all the ele#ents in the enclosing class @. The "ollowing e&a#%le de#onstrates this=

//3 c'13%e=uence.Hava // Mol!s a se=uence of GbHects. interface %elector @ boolean en!-.< GbHect current-.< voi! ne6t-.< A "ublic class %e=uence @ "rivate GbHectNO obs< "rivate int ne6t ? '< "ublic %e=uence-int siUe. @ obs ? ne: GbHectNsiUeO<
@ This is very di""erent "ro# the design o" nested classes in +<<, which is si#%ly a na#e' hiding #echanis#. There is no link to an enclosing ob0ect and no i#%lied %er#issions in +<<.

Cha ter :! Inter$aces & Inner Classes

3;1

A "ublic voi! a!!-GbHect 6. @ if-ne6t P obs.length. @ obsNne6tO ? 6< ne6tKK< A A "rivate class %%elector i#"le#ents %elector @ int i ? '< "ublic boolean en!-. @ return i ?? obs.length< A "ublic GbHect current-. @ return obsNiO< A "ublic voi! ne6t-. @ if-i P obs.length. iKK< A A "ublic %elector get%elector-. @ return ne: %%elector-.< A "ublic static voi! #ain-%tringNO args. @ %e=uence s ? ne: %e=uence-('.< for-int i ? '< i P ('< iKK. s.a!!-$nteger.to%tring-i..< %elector sl ? s.get%elector-.< :hile-4sl.en!-.. @ %yste#.out."rintln-sl.current-..< sl.ne6t-.< A A A ///3>
The )eC*ence is si#%ly a "i&ed'si1ed array o" .b8ect with a class wra%%ed around it. /ou call a''A B to add a new .b8ect to the end o" the seAuence *i" there s roo# le"t,. To "etch each o" the ob0ects in a )eC*ence, there s an inter"ace called )elector, which allows you to see i" you re at the en'A B, to look at the c*rrentA B .b8ect, and to #ove to the ne4tA B .b8ect in the )eC*ence. Because )elector is an interface, #any other classes can i#%le#ent the interface in their own ways, and

3;2

#any #ethods can take the interface as an argu#ent, in order to create generic code. RFSURFSTIJLT+(6PTE5ITIHGU (ere, the ))elector is a private class that %rovides )elector "unctionality. In mainA B, you can see the creation o" a )eC*ence, "ollowed by the addition o" a nu#ber o" )tring ob0ects. Then, a )elector is %roduced with a call to get)electorA B and this is used to #ove through the )eC*ence and select each ite#. RFSURF STIJLT+(6PTE5ITIHIU 6t "irst, the creation o" ))elector looks like 0ust another inner class. But e&a#ine it closely. Cote that each o" the #ethods en'A B, c*rrentA B, and ne4tA B re"er to obs, which is a re"erence that isn t %art o" ))elector, but is instead a private "ield in the enclosing class. (owever, the inner class can access #ethods and "ields "ro# the enclosing class as i" they owned the#. This turns out to be very convenient, as you can see in the above e&a#%le. RFSURFSTIJLT+(6PTE5ITIH2U So an inner class has auto#atic access to the #e#bers o" the enclosing class. (ow can this ha%%enO The inner class #ust kee% a re"erence to the %articular ob0ect o" the enclosing class that was res%onsible "or creating it. Then when you re"er to a #e#ber o" the enclosing class, that *hidden, re"erence is used to select that #e#ber. Eortunately, the co#%iler takes care o" all these details "or you, but you can also understand now that an ob0ect o" an inner class can be created only in association with an ob0ect o" the enclosing class. +onstruction o" the inner class ob0ect reAuires the re"erence to the ob0ect o" the enclosing class, and the co#%iler will co#%lain i" it cannot access that re"erence. Most o" the ti#e this occurs without any intervention on the %art o" the %rogra##er. RFSURF STIJLT+(6PTE5ITI3@U

static inner classes


I" you don t need a connection between the inner class ob0ect and the outer class ob0ect, then you can #ake the inner class static. To understand the #eaning o" static when a%%lied to inner classes, you #ust re#e#ber that the ob0ect o" an ordinary inner class i#%licitly kee%s a re"erence to the ob0ect o" the enclosing class that created it. This is not

Cha ter :! Inter$aces & Inner Classes

3;3

true, however, when you say an inner class is static. 6 static inner class #eans= RFSURFSTIJLT+(6PTE5ITI3MU

-,) --)

/ou don t need an outer'class ob0ect in order to create an ob0ect o" a static inner class. RFSURFSTIJLT+(6PTE5ITI3KU /ou can t access an outer'class ob0ect "ro# an ob0ect o" a static inner class. RFSURFSTIJLT+(6PTE5ITI3LU

static inner classes are di""erent than non' static inner classes in another way, as well. Eields and #ethods in non' static inner classes can only be at the outer level o" a class, so non' static inner classes cannot have static data, static "ields, or static inner classes. (owever, static inner
classes can have all o" these= RFSURFSTIJLT+(6PTE5ITI3?U

//3 c'13Parcel('.Hava // %tatic inner classes. "ublic class Parcel(' @ "rivate static class PContents i#"le#ents Contents @ "rivate int i ? ((< "ublic int value-. @ return i< A A "rotecte! static class PDestination i#"le#ents Destination @ "rivate %tring label< "rivate PDestination-%tring :hereTo. @ label ? :hereTo< A "ublic %tring rea!Label-. @ return label< A // %tatic inner classes can contain // other static ele#ents3 "ublic static voi! f-. @A static int 6 ? ('< static class 0notherLevel @ "ublic static voi! f-. @A static int 6 ? ('< A A "ublic static Destination !est-%tring s. @

3;4

return ne: PDestination-s.< A "ublic static Contents cont-. @ return ne: PContents-.< A "ublic static voi! #ain-%tringNO args. @ Contents c ? cont-.< Destination ! ? !est-8TanUania8.< A A ///3>
In mainA B, no ob0ect o" #arcel>D is necessary; instead you use the nor#al synta& "or selecting a static #e#ber to call the #ethods that return re"erences to -ontents and estination. RFSURF STIJLT+(6PTE5ITI3HU 6s you will see shortly, in an ordinary *non' static, inner class, the link to the outer class ob0ect is achieved with a s%ecial this re"erence. 6 static inner class does not have this s%ecial this re"erence, which #akes it analogous to a static #ethod. RFSURFSTIJLT+(6PTE5ITI33U Cor#ally you can t %ut any code inside an interface, but a static inner class can be %art o" an interface. Since the class is static it doesn t violate the rules "or inter"aces9the static inner class is only %laced inside the na#es%ace o" the inter"ace=

//3 c'13$$nterface.Hava // %tatic inner classes insi!e interfaces. "ublic interface $$nterface @ static class $nner @ int i, H, k< "ublic $nner-. @A voi! f-. @A A A ///3>
Earlier in this book I suggested %utting a mainA B in every class to act as a test bed "or that class. )ne drawback to this is the a#ount o" e&tra co#%iled code you #ust carry around. I" this is a %roble#, you can use a

Cha ter :! Inter$aces & Inner Classes

3;5

static inner class to hold your test code= RFSURF


STIJLT+(6PTE5ITI3GU

//3 c'13TestBe!.Hava // Putting test co!e in a static inner class. "ublic class TestBe! @ TestBe!-. @A voi! f-. @ %yste#.out."rintln-8f-.8.< A "ublic static class Tester @ "ublic static voi! #ain-%tringNO args. @ TestBe! t ? ne: TestBe!-.< t.f-.< A A A ///3>
This generates a se%arate class called Test2e'`Tester *to run the %rogra#, you say 8ava Test2e'`Tester,. /ou can use this class "or testing, but you don t need to include it in your shi%%ing %roduct. RFSURF STIJLT+(6PTE5ITI3IU

$eferring to the outer class ob3ect


I" you need to %roduce the re"erence to the outer class ob0ect, you na#e the outer class "ollowed by a dot and this. Eor e&a#%le, in the class )eC*ence!))elector, any o" its #ethods can %roduce the stored re"erence to the outer class )eC*ence by saying )eC*ence!this. The resulting re"erence is auto#atically the correct ty%e. *This is known and checked at co#%ile'ti#e, so there is no run'ti#e overhead., RFSURF STIJLT+(6PTE5ITI32U So#eti#es you want to tell so#e other ob0ect to create an ob0ect o" one o" its inner classes. To do this you #ust %rovide a re"erence to the other outer class ob0ect in the ne( e&%ression, like this=

//3 c'13Parcel((.Hava // Creating instances of inner classes. "ublic class Parcel(( @ class Contents @

3;7

"rivate int i ? ((< "ublic int value-. @ return i< A A class Destination @ "rivate %tring label< Destination-%tring :hereTo. @ label ? :hereTo< A %tring rea!Label-. @ return label< A A "ublic static voi! #ain-%tringNO args. @ Parcel(( " ? ne: Parcel((-.< // Just use instance of outer class // to create an instances of the inner class3 Parcel((.Contents c ? ".ne: Contents-.< Parcel((.Destination ! ? ".ne: Destination-8TanUania8.< A A ///3>
To create an ob0ect o" the inner class directly, you don t "ollow the sa#e "or# and re"er to the outer class na#e #arcel>> as you #ight e&%ect, but instead you #ust use an ob>ect o" the outer class to #ake an ob0ect o" the inner class=

Parcel((.Contents c ? ".ne: Contents-.<


Thus, it s not %ossible to create an ob0ect o" the inner class unless you already have an ob0ect o" the outer class. This is because the ob0ect o" the inner class is Auietly connected to the ob0ect o" the outer class that it was #ade "ro#. (owever, i" you #ake a static inner class, then it doesn t need a re"erence to the outer class ob0ect. RFSURF STIJLT+(6PTE5ITIG@U

Cha ter :! Inter$aces & Inner Classes

3;8

$eaching outward from a multi.l:@ nested class


It doesn t #atter how dee%ly an inner class #ay be nested9it can trans%arently access all o" the #e#bers o" all the classes it is nested within, as seen here=
@

//3 c'13Julti&esting0ccess.Hava // &este! classes can access all #e#bers of all // levels of the classes they are neste! :ithin. class J&0 @ "rivate voi! f-. @A class 0 @ "rivate voi! g-. @A "ublic class B @ voi! h-. @ g-.< f-.< A A A A "ublic class Julti&esting0ccess @ "ublic static voi! #ain-%tringNO args. @ J&0 #na ? ne: J&0-.< J&0.0 #naa ? #na.ne: 0-.< J&0.0.B #naab ? #naa.ne: B-.< #naab.h-.< A A ///3>
/ou can see that in 1/A!A!2, the #ethods gA B and fA B are callable without any Auali"ication *des%ite the "act that they are private,. This e&a#%le also de#onstrates the synta& necessary to create ob0ects o" #ulti%ly'nested inner classes when you create the ob0ects in a di""erent class. The ! !ne($ synta& %roduces the correct sco%e so you do not have to
@ Thanks again to Martin 7anner.

3;:

Auali"y the class na#e in the constructor call. RFSURF STIJLT+(6PTE5ITIGMU

Inheriting from inner classes


Because the inner class constructor #ust attach to a re"erence o" the enclosing class ob0ect, things are slightly co#%licated when you inherit "ro# an inner class. The %roble# is that the !secret$ re"erence to the enclosing class ob0ect must be initiali1ed, and yet in the derived class there s no longer a de"ault ob0ect to attach to. The answer is to use a synta& %rovided to #ake the association e&%licit=

//3 c'13$nherit$nner.Hava // $nheriting an inner class. class \ith$nner @ class $nner @A A "ublic class $nherit$nner e6ten!s \ith$nner.$nner @ //4 $nherit$nner-. @A // \on2t co#"ile $nherit$nner-\ith$nner :i. @ :i.su"er-.< A "ublic static voi! #ain-%tringNO args. @ \ith$nner :i ? ne: \ith$nner-.< $nherit$nner ii ? ne: $nherit$nner-:i.< A A ///3>
/ou can see that InheritInner is e&tending only the inner class, not the outer one. But when it co#es ti#e to create a constructor, the de"ault one is no good and you can t 0ust %ass a re"erence to an enclosing ob0ect. In addition, you #ust use the synta& RFSURFSTIJLT+(6PTE5ITIGKU

enclosingClass5eference.su"er-.<
inside the constructor. This %rovides the necessary re"erence and the %rogra# will then co#%ile. RFSURFSTIJLT+(6PTE5ITIGLU

Cha ter :! Inter$aces & Inner Classes

3;;

Can inner classes be overriddenA


:hat ha%%ens when you create an inner class, then inherit "ro# the enclosing class and rede"ine the inner classO That is, is it %ossible to override an inner classO This see#s like it would be a %ower"ul conce%t, but !overriding$ an inner class as i" it were another #ethod o" the outer class doesn t really do anything=

//3 c'13BigEgg.Hava // 0n inner class cannot be overri!en // like a #etho!. class Egg @ "rotecte! class ;olk @ "ublic ;olk-. @ %yste#.out."rintln-8Egg.;olk-.8.< A A "rivate ;olk y< "ublic Egg-. @ %yste#.out."rintln-8&e: Egg-.8.< y ? ne: ;olk-.< A A "ublic class BigEgg e6ten!s Egg @ "ublic class ;olk @ "ublic ;olk-. @ %yste#.out."rintln-8BigEgg.;olk-.8.< A A "ublic static voi! #ain-%tringNO args. @ ne: BigEgg-.< A A ///3>
The de"ault constructor is synthesi1ed auto#atically by the co#%iler, and this calls the base'class de"ault constructor. /ou #ight think that since a 2ig&gg is being created, the !overridden$ version o" :olk would be used, but this is not the case. The out%ut is= RFSURFSTIJLT+(6PTE5ITIG?U

4==

&e: Egg-. Egg.;olk-.


This e&a#%le si#%ly shows that there isn t any e&tra inner class #agic going on when you inherit "ro# the outer class. The two inner classes are co#%letely se%arate entities, each in their own na#es%ace. (owever, it s still %ossible to e&%licitly inherit "ro# the inner class= RFSURF STIJLT+(6PTE5ITIGHU

//3 c'13BigEgg .Hava // Pro"er inheritance of an inner class. class Egg @ "rotecte! class ;olk @ "ublic ;olk-. @ %yste#.out."rintln-8Egg .;olk-.8.< A "ublic voi! f-. @ %yste#.out."rintln-8Egg .;olk.f-.8.< A A "rivate ;olk y ? ne: ;olk-.< "ublic Egg -. @ %yste#.out."rintln-8&e: Egg -.8.< A "ublic voi! insert;olk-;olk yy. @ y ? yy< A "ublic voi! g-. @ y.f-.< A A "ublic class BigEgg e6ten!s Egg @ "ublic class ;olk e6ten!s Egg .;olk @ "ublic ;olk-. @ %yste#.out."rintln-8BigEgg .;olk-.8.< A "ublic voi! f-. @ %yste#.out."rintln-8BigEgg .;olk.f-.8.< A A "ublic BigEgg -. @ insert;olk-ne: ;olk-..< A "ublic static voi! #ain-%tringNO args. @ Egg e ? ne: BigEgg -.<

Cha ter :! Inter$aces & Inner Classes

4=1

e .g-.< A A ///3>
Cow 2ig&ggI!:olk e&%licitly e4ten's &ggI!:olk and overrides its #ethods. The #ethod insert:olkA B allows 2ig&ggI to u%cast one o" its own :olk ob0ects into the y re"erence in &ggI, so when gA B calls y!fA B the overridden version o" fA B is used. The out%ut is=

Egg .;olk-. &e: Egg -. Egg .;olk-. BigEgg .;olk-. BigEgg .;olk.f-.
The second call to &ggI!:olkA B is the base'class constructor call o" the 2ig&ggI!:olk constructor. /ou can see that the overridden version o" f A B is used when gA B is called. RFSURFSTIJLT+(6PTE5ITIG3U

Inner class identifiers


Since every class %roduces a !class "ile that holds all the in"or#ation about how to create ob0ects o" this ty%e *this in"or#ation %roduces a !#eta'class$ called the -lass ob0ect,, you #ight guess that inner classes #ust also %roduce !class "iles to contain the in"or#ation "or their -lass ob0ects. The na#es o" these "ilesFclasses have a strict "or#ula= the na#e o" the enclosing class, "ollowed by a [` , "ollowed by the na#e o" the inner class. Eor e&a#%le, the !class "iles created by InheritInner!8ava include=

$nherit$nner.class \ith$nnerc$nner.class \ith$nner.class


I" inner classes are anony#ous, the co#%iler si#%ly starts generating nu#bers as inner class identi"iers. I" inner classes are nested within inner classes, their na#es are si#%ly a%%ended a"ter a [` and the outer class identi"ier*s,. RFSURFSTIJLT+(6PTE5ITIGGU

4=2

6lthough this sche#e o" generating internal na#es is si#%le and straight"orward, it s also robust and handles #ost situations @. Since it is the standard na#ing sche#e "or Java, the generated "iles are auto#atically %lat"or#'inde%endent. *Cote that the Java co#%iler is changing your inner classes in all sorts o" other ways in order to #ake the# work., RFSURFSTIJLT+(6PTE5ITIGIU

Wh: inner classesA


6t this %oint you ve seen a lot o" synta& and se#antics describing the way inner classes work, but this doesn t answer the Auestion o" why they e&ist. :hy did Sun go to so #uch trouble to add this "unda#ental language "eatureO RFSURFSTIJLT+(6PTE5ITIG2U Ty%ically, the inner class inherits "ro# a class or i#%le#ents an interface, and the code in the inner class #ani%ulates the outer class ob0ect that it was created within. So you could say that an inner class %rovides a kind o" window into the outer class. RFSURF STIJLT+(6PTE5ITII@U 6 Auestion that cuts to the heart o" inner classes is this= i" I 0ust need a re"erence to an interface, why don t I 0ust #ake the outer class i#%le#ent that interfaceO The answer is !I" that s all you need, then that s how you should do it.$ So what is it that distinguishes an inner class i#%le#enting an interface "ro# an outer class i#%le#enting the sa#e interfaceO The answer is that you can t always have the convenience o" interfaces9so#eti#es you re working with i#%le#entations. So the #ost co#%elling reason "or inner classes is=

Each inner class can inde endentl) inherit $rom an im lementation' ThusD the inner class is not limited b) ,hether the outer class is alread) inheriting $rom an im lementation'
:ithout the ability that inner classes %rovide to inherit9in e""ect9"ro# #ore than one concrete or abstract class, so#e design and %rogra##ing %roble#s would be intractable. So one way to look at the
@ )n the other hand, [d is a #eta'character to the 4ni& shell and so you ll so#eti#es have

trouble when listing the !class "iles. This is a bit strange co#ing "ro# Sun, a 4ni&'based co#%any. My guess is that they weren t considering this issue, but instead thought you d naturally "ocus on the source'code "iles.

Cha ter :! Inter$aces & Inner Classes

4=3

inner class is as the co#%letion o" the solution o" the #ulti%le'inheritance %roble#. Inter"aces solve %art o" the %roble#, but inner classes e""ectively allow !#ulti%le i#%le#entation inheritance.$ That is, inner classes e""ectively allow you to inherit "ro# #ore than one non' interface. RF SURFSTIJLT+(6PTE5ITIIMU To see this in #ore detail, consider a situation where you have two inter"aces that #ust so#ehow be i#%le#ented within a class. Because o" the "le&ibility o" inter"aces, you have two choices= a single class or an inner class=

//3 c'13Julti$nterfaces.Hava // T:o :ays that a class can // i#"le#ent #ulti"le interfaces. interface 0 @A interface B @A class 9 i#"le#ents 0, B @A class ; i#"le#ents 0 @ B #akeB-. @ // 0nony#ous inner class3 return ne: B-. @A< A A "ublic class Julti$nterfaces @ static voi! takes0-0 a. @A static voi! takesB-B b. @A "ublic static voi! #ain-%tringNO args. @ 9 6 ? ne: 9-.< ; y ? ne: ;-.< takes0-6.< takes0-y.< takesB-6.< takesB-y.#akeB-..< A A ///3>

4=4

)" course, this assu#es that the structure o" your code #akes logical sense either way. (owever, you ll ordinarily have so#e kind o" guidance "ro# the nature o" the %roble# about whether to use a single class or an inner class. But without any other constraints, in the above e&a#%le the a%%roach you take doesn t really #ake #uch di""erence "ro# an i#%le#entation stand%oint. Both o" the# work. RFSURF STIJLT+(6PTE5ITIIKU (owever, i" you have abstract or concrete classes instead o" interfaces, you are suddenly li#ited to using inner classes i" your class #ust so#ehow i#%le#ent both o" the others=

//3 c'13Julti$#"le#entation.Hava // \ith concrete or abstract classes, inner // classes are the only :ay to "ro!uce the effect // of 8#ulti"le i#"le#entation inheritance.8 class C @A abstract class D @A class T e6ten!s C @ D #akeD-. @ return ne: D-. @A< A A "ublic class Julti$#"le#entation @ static voi! takesC-C c. @A static voi! takesD-D !. @A "ublic static voi! #ain-%tringNO args. @ T U ? ne: T-.< takesC-U.< takesD-U.#akeD-..< A A ///3>
I" you didn t need to solve the !#ulti%le i#%le#entation inheritance$ %roble#, you could conceivably code around everything else without the need "or inner classes. But with inner classes you have these additional "eatures= RFSURFSTIJLT+(6PTE5ITIILU

Cha ter :! Inter$aces & Inner Classes

4=5

-4)

The inner class can have #ulti%le instances, each with its own state in"or#ation that is inde%endent o" the in"or#ation in the outer class ob0ect. RFSURFSTIJLT+(6PTE5ITII?U In a single outer class you can have several inner classes, each o" which i#%le#ent the sa#e interface or inherit "ro# the sa#e class in a di""erent way. 6n e&a#%le o" this will be shown shortly. RFSURFSTIJLT+(6PTE5ITIIHU The %oint o" creation o" the inner class ob0ect is not tied to the creation o" the outer class ob0ect. RFSURF STIJLT+(6PTE5ITII3U There is no %otentially con"using !is'a$ relationshi% with the inner class; it s a se%arate entity. RFSURFSTIJLT+(6PTE5ITIIGU

-5)

-6)

47)

6s an e&a#%le, i" )eC*ence!8ava did not use inner classes, you d have to say !a )eC*ence is a )elector,$ and you d only be able to have one )elector in e&istence "or a %articular )eC*ence. 6lso, you can have a second #ethod, get$)electorA B, that %roduces a )elector that #oves backward through the seAuence. This kind o" "le&ibility is only available with inner classes. RFSURFSTIJLT+(6PTE5ITIIIU

Closures L Callbacks
6 closure is a callable ob0ect that retains in"or#ation "ro# the sco%e in which it was created. Ero# this de"inition, you can see that an inner class is an ob0ect'oriented closure, because it doesn t 0ust contain each %iece o" in"or#ation "ro# the outer class ob0ect *!the sco%e in which it was created$,, but it auto#atically holds a re"erence back to the whole outer class ob0ect, where it has %er#ission to #ani%ulate all the #e#bers, even private ones. RFSURFSTIJLT+(6PTE5ITII2U )ne o" the #ost co#%elling argu#ents #ade to include so#e kind o" %ointer #echanis# in Java was to allow callbacks. :ith a callback, so#e other ob0ect is given a %iece o" in"or#ation that allows it to call back into the originating ob0ect at so#e later %oint. This is a very %ower"ul conce%t, as you will see in +ha%ters ML and M3. I" a callback is i#%le#ented using a %ointer, however, you #ust rely on the %rogra##er to behave and not #isuse the %ointer. 6s you ve seen by now, Java tends to be #ore care"ul

4=7

than that, so %ointers were not included in the language. RFSURF STIJLT+(6PTE5ITI2@U The closure %rovided by the inner class is a %er"ect solution; #ore "le&ible and "ar sa"er than a %ointer. (ere s a si#%le e&a#%le=

//3 c'13Callbacks.Hava // Ysing inner classes for callbacks interface $ncre#entable @ voi! incre#ent-.< A // Wery si#"le to Hust i#"le#ent the interface3 class Callee( i#"le#ents $ncre#entable @ "rivate int i ? '< "ublic voi! incre#ent-. @ iKK< %yste#.out."rintln-i.< A A class Jy$ncre#ent @ "ublic voi! incre#ent-. @ %yste#.out."rintln-8Gther o"eration8.< A "ublic static voi! f-Jy$ncre#ent #i. @ #i.incre#ent-.< A A // $f your class #ust i#"le#ent incre#ent-. in // so#e other :ay, you #ust use an inner class3 class Callee e6ten!s Jy$ncre#ent @ "rivate int i ? '< "rivate voi! incr-. @ iKK< %yste#.out."rintln-i.< A "rivate class Closure i#"le#ents $ncre#entable @ "ublic voi! incre#ent-. @ incr-.< A

Cha ter :! Inter$aces & Inner Classes

4=8

A $ncre#entable getCallback5eference-. @ return ne: Closure-.< A A class Caller @ "rivate $ncre#entable callback5eference< Caller-$ncre#entable cbh. @ callback5eference ? cbh< A voi! go-. @ callback5eference.incre#ent-.< A A "ublic class Callbacks @ "ublic static voi! #ain-%tringNO args. @ Callee( c( ? ne: Callee(-.< Callee c ? ne: Callee -.< Jy$ncre#ent.f-c .< Caller caller( ? ne: Caller-c(.< Caller caller ? ne: Caller-c .getCallback5eference-..< caller(.go-.< caller(.go-.< caller .go-.< caller .go-.< A A ///3>
This e&a#%le also %rovides a "urther distinction between i#%le#enting an inter"ace in an outer class vs. doing so in an inner class. -allee> is clearly the si#%ler solution in ter#s o" the code. -alleeI inherits "ro# 1yIncrement which already has a di""erent incrementA B #ethod which does so#ething unrelated to that which is e&%ected by the Incrementable inter"ace. :hen 1yIncrement is inherited into -alleeI, incrementA B can t be overridden "or use by Incrementable, so you re "orced to %rovide a se%arate i#%le#entation using an inner class. 6lso note that when you create an inner class you do not add to or #odi"y the inter"ace o" the outer class. RFSURFSTIJLT+(6PTE5ITI2MU

4=:

Cotice that everything e&ce%t get-allback$eferenceA B in -alleeI is private. To allow an) connection to the outside world, the interface Incrementable is essential. (ere you can see how interfaces allow "or a co#%lete se%aration o" inter"ace "ro# i#%le#entation. RFSURF STIJLT+(6PTE5ITI2KU The inner class -los*re si#%ly i#%le#ents Incrementable to %rovide a hook back into -alleeI9but a sa"e hook. :hoever gets the Incrementable re"erence can, o" course, only call incrementA B and has no other abilities *unlike a %ointer, which would allow you to run wild,. RFSURFSTIJLT+(6PTE5ITI2LU

-aller takes an Incrementable re"erence in its constructor *although


the ca%turing o" the callback re"erence could ha%%en at any ti#e, and then, so#eti#e latter, uses the re"erence to !call back$ into the -allee class. RFSURFSTIJLT+(6PTE5ITI2?U The value o" the callback is in its "le&ibility9you can dyna#ically decide what "unctions will be called at run'ti#e. The bene"it o" this will beco#e #ore evident in +ha%ter ML, where callbacks are used everywhere to i#%le#ent gra%hical user inter"ace *84I, "unctionality. RFSURF STIJLT+(6PTE5ITI2HU

Inner classes L control frameworks


6 #ore concrete e&a#%le o" the use o" inner classes can be "ound in so#ething that I will re"er to here as a control $rame,ork. RFSURF STIJLT+(6PTE5ITI23U 6n a lication $rame,ork is a class or a set o" classes that s designed to solve a %articular ty%e o" %roble#. To a%%ly an a%%lication "ra#ework, you inherit "ro# one or #ore classes and override so#e o" the #ethods. The code you write in the overridden #ethods custo#i1es the general solution %rovided by that a%%lication "ra#ework, in order to solve your s%eci"ic %roble#. The control "ra#ework is a %articular ty%e o" a%%lication "ra#ework do#inated by the need to res%ond to events; a syste# that %ri#arily res%onds to events is called an event/driven s)stem. )ne o" the #ost i#%ortant %roble#s in a%%lication %rogra##ing is the gra%hical user inter"ace *84I,, which is al#ost entirely event'

Cha ter :! Inter$aces & Inner Classes

4=;

driven. 6s you will see in +ha%ter ML, the Java Swing library is a control "ra#ework that elegantly solves the 84I %roble# and that heavily uses inner classes. RFSURFSTIJLT+(6PTE5ITI2GU To see how inner classes allow the si#%le creation and use o" control "ra#eworks, consider a control "ra#ework whose 0ob is to e&ecute events whenever those events are !ready.$ 6lthough !ready$ could #ean anything, in this case the de"ault will be based on clock ti#e. :hat "ollows is a control "ra#ework that contains no s%eci"ic in"or#ation about what it s controlling. Eirst, here is the inter"ace that describes any control event. It s an abstract class instead o" an actual interface because the de"ault behavior is to %er"or# the control based on ti#e, so so#e o" the i#%le#entation can be included here=

//3 c'13controller3Event.Hava // The co##on #etho!s for any control event. "ackage c'1.controller< abstract "ublic class Event @ "rivate long evtTi#e< "ublic Event-long eventTi#e. @ evtTi#e ? eventTi#e< A "ublic boolean rea!y-. @ return %yste#.currentTi#eJillis-. Q? evtTi#e< A abstract "ublic voi! action-.< abstract "ublic %tring !escri"tion-.< A ///3>
The constructor si#%ly ca%tures the ti#e when you want the &vent to run, while rea'yA B tells you when it s ti#e to run it. )" course, rea'yA B could be overridden in a derived class to base the &vent on so#ething other than ti#e. RFSURFSTIJLT+(6PTE5ITI2IU

actionA B is the #ethod that s called when the &vent is rea'yA B, and 'escriptionA B gives te&tual in"or#ation about the &vent. RFSURF
STIJLT+(6PTE5ITI22U The "ollowing "ile contains the actual control "ra#ework that #anages and "ires events. The "irst class is really 0ust a !hel%er$ class whose 0ob is

41=

to hold &vent ob0ects. /ou can re%lace it with any a%%ro%riate container, and in +ha%ter 2 you ll discover other containers that will do the trick without reAuiring you to write this e&tra code=

//3 c'13controller3Controller.Hava // 0long :ith Event, the generic // fra#e:ork for all control syste#s3 "ackage c'1.controller< // This is Hust a :ay to hol! Event obHects. class Event%et @ "rivate EventNO events ? ne: EventN(''O< "rivate int in!e6 ? '< "rivate int ne6t ? '< "ublic voi! a!!-Event e. @ if-in!e6 Q? events.length. return< // -$n real life, thro: e6ce"tion. eventsNin!e6KKO ? e< A "ublic Event get&e6t-. @ boolean loo"e! ? false< int start ? ne6t< !o @ ne6t ? -ne6t K (. V events.length< // %ee if it has loo"e! to the beginning3 if-start ?? ne6t. loo"e! ? true< // $f it loo"s "ast start, the list // is e#"ty3 if--ne6t ?? -start K (. V events.length. DD loo"e!. return null< A :hile-eventsNne6tO ?? null.< return eventsNne6tO< A "ublic voi! re#oveCurrent-. @ eventsNne6tO ? null< A A "ublic class Controller @ "rivate Event%et es ? ne: Event%et-.<

Cha ter :! Inter$aces & Inner Classes

411

"ublic voi! a!!Event-Event c. @ es.a!!-c.< A "ublic voi! run-. @ Event e< :hile--e ? es.get&e6t-.. 4? null. @ if-e.rea!y-.. @ e.action-.< %yste#.out."rintln-e.!escri"tion-..< es.re#oveCurrent-.< A A A A ///3> &vent)et arbitrarily holds M@@ &vents. *I" a !real$ container "ro#
+ha%ter 2 is used here you don t need to worry about its #a&i#u# si1e, since it will resi1e itsel",. The in'e4 is used to kee% track o" the ne&t available s%ace, and ne4t is used when you re looking "or the ne&t &vent in the list, to see whether you ve loo%ed around. This is i#%ortant during a call to get/e4tA B, because &vent ob0ects are re#oved "ro# the list *using remove-*rrentA B, once they re run, so get/e4tA B will encounter holes in the list as it #oves through it. RFSURF STIJLT+(6PTE5ITIM@@U Cote that remove-*rrentA B doesn t 0ust set so#e "lag indicating that the ob0ect is no longer in use. Instead, it sets the re"erence to n*ll. This is i#%ortant because i" the garbage collector sees a re"erence that s still in use then it can t clean u% the ob0ect. I" you think your re"erences #ight hang around *as they would here,, then it s a good idea to set the# to n*ll to give the garbage collector %er#ission to clean the# u%. RFSURF STIJLT+(6PTE5ITIM@MU

-ontroller is where the actual work goes on. It uses an &vent)et to hold its &vent ob0ects, and a''&ventA B allows you to add new events to this list. But the i#%ortant #ethod is r*nA B. This #ethod loo%s through the &vent)et, hunting "or an &vent ob0ect that s rea'yA B to run. Eor each one it "inds rea'yA B, it calls the actionA B #ethod, %rints out the 'escriptionA B, and then re#oves the &vent "ro# the list. RFSURF STIJLT+(6PTE5ITIM@KU

412

Cote that so "ar in this design you know nothing about e&actly ,hat an &vent does. 6nd this is the cru& o" the design; how it !se%arates the things that change "ro# the things that stay the sa#e.$ )r, to use #y ter#, the !vector o" change$ is the di""erent actions o" the various kinds o" &vent ob0ects, and you e&%ress di""erent actions by creating di""erent &vent subclasses *in %esign Patterns %arlance, the &vent subclasses re%resent the Command Pattern,. RFSURFSTIJLT+(6PTE5ITIM@LU This is where inner classes co#e into %lay. They allow two things=

4()

To create the entire i#%le#entation o" a control'"ra#ework a%%lication in a single class, thereby enca%sulating everything that s uniAue about that i#%le#entation. Inner classes are used to e&%ress the #any di""erent kinds o" actionA B necessary to solve the %roble#. In addition, the "ollowing e&a#%le uses private inner classes so the i#%le#entation is co#%letely hidden and can be changed with i#%unity. RFSURFSTIJLT+(6PTE5ITIM@?U Inner classes kee% this i#%le#entation "ro# beco#ing awkward, since you re able to easily access any o" the #e#bers in the outer class. :ithout this ability the code #ight beco#e un%leasant enough that you d end u% seeking an alternative. RFSURF STIJLT+(6PTE5ITIM@HU

4!)

+onsider a %articular i#%le#entation o" the control "ra#ework designed to control greenhouse "unctions @. Each action is entirely di""erent= turning lights, water, and ther#ostats on and o"", ringing bells, and restarting the syste#. But the control "ra#ework is designed to easily isolate this di""erent code. Inner classes allow you to have #ulti%le derived versions o" the sa#e base class, &vent, within a single class. Eor each ty%e o" action you inherit a new &vent inner class, and write the control code inside o" actionA B. RFSURFSTIJLT+(6PTE5ITIM@3U 6s is ty%ical with an a%%lication "ra#ework, the class

"reenho*se-ontrols is inherited "ro# -ontroller= //3 c'13areenhouseControls.Hava // This "ro!uces a s"ecific a""lication of the
@ Eor so#e reason this has always been a %leasing %roble# "or #e to solve; it ca#e "ro# #y earlier book C++ Inside & Out, but Java allows a #uch #ore elegant solution.

Cha ter :! Inter$aces & Inner Classes

413

// control syste#, all in a single class. $nner // classes allo: you to enca"sulate !ifferent // functionality for each ty"e of event. i#"ort c'1.controller.B< "ublic class areenhouseControls e6ten!s Controller @ "rivate boolean light ? false< "rivate boolean :ater ? false< "rivate %tring ther#ostat ? 8Day8< "rivate class LightGn e6ten!s Event @ "ublic LightGn-long eventTi#e. @ su"er-eventTi#e.< A "ublic voi! action-. @ // Put har!:are control co!e here to // "hysically turn on the light. light ? true< A "ublic %tring !escri"tion-. @ return 8Light is on8< A A "rivate class LightGff e6ten!s Event @ "ublic LightGff-long eventTi#e. @ su"er-eventTi#e.< A "ublic voi! action-. @ // Put har!:are control co!e here to // "hysically turn off the light. light ? false< A "ublic %tring !escri"tion-. @ return 8Light is off8< A A "rivate class \aterGn e6ten!s Event @ "ublic \aterGn-long eventTi#e. @ su"er-eventTi#e.< A "ublic voi! action-. @

414

// Put har!:are control co!e here :ater ? true< A "ublic %tring !escri"tion-. @ return 8areenhouse :ater is on8< A A "rivate class \aterGff e6ten!s Event @ "ublic \aterGff-long eventTi#e. @ su"er-eventTi#e.< A "ublic voi! action-. @ // Put har!:are control co!e here :ater ? false< A "ublic %tring !escri"tion-. @ return 8areenhouse :ater is off8< A A "rivate class Ther#ostat&ight e6ten!s Event @ "ublic Ther#ostat&ight-long eventTi#e. @ su"er-eventTi#e.< A "ublic voi! action-. @ // Put har!:are control co!e here ther#ostat ? 8&ight8< A "ublic %tring !escri"tion-. @ return 8Ther#ostat on night setting8< A A "rivate class Ther#ostatDay e6ten!s Event @ "ublic Ther#ostatDay-long eventTi#e. @ su"er-eventTi#e.< A "ublic voi! action-. @ // Put har!:are control co!e here ther#ostat ? 8Day8< A "ublic %tring !escri"tion-. @ return 8Ther#ostat on !ay setting8<

Cha ter :! Inter$aces & Inner Classes

415

A A // 0n e6a#"le of an action-. that inserts a // ne: one of itself into the event list3 "rivate int rings< "rivate class Bell e6ten!s Event @ "ublic Bell-long eventTi#e. @ su"er-eventTi#e.< A "ublic voi! action-. @ // 5ing every secon!s, 2rings2 ti#es3 %yste#.out."rintln-8Bing48.< if---rings Q '. a!!Event-ne: Bell%yste#.currentTi#eJillis-. K '''..< A "ublic %tring !escri"tion-. @ return 85ing bell8< A A "rivate class 5estart e6ten!s Event @ "ublic 5estart-long eventTi#e. @ su"er-eventTi#e.< A "ublic voi! action-. @ long t# ? %yste#.currentTi#eJillis-.< // $nstea! of har!-:iring, you coul! "arse // configuration infor#ation fro# a te6t // file here3 rings ? ,< a!!Event-ne: Ther#ostat&ight-t#..< a!!Event-ne: LightGn-t# K ('''..< a!!Event-ne: LightGff-t# K '''..< a!!Event-ne: \aterGn-t# K )'''..< a!!Event-ne: \aterGff-t# K 1'''..< a!!Event-ne: Bell-t# K C'''..< a!!Event-ne: Ther#ostatDay-t# K (''''..< // Can even a!! a 5estart obHect4 a!!Event-ne: 5estart-t# K ''''..< A "ublic %tring !escri"tion-. @

417

return 85estarting syste#8< A A "ublic static voi! #ain-%tringNO args. @ areenhouseControls gc ? ne: areenhouseControls-.< long t# ? %yste#.currentTi#eJillis-.< gc.a!!Event-gc.ne: 5estart-t#..< gc.run-.< A A ///3>
Cote that light, (ater, thermostat, and rings all belong to the outer class "reenho*se-ontrols, and yet the inner classes can access those "ields without Auali"ication or s%ecial %er#ission. 6lso, #ost o" the actionA B #ethods involve so#e sort o" hardware control, which would #ost likely involve calls to non'Java code. RFSURF STIJLT+(6PTE5ITIM@GU Most o" the &vent classes look si#ilar, but 2ell and $estart are s%ecial. 2ell rings, and i" it hasn t yet rung enough ti#es it adds a new 2ell ob0ect to the event list, so it will ring again later. Cotice how inner classes almost look like #ulti%le inheritance= 2ell has all the #ethods o" &vent and it also a%%ears to have all the #ethods o" the outer class "reenho*se-ontrols. RFSURFSTIJLT+(6PTE5ITIM@IU

$estart is res%onsible "or initiali1ing the syste#, so it adds all the a%%ro%riate events. )" course, a #ore "le&ible way to acco#%lish this is to avoid hard'coding the events and instead read the# "ro# a "ile. *6n e&ercise in +ha%ter MM asks you to #odi"y this e&a#%le to do 0ust that., Since $estartA B is 0ust another &vent ob0ect, you can also add a $estart ob0ect within $estart!actionA B so that the syste# regularly restarts itsel". 6nd all you need to do in mainA B is create a "reenho*se-ontrols ob0ect and add a $estart ob0ect to get it going. RFSURFSTIJLT+(6PTE5ITIM@2U This e&a#%le should #ove you a long way toward a%%reciating the value o" inner classes, es%ecially when used within a control "ra#ework. (owever, in +ha%ter ML you ll see how elegantly inner classes are used to describe the actions o" a gra%hical user inter"ace. By the ti#e you "inish that cha%ter you should be "ully convinced.

Cha ter :! Inter$aces & Inner Classes

418

1ummar:
Inter"aces and inner classes are #ore so%histicated conce%ts than what you ll "ind in #any ))P languages. Eor e&a#%le, there s nothing like the# in +<<. Together, they solve the sa#e %roble# that +<< atte#%ts to solve with its #ulti%le inheritance *MI, "eature. (owever, MI in +<< turns out to be rather di""icult to use, while Java inter"aces and inner classes are, by co#%arison, #uch #ore accessible. RFSURF STIJLT+(6PTE5ITIMM@U 6lthough the "eatures the#selves are reasonably straight"orward, the use o" these "eatures is a design issue, #uch the sa#e as %oly#or%his#. )ver ti#e, you ll beco#e better at recogni1ing situations where you should use an inter"ace, or an inner class, or both. But at this %oint in this book you should at least be co#"ortable with the synta& and se#antics. 6s you see these language "eatures in use you ll eventually internali1e the#. RFSURF STIJLT+(6PTE5ITIMMMU

/0ercises
Solutions to selected e&ercises can be "ound in the electronic docu#entThe Thinking in Java "nnotated Solution @uide, available "or a s#all "ee "ro# ,,,'0ruceEckel'com.

6,) Prove that the "ields in an interface are i#%licitly static and
final. RFSURFSTIJLT+(6PTE5ITIMMKU

6-) +reate an interface containing three #ethods, in its own


package. I#%le#ent the inter"ace in a di""erent package. RF
SURFSTIJLT+(6PTE5ITIMMLU

64) Prove that all the #ethods in an interface are auto#atically


p*blic. RFSURFSTIJLT+(6PTE5ITIMM?U

65) In cDZ<)an'(ich!8ava, create an inter"ace called FastFoo'


*with a%%ro%riate #ethods, and change )an'(ich so that it also i#%le#ents FastFoo'. RFSURFSTIJLT+(6PTE5ITIMMHU

66) +reate three interfaces, each with two #ethods. Inherit a new
interface "ro# the three, adding a new #ethod. +reate a class by

41:

i#%le#enting the new interface and also inheriting "ro# a concrete class. Cow write "our #ethods, each o" which takes one o" the "our interfaces as an argu#ent. In mainA B, create an ob0ect o" your class and %ass it to each o" the #ethods. RFSURF STIJLT+(6PTE5ITIMM3U

(77) Modi"y E&ercise H by creating an abstract class and inheriting


that into the derived class. RFSURFSTIJLT+(6PTE5ITIMMGU

(7() Modi"y 1*sic@!8ava by adding a #layable interface.


5e#ove Move the playA B declaration "ro# Instr*ment to #layable. 6dd #layable to the derived classes by including it in the implements list. +hange t*neA B so that it takes a #layable instead o" an Instr*ment. RFSURFSTIJLT+(6PTE5ITIMMIU

(7!) +hange E&ercise 3 in +ha%ter G so that $o'ent is an


interface. RFSURFSTIJLT+(6PTE5ITIMM2U

(7*) In A'vent*re!8ava, add an interface called -an-limb,


"ollowing the "or# o" the other inter"aces. RFSURF STIJLT+(6PTE5ITIMK@U

(7+) :rite a %rogra# that i#%orts and uses 1onthI!8ava. RFSURF


STIJLT+(6PTE5ITIMKMU

(7,) Eollowing the e&a#%le given in 1onthI!8ava, create an


enu#eration o" days o" the week. RFSURF STIJLT+(6PTE5ITIMKKU

(7-) +reate an interface with at least one #ethod, in its own


%ackage. +reate a class in a se%arate %ackage. 6dd a protecte' inner class that i#%le#ents the interface. In a third %ackage, inherit "ro# your class and, inside a #ethod, return an ob0ect o" the protecte' inner class, u%casting to the interface during the return. RFSURFSTIJLT+(6PTE5ITIMKLU

(74) +reate an interface with at least one #ethod, and i#%le#ent


that interface by de"ining an inner class within a #ethod, which returns a re"erence to your interface. RFSURF STIJLT+(6PTE5ITIMK?U

Cha ter :! Inter$aces & Inner Classes

41;

(75) 5e%eat E&ercise ML but de"ine the inner class within a sco%e
within a #ethod. RFSURFSTIJLT+(6PTE5ITIMKHU

(76) 5e%eat E&ercise ML using an anony#ous inner class. RFSURF


STIJLT+(6PTE5ITIMK3U

((7) +reate a private inner class that i#%le#ents a p*blic


interface. :rite a #ethod that returns a re"erence to an instance o" the private inner class, u%cast to the interface. Show that the
inner class is co#%letely hidden by trying to downcast to it. RF SURFSTIJLT+(6PTE5ITIMKGU

((() +reate a class with a nonde"ault constructor and no de"ault


constructor. +reate a second class that has a #ethod which returns a re"erence to the "irst class. +reate the ob0ect to return by #aking an anony#ous inner class that inherits "ro# the "irst class. RFSURFSTIJLT+(6PTE5ITIMKIU

((!) +reate a class with a private "ield and a private #ethod.


+reate an inner class with a #ethod that #odi"ies the outer class "ield and calls the outer class #ethod. In a second outer class #ethod, create an ob0ect o" the inner class and call it s #ethod, then show the e""ect on the outer class ob0ect. RFSURF STIJLT+(6PTE5ITIMK2U

((*) 5e%eat E&ercise MI using an anony#ous inner class. RFSURF


STIJLT+(6PTE5ITIML@U

((+) +reate a class containing a static inner class. In mainA B,


create an instance o" the inner class. RFSURF STIJLT+(6PTE5ITIMLMU

((,) +reate an interface containing a static inner class.


I#%le#ent this interface and create an instance o" the inner class. RFSURFSTIJLT+(6PTE5ITIMLKU

((-) +reate a class containing an inner class that itsel" contains an


inner class. 5e%eat this using static inner classes. Cote the na#es o" the !class "iles %roduced by the co#%iler. RFSURF STIJLT+(6PTE5ITIMLLU

42=

((4) +reate a class with an inner class. In a se%arate class, #ake an


instance o" the inner class. RFSURFSTIJLT+(6PTE5ITIML?U

((5) +reate a class with an inner class that has a nonde"ault


constructor. +reate a second class with an inner class that inherits "ro# the "irst inner class. RFSURFSTIJLT+(6PTE5ITIMLHU

((6) 5e%air the %roble# in 0in'&rror!8ava. RFSURF


STIJLT+(6PTE5ITIML3U

(!7) Modi"y )eC*ence!8ava by adding a #ethod get$)electorA B


that %roduces a di""erent i#%le#entation o" the )elector interface that #oves backward through the seAuence "ro# the end to the beginning. RFSURFSTIJLT+(6PTE5ITIMLGU

(!() +reate an interface U with three #ethods. +reate a class A


with a #ethod that %roduces a re"erence to a U by building an anony#ous inner class. +reate a second class 2 that contains an array o" U. 2 should have one #ethod that acce%ts and stores a re"erence to a U in the array, a second #ethod that sets a re"erence in the array *s%eci"ied by the #ethod argu#ent, to n*ll and a third #ethod that #oves through the array and calls the #ethods in U. In mainA B, create a grou% o" A ob0ects and a single 2. Eill the 2 with U re"erences %roduced by the A ob0ects. 4se the 2 to call back into all the A ob0ects. 5e#ove so#e o" the U re"erences "ro# the 2. RFSURFSTIJLT+(6PTE5ITIMLIU

(!!) In "reenho*se-ontrols!8ava, add &vent inner classes that


turn "ans on and o"". RFSURFSTIJLT+(6PTE5ITIML2U

(!*) Show that an inner class has access to the private ele#ents o"
its outer class. 7eter#ine whether the reverse is true. RFSU

Cha ter :! Inter$aces & Inner Classes

421

6: >olding Gour Ob3ects


RFSTIJLT+(6PTE52TI@UIt s a "airly si#%le %rogra# that has only a "i&ed Auantity o" ob0ects with known li"eti#es.
In general, your %rogra#s will always be creating new ob0ects based on so#e criteria that will be known only at the ti#e the %rogra# is running. /ou won t know until run'ti#e the Auantity or even the e&act ty%e o" the ob0ects you need. To solve the general %rogra##ing %roble#, you need to be able to create any nu#ber o" ob0ects, anyti#e, anywhere. So you can t rely on creating a na#ed re"erence to hold each one o" your ob0ects=

JyGbHect #y5eference<
since you ll never know how #any o" these you ll actually need. RFSURF STIJLT+(6PTE52TIMU To solve this rather essential %roble#, Java has several ways to hold ob0ects *or rather, re"erences to ob0ects,. The built'in ty%e is the array, which has been discussed be"ore. 6lso, the Java utilities library has a reasonably co#%lete set o" container classes *also known as collection classes, but because the Java K libraries use the na#e -ollection to re"er to a %articular subset o" the library, I shall use the #ore inclusive ter# !container$,. +ontainers %rovide so%histicated ways to hold and even #ani%ulate your ob0ects. RFSURFSTIJLT+(6PTE52TIKU

Arra:s
Most o" the necessary introduction to arrays is in the last section o" +ha%ter ?, which showed how you de"ine and initiali1e an array. (olding ob0ects is the "ocus o" this cha%ter, and an array is 0ust one way to hold

422

ob0ects. But there are a nu#ber o" other ways to hold ob0ects, so what #akes an array s%ecialO RFSURFSTIJLT+(6PTE52TILU There are two issues that distinguish arrays "ro# other ty%es o" containers= e""iciency and ty%e. The array is the #ost e""icient way that Java %rovides to store and rando#ly access a seAuence o" ob0ects *actually, ob0ect re"erences,. The array is a si#%le linear seAuence, which #akes ele#ent access "ast, but you %ay "or this s%eed= when you create an array ob0ect, its si1e is "i&ed and cannot be changed "or the li"eti#e o" that array ob0ect. /ou #ight suggest creating an array o" a %articular si1e and then, i" you run out o" s%ace, creating a new one and #oving all the re"erences "ro# the old one to the new one. This is the behavior o" the Array+ist class, which will be studied later in this cha%ter. (owever, because o" the overhead o" this si1e "le&ibility, an Array+ist is #easurably less e""icient than an array. RFSURFSTIJLT+(6PTE52TI?U The vector container class in +<< does know the ty%e o" ob0ects it holds, but it has a di""erent drawback when co#%ared with arrays in Java= the +<< vector s operator]^ doesn t do bounds checking, so you can run %ast the end @. In Java, you get bounds checking regardless o" whether you re using an array or a container9you ll get a $*ntime&4ception i" you e&ceed the bounds. 6s you ll learn in +ha%ter M@, this ty%e o" e&ce%tion indicates a %rogra##er error, and thus you don t need to check "or it in your code. 6s an aside, the reason the +<< vector doesn t check bounds with every access is s%eed9in Java you have the constant %er"or#ance overhead o" bounds checking all the ti#e "or both arrays and containers. RFSURFSTIJLT+(6PTE52TIHU The other generic container classes that will be studied in this cha%ter,

+ist, )et, and 1ap, all deal with ob0ects as i" they had no s%eci"ic ty%e. That is, they treat the# as ty%e .b8ect, the root class o" all classes in
Java. This works "ine "ro# one stand%oint= you need to build only one container, and any Java ob0ect will go into that container. *E&ce%t "or %ri#itives9these can be %laced in containers as constants using the Java %ri#itive wra%%er classes, or as changeable values by wra%%ing in your own class., This is the second %lace where an array is su%erior to the generic containers= when you create an array, you create it to hold a
@ It s %ossible, however, to ask how big the vector is, and the atA B #ethod does %er"or# bounds checking.

Cha ter ;! .olding Lour Ob>ects

423

s%eci"ic ty%e. This #eans that you get co#%ile'ti#e ty%e checking to %revent you "ro# %utting the wrong ty%e in, or #istaking the ty%e that you re e&tracting. )" course, Java will %revent you "ro# sending an ina%%ro%riate #essage to an ob0ect, either at co#%ile'ti#e or at run'ti#e. So it s not #uch riskier one way or the other, it s 0ust nicer i" the co#%iler %oints it out to you, "aster at run'ti#e, and there s less likelihood that the end user will get sur%rised by an e&ce%tion. RFSURF STIJLT+(6PTE52TI3U Eor e""iciency and ty%e checking it s always worth trying to use an array i" you can. (owever, when you re trying to solve a #ore general %roble# arrays can be too restrictive. 6"ter looking at arrays, the rest o" this cha%ter will be devoted to the container classes %rovided by Java. RFSURF STIJLT+(6PTE52TIGU

Arra:s are first@class ob3ects


5egardless o" what ty%e o" array you re working with, the array identi"ier is actually a re"erence to a true ob0ect that s created on the hea%. This is the ob0ect that holds the re"erences to the other ob0ects, and it can be created either i#%licitly, as %art o" the array initiali1ation synta&, or e&%licitly with a ne( e&%ression. Part o" the array ob0ect *in "act, the only "ield or #ethod you can access, is the read'only length #e#ber that tells you how #any ele#ents can be stored in that array ob0ect. The []^ synta& is the only other access that you have to the array ob0ect. RFSURF STIJLT+(6PTE52TIIU The "ollowing e&a#%le shows the various ways that an array can be initiali1ed, and how the array re"erences can be assigned to di""erent array ob0ects. It also shows that arrays o" ob0ects and arrays o" %ri#itives are al#ost identical in their use. The only di""erence is that arrays o" ob0ects hold re"erences, while arrays o" %ri#itives hold the %ri#itive values directly. RFSURFSTIJLT+(6PTE52TI2U

//3 c'C30rray%iUe.Hava // $nitialiUation D re-assign#ent of arrays. class \eeble @A // 0 s#all #ythical creature "ublic class 0rray%iUe @

424

"ublic static voi! #ain-%tringNO args. @ // 0rrays of obHects3 \eebleNO a< // &ull reference \eebleNO b ? ne: \eebleN,O< // &ull references \eebleNO c ? ne: \eebleNIO< for-int i ? '< i P c.length< iKK. cNiO ? ne: \eeble-.< // 0ggregate initialiUation3 \eebleNO ! ? @ ne: \eeble-., ne: \eeble-., ne: \eeble-. A< // Dyna#ic aggregate initialiUation3 a ? ne: \eebleNO @ ne: \eeble-., ne: \eeble-. A< %yste#.out."rintln-8a.length?8 K a.length.< %yste#.out."rintln-8b.length ? 8 K b.length.< // The references insi!e the array are // auto#atically initialiUe! to null3 for-int i ? '< i P b.length< iKK. %yste#.out."rintln-8bN8 K i K 8O?8 K bNiO.< %yste#.out."rintln-8c.length ? 8 K c.length.< %yste#.out."rintln-8!.length ? 8 K !.length.< a ? !< %yste#.out."rintln-8a.length ? 8 K a.length.< // 0rrays of "ri#itives3 intNO e< // &ull reference intNO f ? ne: intN,O< intNO g ? ne: intNIO< for-int i ? '< i P g.length< iKK. gNiO ? iBi< intNO h ? @ ((, I*, C) A< // Co#"ile error3 variable e not initialiUe!3 //4%yste#.out."rintln-8e.length?8 K e.length.< %yste#.out."rintln-8f.length ? 8 K f.length.< // The "ri#itives insi!e the array are // auto#atically initialiUe! to Uero3 for-int i ? '< i P f.length< iKK. %yste#.out."rintln-8fN8 K i K 8O?8 K fNiO.< %yste#.out."rintln-8g.length ? 8 K g.length.<

Cha ter ;! .olding Lour Ob>ects

425

%yste#.out."rintln-8h.length ? 8 K h.length.< e ? h< %yste#.out."rintln-8e.length ? 8 K e.length.< e ? ne: intNO @ (, A< %yste#.out."rintln-8e.length ? 8 K e.length.< A A ///3>
(ere s the out%ut "ro# the %rogra#=

a.length? b.length ? bN'O?null bN(O?null bN O?null bN)O?null bNIO?null c.length ? !.length ? a.length ? a.length ? f.length ? fN'O?' fN(O?' fN O?' fN)O?' fNIO?' g.length ? h.length ? e.length ? e.length ?

I ) ) ,

I ) )

The array a is initially 0ust a n*ll re"erence, and the co#%iler %revents you "ro# doing anything with this re"erence until you ve %ro%erly initiali1ed it. The array b is initiali1ed to %oint to an array o" 0eeble re"erences, but no actual 0eeble ob0ects are ever %laced in that array. (owever, you can still ask what the si1e o" the array is, since b is %ointing to a legiti#ate ob0ect. This brings u% a slight drawback= you can t "ind out how #any ele#ents are actually in the array, since length tells you only how #any ele#ents can be %laced in the array; that is, the si1e o" the array ob0ect, not the nu#ber o" ele#ents it actually holds. (owever, when

427

an array ob0ect is created its re"erences are auto#atically initiali1ed to n*ll, so you can see whether a %articular array slot has an ob0ect in it by checking to see whether it s n*ll. Si#ilarly, an array o" %ri#itives is auto#atically initiali1ed to 1ero "or nu#eric ty%es, AcharBD "or char, and false "or boolean. RFSURFSTIJLT+(6PTE52TIM@U 6rray c shows the creation o" the array ob0ect "ollowed by the assign#ent o" 0eeble ob0ects to all the slots in the array. 6rray ' shows the !aggregate initiali1ation$ synta& that causes the array ob0ect to be created *i#%licitly with ne( on the hea%, 0ust like "or array c, and initiali1ed with 0eeble ob0ects, all in one state#ent. RFSURFSTIJLT+(6PTE52TIMMU The ne&t array initiali1ation could be thought o" as a !dyna#ic aggregate initiali1ation.$ The aggregate initiali1ation used by ' #ust be used at the %oint o" ' s de"inition, but with the second synta& you can create and initiali1e an array ob0ect anywhere. Eor e&a#%le, su%%ose hi'eA B is a #ethod that takes an array o" 0eeble ob0ects. /ou could call it by saying=

hi!e-!.<
but you can also dyna#ically create the array you want to %ass as the argu#ent=

hi!e-ne: \eebleNO @ ne: \eeble-., ne: \eeble-. A.<


In so#e situations this new synta& %rovides a #ore convenient way to write code. RFSURFSTIJLT+(6PTE52TIMKU The e&%ression=

a ? !<
shows how you can take a re"erence that s attached to one array ob0ect and assign it to another array ob0ect, 0ust as you can do with any other ty%e o" ob0ect re"erence. Cow both a and ' are %ointing to the sa#e array ob0ect on the hea%. RFSURFSTIJLT+(6PTE52TIMLU The second %art o" Array)i7e!8ava shows that %ri#itive arrays work 0ust like ob0ect arrays e*ce t that %ri#itive arrays hold the %ri#itive values directly. RFSURFSTIJLT+(6PTE52TIM?U

Cha ter ;! .olding Lour Ob>ects

428

Containers of .rimitives
+ontainer classes can hold only re"erences to ob0ects. 6n array, however, can be created to hold %ri#itives directly, as well as re"erences to ob0ects. It is %ossible to use the !wra%%er$ classes such as Integer, o*ble, etc. to %lace %ri#itive values inside a container, but the wra%%er classes "or %ri#itives can be awkward to use. In addition, it s #uch #ore e""icient to create and access an array o" %ri#itives than a container o" wra%%ed %ri#itives. RFSURFSTIJLT+(6PTE52TIMHU )" course, i" you re using a %ri#itive ty%e and you need the "le&ibility o" a container that auto#atically e&%ands when #ore s%ace is needed, the array won t work and you re "orced to use a container o" wra%%ed %ri#itives. /ou #ight think that there should be a s%eciali1ed ty%e o" Array+ist "or each o" the %ri#itive data ty%es, but Java doesn t %rovide this "or you. So#e sort o" te#%lati1ing #echanis# #ight so#eday %rovide a better way "or Java to handle this %roble#. @ RFSURF STIJLT+(6PTE52TIM3U

$eturning an arra:
Su%%ose you re writing a #ethod and you don t 0ust want to return 0ust one thing, but a whole bunch o" things. Danguages like + and +<< #ake this di""icult because you can t 0ust return an array, only a %ointer to an array. This introduces %roble#s because it beco#es #essy to control the li"eti#e o" the array, which easily leads to #e#ory leaks. RFSURF STIJLT+(6PTE52TIMGU Java takes a si#ilar a%%roach, but you 0ust !return an array.$ 6ctually, o" course, you re returning a re"erence to an array, but with Java you never worry about res%onsibility "or that array9it will be around as long as you need it, and the garbage collector will clean it u% when you re done. RF SURFSTIJLT+(6PTE52TIMIU 6s an e&a#%le, consider returning an array o" )tring=

//3 c'C3$ceCrea#.Hava // 5eturning arrays fro# #etho!s.


@ This is one o" the %laces where +<< is distinctly su%erior to Java, since +<< su%%orts

arameteri?ed t) es with the template keyword.

42:

"ublic class $ceCrea# @ static %tringNO flav ? @ 8Chocolate8, 8%tra:berry8, 8Wanilla Lu!ge %:irl8, 8Jint Chi"8, 8Jocha 0l#on! Lu!ge8, 85u# 5aisin8, 8Praline Crea#8, 8Ju! Pie8 A< static %tringNO flavor%et-int n. @ // Lorce it to be "ositive D :ithin boun!s3 n ? Jath.abs-n. V -flav.length K (.< %tringNO results ? ne: %tringNnO< booleanNO "icke! ? ne: booleanNflav.lengthO< for -int i ? '< i P n< iKK. @ int t< !o t ? -int.-Jath.ran!o#-. B flav.length.< :hile -"icke!NtO.< resultsNiO ? flavNtO< "icke!NtO ? true< A return results< A "ublic static voi! #ain-%tringNO args. @ for-int i ? '< i P '< iKK. @ %yste#.out."rintln8flavor%et-8 K i K 8. ? 8.< %tringNO fl ? flavor%et-flav.length.< for-int H ? '< H P fl.length< HKK. %yste#.out."rintln-8_t8 K flNHO.< A A A ///3>
The #ethod flavor)etA B creates an array o" )tring called res*lts. The si1e o" this array is n, deter#ined by the argu#ent you %ass into the #ethod. Then it %roceeds to choose "lavors rando#ly "ro# the array flav and %lace the# into res*lts, which it "inally returns. 5eturning an array is 0ust like returning any other ob0ect9it s a re"erence. It s not i#%ortant that the array was created within flavor)etA B, or that the array was

Cha ter ;! .olding Lour Ob>ects

42;

created any%lace else, "or that #atter. The garbage collector takes care o" cleaning u% the array when you re done with it, and the array will %ersist "or as long as you need it. RFSURFSTIJLT+(6PTE52TIM2U 6s an aside, notice that when flavor)etA B chooses "lavors rando#ly, it ensures that a rando# choice hasn t been %icked be"ore. This is %er"or#ed in a 'o loo% that kee%s #aking rando# choices until it "inds one that s not already in the picke' array. *)" course, a )tring co#%arison could also have been %er"or#ed to see i" the rando# choice was already in the res*lts array, but )tring co#%arisons are ine""icient., I" it s success"ul, it adds the entry and "inds the ne&t one * i gets incre#ented,. RFSURFSTIJLT+(6PTE52TIK@U

mainA B %rints out K@ "ull sets o" "lavors, so you can see that flavor)et A B chooses the "lavors in a rando# order each ti#e. It s easiest to see this
i" you redirect the out%ut into a "ile. 6nd while you re looking at the "ile, re#e#ber, you 0ust ,ant the ice crea#, you don t need it. RFSURF STIJLT+(6PTE52TIKMU

#he Arrays class


In 8ava!*til, you ll "ind the Arrays class, which holds a set o" static #ethods that %er"or# utility "unctions "or arrays. There are "our basic "unctions= eC*alsA B, to co#%are two arrays "or eAuality; fillA B, to "ill an array with a value; sortA B, to sort the array; and binary)earchA B, to "ind an ele#ent in a sorted array. 6ll o" these #ethods are overloaded "or all the %ri#itive ty%es and .b8ects. In addition, there s a single as+istA B #ethod that takes any array and turns it into a +ist container9which you ll learn about later in this cha%ter. RFSURFSTIJLT+(6PTE52TIKKU :hile use"ul, the Arrays class sto%s short o" being "ully "unctional. Eor e&a#%le, it would be nice to be able to easily %rint the ele#ents o" an array without having to code a for loo% by hand every ti#e. 6nd as you ll see, the fillA B #ethod only takes a single value and %laces it in the array, so i" you wanted9"or e&a#%le9to "ill an array with rando#ly generated nu#bers, fillA B is no hel%. RFSURFSTIJLT+(6PTE52TIKLU Thus it #akes sense to su%%le#ent the Arrays class with so#e additional utilities, which will be %laced in the package com!

43=

br*ceeckel!*til "or convenience. These will %rint an array o" any ty%e,
and "ill an array with values or ob0ects that are created by an ob0ect called a generator that you can de"ine. RFSURFSTIJLT+(6PTE52TIK?U Because code needs to be created "or each %ri#itive ty%e as well as .b8ect, there s a lot o" nearly du%licated code @. Eor e&a#%le, a !generator$ inter"ace is reAuired "or each ty%e because the return ty%e o" ne4tA B #ust be di""erent in each case=

//3 co#3bruceeckel3util3aenerator.Hava "ackage co#.bruceeckel.util< "ublic interface aenerator @ GbHect ne6t-.< A ///3> //3 co#3bruceeckel3util3Booleanaenerator.Hava "ackage co#.bruceeckel.util< "ublic interface Booleanaenerator @ boolean ne6t-.< A ///3> //3 co#3bruceeckel3util3Byteaenerator.Hava "ackage co#.bruceeckel.util< "ublic interface Byteaenerator @ byte ne6t-.< A ///3> //3 co#3bruceeckel3util3Charaenerator.Hava "ackage co#.bruceeckel.util< "ublic interface Charaenerator @ char ne6t-.< A ///3> //3 co#3bruceeckel3util3%hortaenerator.Hava "ackage co#.bruceeckel.util< "ublic interface %hortaenerator @ short ne6t-.< A ///3>
@ The +<< %rogra##er will note how #uch the code could be colla%sed with the use o" de"ault argu#ents and te#%lates. The Python %rogra##er will note that this entire library would be largely unnecessary in that language.

Cha ter ;! .olding Lour Ob>ects

431

//3 co#3bruceeckel3util3$ntaenerator.Hava "ackage co#.bruceeckel.util< "ublic interface $ntaenerator @ int ne6t-.< A ///3> //3 co#3bruceeckel3util3Longaenerator.Hava "ackage co#.bruceeckel.util< "ublic interface Longaenerator @ long ne6t-.< A ///3> //3 co#3bruceeckel3util3Lloataenerator.Hava "ackage co#.bruceeckel.util< "ublic interface Lloataenerator @ float ne6t-.< A ///3> //3 co#3bruceeckel3util3Doubleaenerator.Hava "ackage co#.bruceeckel.util< "ublic interface Doubleaenerator @ !ouble ne6t-.< A ///3> ArraysI contains a variety o" printA B "unctions, overloaded "or each
ty%e. /ou can si#%ly %rint an array, you can add a #essage be"ore the array is %rinted, or you can %rint a range o" ele#ents within an array. The printA B code is sel"'e&%lanatory=

//3 co#3bruceeckel3util30rrays .Hava // 0 su""le#ent to Hava.util.0rrays, to "rovi!e // a!!itional useful functionality :hen :orking // :ith arrays. 0llo:s any array to be "rinte!, // an! to be fille! via a user-!efine! // 8generator8 obHect. "ackage co#.bruceeckel.util< i#"ort Hava.util.B< "ublic class 0rrays @ "rivate static voi!

432

start-int fro#, int to, int length. @ if-fro# 4? ' XX to 4? length. %yste#.out."rint-8N8K fro# K838K to K8O 8.< %yste#.out."rint-8-8.< A "rivate static voi! en!-. @ %yste#.out."rintln-8.8.< A "ublic static voi! "rint-GbHectNO a. @ "rint-a, ', a.length.< A "ublic static voi! "rint-%tring #sg, GbHectNO a. @ %yste#.out."rint-#sg K 8 8.< "rint-a, ', a.length.< A "ublic static voi! "rint-GbHectNO a, int fro#, int to.@ start-fro#, to, a.length.< for-int i ? fro#< i P to< iKK. @ %yste#.out."rint-aNiO.< if-i P to -(. %yste#.out."rint-8, 8.< A en!-.< A "ublic static voi! "rint-booleanNO a. @ "rint-a, ', a.length.< A "ublic static voi! "rint-%tring #sg, booleanNO a. @ %yste#.out."rint-#sg K 8 8.< "rint-a, ', a.length.< A "ublic static voi! "rint-booleanNO a, int fro#, int to. @ start-fro#, to, a.length.< for-int i ? fro#< i P to< iKK. @ %yste#.out."rint-aNiO.< if-i P to -(. %yste#.out."rint-8, 8.<

Cha ter ;! .olding Lour Ob>ects

433

A en!-.< A "ublic static voi! "rint-byteNO a. @ "rint-a, ', a.length.< A "ublic static voi! "rint-%tring #sg, byteNO a. @ %yste#.out."rint-#sg K 8 8.< "rint-a, ', a.length.< A "ublic static voi! "rint-byteNO a, int fro#, int to. @ start-fro#, to, a.length.< for-int i ? fro#< i P to< iKK. @ %yste#.out."rint-aNiO.< if-i P to -(. %yste#.out."rint-8, 8.< A en!-.< A "ublic static voi! "rint-charNO a. @ "rint-a, ', a.length.< A "ublic static voi! "rint-%tring #sg, charNO a. @ %yste#.out."rint-#sg K 8 8.< "rint-a, ', a.length.< A "ublic static voi! "rint-charNO a, int fro#, int to. @ start-fro#, to, a.length.< for-int i ? fro#< i P to< iKK. @ %yste#.out."rint-aNiO.< if-i P to -(. %yste#.out."rint-8, 8.< A en!-.< A "ublic static voi! "rint-shortNO a. @ "rint-a, ', a.length.<

434

A "ublic static voi! "rint-%tring #sg, shortNO a. @ %yste#.out."rint-#sg K 8 8.< "rint-a, ', a.length.< A "ublic static voi! "rint-shortNO a, int fro#, int to. @ start-fro#, to, a.length.< for-int i ? fro#< i P to< iKK. @ %yste#.out."rint-aNiO.< if-i P to - (. %yste#.out."rint-8, 8.< A en!-.< A "ublic static voi! "rint-intNO a. @ "rint-a, ', a.length.< A "ublic static voi! "rint-%tring #sg, intNO a. @ %yste#.out."rint-#sg K 8 8.< "rint-a, ', a.length.< A "ublic static voi! "rint-intNO a, int fro#, int to. @ start-fro#, to, a.length.< for-int i ? fro#< i P to< iKK. @ %yste#.out."rint-aNiO.< if-i P to - (. %yste#.out."rint-8, 8.< A en!-.< A "ublic static voi! "rint-longNO a. @ "rint-a, ', a.length.< A "ublic static voi! "rint-%tring #sg, longNO a. @ %yste#.out."rint-#sg K 8 8.< "rint-a, ', a.length.<

Cha ter ;! .olding Lour Ob>ects

435

A "ublic static voi! "rint-longNO a, int fro#, int to. @ start-fro#, to, a.length.< for-int i ? fro#< i P to< iKK. @ %yste#.out."rint-aNiO.< if-i P to - (. %yste#.out."rint-8, 8.< A en!-.< A "ublic static voi! "rint-floatNO a. @ "rint-a, ', a.length.< A "ublic static voi! "rint-%tring #sg, floatNO a. @ %yste#.out."rint-#sg K 8 8.< "rint-a, ', a.length.< A "ublic static voi! "rint-floatNO a, int fro#, int to. @ start-fro#, to, a.length.< for-int i ? fro#< i P to< iKK. @ %yste#.out."rint-aNiO.< if-i P to - (. %yste#.out."rint-8, 8.< A en!-.< A "ublic static voi! "rint-!oubleNO a. @ "rint-a, ', a.length.< A "ublic static voi! "rint-%tring #sg, !oubleNO a. @ %yste#.out."rint-#sg K 8 8.< "rint-a, ', a.length.< A "ublic static voi! "rint-!oubleNO a, int fro#, int to.@ start-fro#, to, a.length.< for-int i ? fro#< i P to< iKK. @

437

%yste#.out."rint-aNiO.< if-i P to - (. %yste#.out."rint-8, 8.< A en!-.< A // Lill an array using a generator3 "ublic static voi! fill-GbHectNO a, aenerator gen. @ fill-a, ', a.length, gen.< A "ublic static voi! fill-GbHectNO a, int fro#, int to, aenerator gen.@ for-int i ? fro#< i P to< iKK. aNiO ? gen.ne6t-.< A "ublic static voi! fill-booleanNO a, Booleanaenerator gen. @ fill-a, ', a.length, gen.< A "ublic static voi! fill-booleanNO a, int fro#, int to, Booleanaenerator gen. @ for-int i ? fro#< i P to< iKK. aNiO ? gen.ne6t-.< A "ublic static voi! fill-byteNO a, Byteaenerator gen. @ fill-a, ', a.length, gen.< A "ublic static voi! fill-byteNO a, int fro#, int to, Byteaenerator gen. @ for-int i ? fro#< i P to< iKK. aNiO ? gen.ne6t-.< A "ublic static voi! fill-charNO a, Charaenerator gen. @ fill-a, ', a.length, gen.< A

Cha ter ;! .olding Lour Ob>ects

438

"ublic static voi! fill-charNO a, int fro#, int to, Charaenerator gen. @ for-int i ? fro#< i P to< iKK. aNiO ? gen.ne6t-.< A "ublic static voi! fill-shortNO a, %hortaenerator gen. @ fill-a, ', a.length, gen.< A "ublic static voi! fill-shortNO a, int fro#, int to, %hortaenerator gen. @ for-int i ? fro#< i P to< iKK. aNiO ? gen.ne6t-.< A "ublic static voi! fill-intNO a, $ntaenerator gen. @ fill-a, ', a.length, gen.< A "ublic static voi! fill-intNO a, int fro#, int to, $ntaenerator gen. @ for-int i ? fro#< i P to< iKK. aNiO ? gen.ne6t-.< A "ublic static voi! fill-longNO a, Longaenerator gen. @ fill-a, ', a.length, gen.< A "ublic static voi! fill-longNO a, int fro#, int to, Longaenerator gen. @ for-int i ? fro#< i P to< iKK. aNiO ? gen.ne6t-.< A "ublic static voi! fill-floatNO a, Lloataenerator gen. @ fill-a, ', a.length, gen.< A "ublic static voi!

43:

fill-floatNO a, int fro#, int to, Lloataenerator gen. @ for-int i ? fro#< i P to< iKK. aNiO ? gen.ne6t-.< A "ublic static voi! fill-!oubleNO a, Doubleaenerator gen. @ fill-a, ', a.length, gen.< A "ublic static voi! fill-!oubleNO a, int fro#, int to, Doubleaenerator gen.@ for-int i ? fro#< i P to< iKK. aNiO ? gen.ne6t-.< A "rivate static 5an!o# r ? ne: 5an!o#-.< "ublic static class 5an!Booleanaenerator i#"le#ents Booleanaenerator @ "ublic boolean ne6t-. @ return r.ne6tBoolean-.< A A "ublic static class 5an!Byteaenerator i#"le#ents Byteaenerator @ "ublic byte ne6t-. @ return -byte.r.ne6t$nt-.< A A static %tring ssource ? 80BCDELaM$J`LJ&GP/5%TYW\9;T8 K 8abc!efghiHkl#no"=rstuv:6yU8< static charNO src ? ssource.toChar0rray-.< "ublic static class 5an!Charaenerator i#"le#ents Charaenerator @ "ublic char ne6t-. @ int "os ? Jath.abs-r.ne6t$nt-..< return srcN"os V src.lengthO< A A "ublic static class 5an!%tringaenerator i#"le#ents aenerator @

Cha ter ;! .olding Lour Ob>ects

43;

"rivate int len< "rivate 5an!Charaenerator cg ? ne: 5an!Charaenerator-.< "ublic 5an!%tringaenerator-int length. @ len ? length< A "ublic GbHect ne6t-. @ charNO buf ? ne: charNlenO< for-int i ? '< i P len< iKK. bufNiO ? cg.ne6t-.< return ne: %tring-buf.< A A "ublic static class 5an!%hortaenerator i#"le#ents %hortaenerator @ "ublic short ne6t-. @ return -short.r.ne6t$nt-.< A A "ublic static class 5an!$ntaenerator i#"le#ents $ntaenerator @ "rivate int #o! ? (''''< "ublic 5an!$ntaenerator-. @A "ublic 5an!$ntaenerator-int #o!ulo. @ #o! ? #o!ulo< A "ublic int ne6t-. @ return r.ne6t$nt-. V #o!< A A "ublic static class 5an!Longaenerator i#"le#ents Longaenerator @ "ublic long ne6t-. @ return r.ne6tLong-.< A A "ublic static class 5an!Lloataenerator i#"le#ents Lloataenerator @ "ublic float ne6t-. @ return r.ne6tLloat-.< A A "ublic static class 5an!Doubleaenerator i#"le#ents Doubleaenerator @ "ublic !ouble ne6t-. @return r.ne6tDouble-.<A

44=

A A ///3>
To "ill an array o" ele#ents using a generator, the fillA B #ethod takes a re"erence to an a%%ro%riate generator interface, which has a ne4tA B #ethod that will so#ehow %roduce an ob0ect o" the right ty%e *de%ending on how the inter"ace is i#%le#ented,. The fillA B #ethod si#%ly calls ne4tA B until the desired range has been "illed. Cow you can create any generator by i#%le#enting the a%%ro%riate interface, and use your generator with fillA B. RFSURFSTIJLT+(6PTE52TIKHU 5ando# data generators are use"ul "or testing, so a set o" inner classes is created to i#%le#ent all the %ri#itive generator inter"aces, as well as a )tring generator to re%resent .b8ect. /ou can see that $an')tring"enerator uses $an'-har"enerator to "ill an array o" characters, which is then turned into a )tring. The si1e o" the array is deter#ined by the constructor argu#ent. RFSURF STIJLT+(6PTE52TIK3U To generate nu#bers that aren t too large, $an'Int"enerator de"aults to a #odulus o" M@,@@@, but the overloaded constructor allows you to choose a s#aller value. RFSURFSTIJLT+(6PTE52TIKGU (ere s a %rogra# to test the library, and to de#onstrate how it is used=

//3 c'C3Test0rrays .Hava // Test an! !e#onstrate 0rrays i#"ort co#.bruceeckel.util.B<

utilities

"ublic class Test0rrays @ "ublic static voi! #ain-%tringNO args. @ int siUe ? +< // Gr get the siUe fro# the co##an! line3 if-args.length 4? '. siUe ? $nteger."arse$nt-argsN'O.< booleanNO a( ? ne: booleanNsiUeO< byteNO a ? ne: byteNsiUeO< charNO a) ? ne: charNsiUeO< shortNO aI ? ne: shortNsiUeO< intNO a, ? ne: intNsiUeO< longNO a+ ? ne: longNsiUeO<

Cha ter ;! .olding Lour Ob>ects

441

floatNO a* ? ne: floatNsiUeO< !oubleNO a1 ? ne: !oubleNsiUeO< %tringNO aC ? ne: %tringNsiUeO< 0rrays .fill-a(, ne: 0rrays .5an!Booleanaenerator-..< 0rrays ."rint-a(.< 0rrays ."rint-8a( ? 8, a(.< 0rrays ."rint-a(, siUe/), siUe/) K siUe/).< 0rrays .fill-a , ne: 0rrays .5an!Byteaenerator-..< 0rrays ."rint-a .< 0rrays ."rint-8a ? 8, a .< 0rrays ."rint-a , siUe/), siUe/) K siUe/).< 0rrays .fill-a), ne: 0rrays .5an!Charaenerator-..< 0rrays ."rint-a).< 0rrays ."rint-8a) ? 8, a).< 0rrays ."rint-a), siUe/), siUe/) K siUe/).< 0rrays .fill-aI, ne: 0rrays .5an!%hortaenerator-..< 0rrays ."rint-aI.< 0rrays ."rint-8aI ? 8, aI.< 0rrays ."rint-aI, siUe/), siUe/) K siUe/).< 0rrays .fill-a,, ne: 0rrays .5an!$ntaenerator-..< 0rrays ."rint-a,.< 0rrays ."rint-8a, ? 8, a,.< 0rrays ."rint-a,, siUe/), siUe/) K siUe/).< 0rrays .fill-a+, ne: 0rrays .5an!Longaenerator-..< 0rrays ."rint-a+.< 0rrays ."rint-8a+ ? 8, a+.< 0rrays ."rint-a+, siUe/), siUe/) K siUe/).< 0rrays .fill-a*, ne: 0rrays .5an!Lloataenerator-..< 0rrays ."rint-a*.< 0rrays ."rint-8a* ? 8, a*.< 0rrays ."rint-a*, siUe/), siUe/) K siUe/).< 0rrays .fill-a1, ne: 0rrays .5an!Doubleaenerator-..< 0rrays ."rint-a1.<

442

0rrays ."rint-8a1 ? 8, a1.< 0rrays ."rint-a1, siUe/), siUe/) K siUe/).< 0rrays .fill-aC, ne: 0rrays .5an!%tringaenerator-*..< 0rrays ."rint-aC.< 0rrays ."rint-8aC ? 8, aC.< 0rrays ."rint-aC, siUe/), siUe/) K siUe/).< A A ///3>
The si7e %ara#eter has a de"ault value, but you can also set it "ro# the co##and line. RFSURFSTIJLT+(6PTE52TIKIU

<illing an arra:
The Java standard library Arrays also has a fillA B #ethod, but that is rather trivial9it only du%licates a single value into each location, or in the case o" ob0ects, co%ies the sa#e re"erence into each location. 4sing ArraysI!printA B, the Arrays!fillA B #ethods can be easily de#onstrated=

//3 c'C3Lilling0rrays.Hava // Ysing 0rrays.fill-. i#"ort co#.bruceeckel.util.B< i#"ort Hava.util.B< "ublic class Lilling0rrays @ "ublic static voi! #ain-%tringNO args. @ int siUe ? +< // Gr get the siUe fro# the co##an! line3 if-args.length 4? '. siUe ? $nteger."arse$nt-argsN'O.< booleanNO a( ? ne: booleanNsiUeO< byteNO a ? ne: byteNsiUeO< charNO a) ? ne: charNsiUeO< shortNO aI ? ne: shortNsiUeO< intNO a, ? ne: intNsiUeO< longNO a+ ? ne: longNsiUeO< floatNO a* ? ne: floatNsiUeO< !oubleNO a1 ? ne: !oubleNsiUeO< %tringNO aC ? ne: %tringNsiUeO<

Cha ter ;! .olding Lour Ob>ects

443

0rrays.fill-a(, true.< 0rrays ."rint-8a( ? 8, a(.< 0rrays.fill-a , -byte.((.< 0rrays ."rint-8a ? 8, a .< 0rrays.fill-a), 262.< 0rrays ."rint-8a) ? 8, a).< 0rrays.fill-aI, -short.(*.< 0rrays ."rint-8aI ? 8, aI.< 0rrays.fill-a,, (C.< 0rrays ."rint-8a, ? 8, a,.< 0rrays.fill-a+, ).< 0rrays ."rint-8a+ ? 8, a+.< 0rrays.fill-a*, C.< 0rrays ."rint-8a* ? 8, a*.< 0rrays.fill-a1, I*.< 0rrays ."rint-8a1 ? 8, a1.< 0rrays.fill-aC, 8Mello8.< 0rrays ."rint-8aC ? 8, aC.< // Jani"ulating ranges3 0rrays.fill-aC, ), ,, 8\orl!8.< 0rrays ."rint-8aC ? 8, aC.< A A ///3>
/ou can either "ill the entire array, or9as the last two state#ents show9a range o" ele#ents. But since you can only %rovide a single value to use "or "illing using Arrays!fillA B, the ArraysI!fillA B #ethods %roduce #uch #ore interesting results. RFSURFSTIJLT+(6PTE52TIK2U

Co.:ing an arra:
The Java standard library %rovides a static #ethod, )ystem!arraycopy A B, which can #ake #uch "aster co%ies o" an array than i" you use a for loo% to %er"or# the co%y by hand. )ystem!arraycopyA B is overloaded to handle all ty%es. (ere s an e&a#%le that #ani%ulates arrays o" int=

//3 c'C3Co"ying0rrays.Hava // Ysing %yste#.arrayco"y-. i#"ort co#.bruceeckel.util.B< i#"ort Hava.util.B<

444

"ublic class Co"ying0rrays @ "ublic static voi! #ain-%tringNO args. @ intNO i ? ne: intN ,O< intNO H ? ne: intN ,O< 0rrays.fill-i, I*.< 0rrays.fill-H, CC.< 0rrays ."rint-8i ? 8, i.< 0rrays ."rint-8H ? 8, H.< %yste#.arrayco"y-i, ', H, ', i.length.< 0rrays ."rint-8H ? 8, H.< intNO k ? ne: intN('O< 0rrays.fill-k, (').< %yste#.arrayco"y-i, ', k, ', k.length.< 0rrays ."rint-8k ? 8, k.< 0rrays.fill-k, (').< %yste#.arrayco"y-k, ', i, ', k.length.< 0rrays ."rint-8i ? 8, i.< // GbHects3 $ntegerNO u ? ne: $ntegerN('O< $ntegerNO v ? ne: $ntegerN,O< 0rrays.fill-u, ne: $nteger-I*..< 0rrays.fill-v, ne: $nteger-CC..< 0rrays ."rint-8u ? 8, u.< 0rrays ."rint-8v ? 8, v.< %yste#.arrayco"y-v, ', u, u.length/ , v.length.< 0rrays ."rint-8u ? 8, u.< A A ///3>
The argu#ents to arraycopyA B are the source array, the o""set into the source array "ro# whence to start co%ying, the destination array, the o""set into the destination array where the co%ying begins, and the nu#ber o" ele#ents to co%y. Caturally, any violation o" the array boundaries will cause an e&ce%tion. RFSURFSTIJLT+(6PTE52TIL@U The e&a#%le shows that both %ri#itive arrays and ob0ect arrays can be co%ied. (owever, i" you co%y arrays o" ob0ects then only the re"erences get co%ied9there s no du%lication o" the ob0ects the#selves. This is called a shallo, co ) *see 6%%endi& 6,. RFSURFSTIJLT+(6PTE52TILMU

Cha ter ;! .olding Lour Ob>ects

445

Com.aring arra:s
Arrays %rovides the overloaded #ethod eC*alsA B to co#%are entire
arrays "or eAuality. 6gain, these are overloaded "or all the %ri#itives, and "or .b8ect. To be eAual, the arrays #ust have the sa#e nu#ber o" ele#ents and each ele#ent #ust be eAuivalent to each corres%onding ele#ent in the other array, using the eC*alsA B "or each ele#ent. *Eor %ri#itives, that %ri#itive s wra%%er class eC*alsA B is used; "or e&a#%le, Integer!eC*alsA B "or int., (ere s an e&a#%le=

//3 c'C3Co#"aring0rrays.Hava // Ysing 0rrays.e=uals-. i#"ort Hava.util.B< "ublic class Co#"aring0rrays @ "ublic static voi! #ain-%tringNO args. @ intNO a( ? ne: intN('O< intNO a ? ne: intN('O< 0rrays.fill-a(, I*.< 0rrays.fill-a , I*.< %yste#.out."rintln-0rrays.e=uals-a(, a a N)O ? ((< %yste#.out."rintln-0rrays.e=uals-a(, a %tringNO s( ? ne: %tringN,O< 0rrays.fill-s(, 8Mi8.< %tringNO s ? @8Mi8, 8Mi8, 8Mi8, 8Mi8, %yste#.out."rintln-0rrays.e=uals-s(, s A A ///3>

..< ..< 8Mi8A< ..<

)riginally, a> and aI are e&actly eAual, so the out%ut is !true,$ but then one o" the ele#ents is changed so the second line o" out%ut is !"alse.$ In the last case, all the ele#ents o" s> %oint to the sa#e ob0ect, but sI has "ive uniAue ob0ects. (owever, array eAuality is based on contents *via .b8ect!eC*alsA B, and so the result is !true.$ RFSURF STIJLT+(6PTE52TILKU

447

Arra: element com.arisons


)ne o" the #issing "eatures in the Java M.@ and M.M libraries is algorith#ic o%erations9even si#%le sorting. This was a rather con"using situation to so#eone e&%ecting an adeAuate standard library. Eortunately, Java K re#edies the situation, at least "or the sorting %roble#. RFSURF STIJLT+(6PTE52TILLU 6 %roble# with writing generic sorting code is that sorting #ust %er"or# co#%arisons based on the actual ty%e o" the ob0ect. )" course, one a%%roach is to write a di""erent sorting #ethod "or every di""erent ty%e, but you should be able to recogni1e that this does not %roduce code that is easily reused "or new ty%es. RFSURFSTIJLT+(6PTE52TIL?U 6 %ri#ary goal o" %rogra##ing design is to !se%arate things that change "ro# things that stay the sa#e,$ and here, the code that stays the sa#e is the general sort algorith#, but the thing that changes "ro# one use to the ne&t is the way ob0ects are co#%ared. So instead o" hard'wiring the co#%arison code into #any di""erent sort routines, the techniAue o" the callback is used. :ith a callback, the %art o" the code that varies "ro# case to case is enca%sulated inside its own class, and the %art o" the code that s always the sa#e will call back to the code that changes. That way you can #ake di""erent ob0ects to e&%ress di""erent ways o" co#%arison and "eed the# to the sa#e sorting code. RFSURF STIJLT+(6PTE52TILHU In Java K, there are two ways to %rovide co#%arison "unctionality. The "irst is with the natural com arison method that is i#%arted to a class by i#%le#enting the 8ava!lang!-omparable inter"ace. This is a very si#%le inter"ace with a single #ethod, compareToA B. This #ethod takes another .b8ect as an argu#ent, and %roduces a negative value i" the argu#ent is less than the current ob0ect is less than the argu#ent, 1ero i" the argu#ent is eAual, and a %ositive value i" the current ob0ect is greater than the argu#ent is greater than the current ob0ect. RFSURF STIJLT+(6PTE52TIL3U (ere s a class that i#%le#ents -omparable and de#onstrates the co#%arability by using the Java standard library #ethod Arrays!sortA B=

//3 c'C3Co#"Ty"e.Hava

Cha ter ;! .olding Lour Ob>ects

448

// $#"le#enting Co#"arable in a class. i#"ort co#.bruceeckel.util.B< i#"ort Hava.util.B< "ublic class Co#"Ty"e i#"le#ents Co#"arable @ int i< int H< "ublic Co#"Ty"e-int n(, int n . @ i ? n(< H ? n < A "ublic %tring to%tring-. @ return 8Ni ? 8 K i K 8, H ? 8 K H K 8O8< A "ublic int co#"areTo-GbHect rv. @ int rvi ? --Co#"Ty"e.rv..i< return -i P rvi [ -( 3 -i ?? rvi [ ' 3 (..< A "rivate static 5an!o# r ? ne: 5an!o#-.< "rivate static int ran!$nt-. @ return Jath.abs-r.ne6t$nt-.. V (''< A "ublic static aenerator generator-. @ return ne: aenerator-. @ "ublic GbHect ne6t-. @ return ne: Co#"Ty"e-ran!$nt-.,ran!$nt-..< A A< A "ublic static voi! #ain-%tringNO args. @ Co#"Ty"eNO a ? ne: Co#"Ty"eN('O< 0rrays .fill-a, generator-..< 0rrays ."rint-8before sorting, a ? 8, a.< 0rrays.sort-a.< 0rrays ."rint-8after sorting, a ? 8, a.< A A ///3>
:hen you de"ine the co#%arison "unction, you are res%onsible "or deciding what it #eans to co#%are one o" your ob0ects to another. (ere,

44:

only the i values are used in the co#%arison, and the 8 values are ignored. RFSURFSTIJLT+(6PTE52TILGU The static ran'IntA B #ethod %roduces %ositive values between 1ero and M@@, and the generatorA B #ethod %roduces an ob0ect that i#%le#ents the "enerator inter"ace, by creating an anony#ous inner class *see +ha%ter I,. This builds -ompType ob0ects by initiali1ing the# with rando# values. In mainA B, the generator is used to "ill an array o" -ompType, which is then sorted. I" -omparable hadn t been i#%le#ented, then you d get a co#%ile'ti#e error #essage when you tried to call sortA B. RFSURFSTIJLT+(6PTE52TILIU Cow su%%ose so#eone hands you a class that doesn t i#%le#ent -omparable, or they hand you this class that does i#%le#ent -omparable, but you decide you don t like the way it works and would rather have a di""erent co#%arison "unction "or the ty%e. To do this, you use the second a%%roach "or co#%aring ob0ects, by creating a se%arate class that i#%le#ents an inter"ace called -omparator. This has two #ethods, compareA B and eC*alsA B. (owever, you don t have to i#%le#ent eC*alsA B e&ce%t "or s%ecial %er"or#ance needs, because anyti#e you create a class it is i#%licitly inherited "ro# .b8ect, which has an eC*alsA B. So you can 0ust use the de"ault .b8ect eC*alsA B and satis"y the contract i#%osed by the inter"ace. RFSURF STIJLT+(6PTE52TIL2U The -ollections class *which we ll look at #ore later, contains a single -omparator that reverses the natural sorting order. This can easily be a%%lied to the -ompType= RFSURFSTIJLT+(6PTE52TI?@U

//3 c'C35everse.Hava // The Collecions.reverseGr!er-. Co#"arator. i#"ort co#.bruceeckel.util.B< i#"ort Hava.util.B< "ublic class 5everse @ "ublic static voi! #ain-%tringNO args. @ Co#"Ty"eNO a ? ne: Co#"Ty"eN('O< 0rrays .fill-a, Co#"Ty"e.generator-..< 0rrays ."rint-8before sorting, a ? 8, a.< 0rrays.sort-a, Collections.reverseGr!er-..<

Cha ter ;! .olding Lour Ob>ects

44;

0rrays ."rint-8after sorting, a ? 8, a.< A A ///3>


The call to -ollections!reverse.r'erA B %roduces the re"erence to the -omparator. RFSURFSTIJLT+(6PTE52TI?MU 6s a second e&a#%le, the "ollowing -omparator co#%ares -ompType ob0ects based on their 8 values rather than their i values=

//3 c'C3Co#"aratorTest.Hava // $#"le#enting a Co#"arator for a class. i#"ort co#.bruceeckel.util.B< i#"ort Hava.util.B< class Co#"Ty"eCo#"arator i#"le#ents Co#"arator @ "ublic int co#"are-GbHect o(, GbHect o . @ int H( ? --Co#"Ty"e.o(..H< int H ? --Co#"Ty"e.o ..H< return -H( P H [ -( 3 -H( ?? H [ ' 3 (..< A A "ublic class Co#"aratorTest @ "ublic static voi! #ain-%tringNO args. @ Co#"Ty"eNO a ? ne: Co#"Ty"eN('O< 0rrays .fill-a, Co#"Ty"e.generator-..< 0rrays ."rint-8before sorting, a ? 8, a.< 0rrays.sort-a, ne: Co#"Ty"eCo#"arator-..< 0rrays ."rint-8after sorting, a ? 8, a.< A A ///3>
The compareA B #ethod #ust return a negative integer, 1ero, or a %ositive integer i" the "irst argu#ent is less than, eAual to, or greater than the second, res%ectively. RFSURFSTIJLT+(6PTE52TI?KU

1orting an arra:
:ith the built'in sorting #ethods, you can sort any array o" %ri#itives, and any array o" ob0ects that either i#%le#ents -omparable or has an

45=

associated -omparator. This "ills a big hole in the Java libraries9 believe it or not, there was no su%%ort in Java M.@ or M.M "or sorting )trings. (ere s an e&a#%le that generates rando# )tring ob0ects and sorts the#=

//3 c'C3%tring%orting.Hava // %orting an array of %trings. i#"ort co#.bruceeckel.util.B< i#"ort Hava.util.B< "ublic class %tring%orting @ "ublic static voi! #ain-%tringNO args. @ %tringNO sa ? ne: %tringN)'O< 0rrays .fill-sa, ne: 0rrays .5an!%tringaenerator-,..< 0rrays ."rint-8Before sorting3 8, sa.< 0rrays.sort-sa.< 0rrays ."rint-80fter sorting3 8, sa.< A A ///3>
)ne thing you ll notice about the out%ut in the )tring sorting algorith# is that it s le*icogra hic, so it %uts all the words starting with u%%ercase letters "irst, "ollowed by all the words starting with lowercase letters. *Tele%hone books are ty%ically sorted this way., /ou #ay also want to grou% the words together regardless o" case, and you can do this by de"ining a -omparator class, thereby overriding the de"ault )tring -omparable behavior. Eor reuse, this will be added to the !util$ %ackage= RFSURFSTIJLT+(6PTE52TI?LU

//3 co#3bruceeckel3util30l"habeticCo#"arator.Hava // `ee"ing u""er an! lo:ercase letters together. "ackage co#.bruceeckel.util< i#"ort Hava.util.B< "ublic class 0l"habeticCo#"arator i#"le#ents Co#"arator @ "ublic int co#"are-GbHect o(, GbHect o . @ %tring s( ? -%tring.o(< %tring s ? -%tring.o < return s(.toLo:erCase-..co#"areTo-

Cha ter ;! .olding Lour Ob>ects

451

s .toLo:erCase-..< A A ///3>
Each )tring is converted to lowercase be"ore the co#%arison. )tring s built'in compareToA B #ethod %rovides the desired "unctionality. RF SURFSTIJLT+(6PTE52TI??U (ere s a test using Alphabetic-omparator=

//3 c'C30l"habetic%orting.Hava // `ee"ing u""er an! lo:ercase letters together. i#"ort co#.bruceeckel.util.B< i#"ort Hava.util.B< "ublic class 0l"habetic%orting @ "ublic static voi! #ain-%tringNO args. @ %tringNO sa ? ne: %tringN)'O< 0rrays .fill-sa, ne: 0rrays .5an!%tringaenerator-,..< 0rrays ."rint-8Before sorting3 8, sa.< 0rrays.sort-sa, ne: 0l"habeticCo#"arator-..< 0rrays ."rint-80fter sorting3 8, sa.< A A ///3>
The sorting algorith# that s used in the Java standard library is designed to be o%ti#al "or the %articular ty%e you re sorting9a euicksort "or %ri#itives, and a stable #erge sort "or ob0ects. So you shouldn t need to s%end any ti#e worrying about %er"or#ance unless your %ro"iling tool %oints you to the sorting %rocess as a bottleneck. RFSURF STIJLT+(6PTE52TI?HU

1earching a sorted arra:


)nce an array is sorted, you can %er"or# a "ast search "or a %articular ite# using Arrays!binary)earchA B. (owever, it s very i#%ortant that you do not try to use binary)earchA B on an unsorted array; the results will be un%redictable. The "ollowing e&a#%le uses a $an'Int"enerator to "ill an array, then to %roduces values to search "or= RFSURF STIJLT+(6PTE52TI?3U

452

//3 c'C30rray%earching.Hava // Ysing 0rrays.binary%earch-.. i#"ort co#.bruceeckel.util.B< i#"ort Hava.util.B< "ublic class 0rray%earching @ "ublic static voi! #ain-%tringNO args. @ intNO a ? ne: intN(''O< 0rrays .5an!$ntaenerator gen ? ne: 0rrays .5an!$ntaenerator-('''.< 0rrays .fill-a, gen.< 0rrays.sort-a.< 0rrays ."rint-8%orte! array3 8, a.< :hile-true. @ int r ? gen.ne6t-.< int location ? 0rrays.binary%earch-a, r.< if-location Q? '. @ %yste#.out."rintln-8Location of 8 K r K 8 is 8 K location K 8, aN8 K location K 8O ? 8 K aNlocationO.< break< // Gut of :hile loo" A A A A ///3>
In the (hile loo%, rando# values are generated as search ite#s, until one o" the# is "ound. RFSURFSTIJLT+(6PTE52TI?GU

Arrays!binary)earchA B %roduces a value greater than or eAual to 1ero i" the search ite# is "ound. )therwise, it %roduces a negative value re%resenting the %lace that the ele#ent should be inserted i" you are #aintaining the sorted array by hand. The value %roduced is --insertion "oint. - (
The insertion %oint is the inde& o" the "irst ele#ent greater than the key, or a!si7eA B, i" all ele#ents in the array are less than the s%eci"ied key. RF SURFSTIJLT+(6PTE52TI?IU I" the array contains du%licate ele#ents, there is no guarantee which one will be "ound. The algorith# is thus not really designed to su%%ort

Cha ter ;! .olding Lour Ob>ects

453

du%licate ele#ents, as #uch as tolerate the#. I" you need a sorted list o" nondu%licated ele#ents, however, use a Tree)et, which will be introduced later in this cha%ter. This takes care o" all the details "or you auto#atically. )nly in cases o" %er"or#ance bottlenecks should you re%lace the Tree)et with a hand'#aintained array. RFSURF STIJLT+(6PTE52TI?2U I" you have sorted an ob0ect array using a -omparator *%ri#itive arrays do not allow sorting with a -omparator,, you #ust include that sa#e -omparator when you %er"or# a binary)earchA B *using the overloaded version o" the "unction that s %rovided,. Eor e&a#%le, the Alphabetic)orting!8ava %rogra# can be #odi"ied to %er"or# a search=

//3 c'C30l"habetic%earch.Hava // %earching :ith a Co#"arator. i#"ort co#.bruceeckel.util.B< i#"ort Hava.util.B< "ublic class 0l"habetic%earch @ "ublic static voi! #ain-%tringNO args. @ %tringNO sa ? ne: %tringN)'O< 0rrays .fill-sa, ne: 0rrays .5an!%tringaenerator-,..< 0l"habeticCo#"arator co#" ? ne: 0l"habeticCo#"arator-.< 0rrays.sort-sa, co#".< int in!e6 ? 0rrays.binary%earch-sa, saN('O, co#".< %yste#.out."rintln-8$n!e6 ? 8 K in!e6.< A A ///3>
The -omparator #ust be %assed to the overloaded binary)earchA B as the third argu#ent. In the above e&a#%le, success is guaranteed because the search ite# is %lucked out o" the array itsel". RFSURF STIJLT+(6PTE52TIH@U

454

Arra: summar:
To su##ari1e what you ve seen so "ar, your "irst and #ost e""icient choice to hold a grou% o" ob0ects should be an array, and you re "orced into this choice i" you want to hold a grou% o" %ri#itives. In the re#ainder o" this cha%ter we ll look at the #ore general case, when you don t know at the ti#e you re writing the %rogra# how #any ob0ects you re going to need, or i" you need a #ore so%histicated way to store your ob0ects. Java %rovides a library o" container classes to solve this %roble#, the basic ty%es o" which are +ist, )et, and 1ap. /ou can solve a sur%rising nu#ber o" %roble#s using these tools. RFSURFSTIJLT+(6PTE52TIHMU 6#ong their other characteristics9 )et, "or e&a#%le, holds only one ob0ect o" each value, and 1ap is an associative arra) that lets you associate any ob0ect with any other ob0ect9the Java container classes will auto#atically resi1e the#selves. So, unlike arrays, you can %ut in any nu#ber o" ob0ects and you don t need to worry about how big to #ake the container while you re writing the %rogra#. RFSURF STIJLT+(6PTE52TIHKU

Introduction to containers
To #e, container classes are one o" the #ost %ower"ul tools "or raw develo%#ent because they signi"icantly increase your %rogra##ing #uscle. The Java K containers re%resent a thorough redesign @ o" the rather %oor showings in Java M.@ and M.M. So#e o" the redesign #akes things tighter and #ore sensible. It also "ills out the "unctionality o" the containers library, %roviding the behavior o" linked lists, Aueues, and deAues *double'ended Aueues, %ronounced !decks$,. RFSURF STIJLT+(6PTE52TIHLU The design o" a containers library is di""icult *true o" #ost library design %roble#s,. In +<<, the container classes covered the bases with #any di""erent classes. This was better than what was available %rior to the +<<
@ By Joshua Bloch at Sun.

Cha ter ;! .olding Lour Ob>ects

455

container classes *nothing,, but it didn t translate well into Java. )n the other e&tre#e, I ve seen a containers library that consists o" a single class, !container,$ which acts like both a linear seAuence and an associative array at the sa#e ti#e. The Java K container library strikes a balance= the "ull "unctionality that you e&%ect "ro# a #ature container library, but easier to learn and use than the +<< container classes and other si#ilar container libraries. The result can see# a bit odd in %laces. 4nlike so#e o" the decisions #ade in the early Java libraries, these oddities were not accidents, but care"ully considered decisions based on trade'o""s in co#%le&ity. It #ight take you a little while to get co#"ortable with so#e as%ects o" the library, but I think you ll "ind yoursel" ra%idly acAuiring and using these new tools. RFSURFSTIJLT+(6PTE52TIH?U The Java K container library takes the issue o" !holding your ob0ects$ and divides it into two distinct conce%ts=

4*)

-ollection= a grou% o" individual ele#ents, o"ten with so#e rule a%%lied to the#. 6 +ist #ust hold the ele#ents in a %articular seAuence, and a )et cannot have any du%licate ele#ents. *6 bag,
which is not i#%le#ented in the Java container library9since +ists %rovide you with enough o" that "unctionality9has no such rules., N5WON5WTIJJX-HA#T&$?XI@@O

4+)

1ap= a grou% o" key'value ob0ect %airs. 6t "irst glance, this #ight see# like it ought to be a -ollection o" %airs, but when you try to
i#%le#ent it that way the design gets awkward, so it s clearer to #ake it a se%arate conce%t. )n the other hand, it s convenient to look at %ortions o" a 1ap by creating a -ollection to re%resent that %ortion. Thus, a 1ap can return a )et o" its keys, a -ollection o" its values, or a )et o" its %airs. 1aps, like arrays, can easily be e&%anded to #ulti%le di#ensions without adding new conce%ts= you si#%ly #ake a 1ap whose values are 1aps *and the values o" those 1aps can be 1aps, etc.,. N5WON5

WTIJJX-HA#T&$?XI@\O
:e will "irst look at the general "eatures o" containers, then go into details, and "inally learn why there are di""erent versions o" so#e containers, and how to choose between the#. RFSURF STIJLT+(6PTE52TIHGU

457

rinting containers
4nlike arrays, the containers %rint nicely without any hel%. (ere s an e&a#%le that also introduces you to the basic ty%es o" containers=

//3 c'C3PrintingContainers.Hava // Containers "rint the#selves auto#atically. i#"ort Hava.util.B< "ublic class PrintingContainers @ static Collection fill-Collection c. @ c.a!!-8!og8.< c.a!!-8!og8.< c.a!!-8cat8.< return c< A static Ja" fill-Ja" #. @ #."ut-8!og8, 8Bosco8.< #."ut-8!og8, 8%"ot8.< #."ut-8cat8, 85ags8.< return #< A "ublic static voi! #ain-%tringNO args. @ %yste#.out."rintln-fill-ne: 0rrayList-...< %yste#.out."rintln-fill-ne: Mash%et-...< %yste#.out."rintln-fill-ne: MashJa"-...< A A ///3>
6s #entioned be"ore, there are two basic categories in the Java container library. The distinction is based on the nu#ber o" ite#s that are held in each location o" the container. The -ollection category only holds one ite# in each location *the na#e is a bit #isleading since entire container libraries are o"ten called !collections$,. It includes the +ist, which holds a grou% o" ite#s in a s%eci"ied seAuence, and the )et, which only allows the addition o" one ite# o" each ty%e. The Array+ist is a ty%e o" +ist, and Hash)et is a ty%e o" )et. To add ite#s to any -ollection, there s an a''A B #ethod. RFSURFSTIJLT+(6PTE52TIHIU The 1ap holds key'value %airs, rather like a #ini database. The above %rogra# uses one "lavor o" 1ap, the Hash1ap. I" you have a 1ap that

Cha ter ;! .olding Lour Ob>ects

458

associates states with their ca%itals and you want to know the ca%ital o" )hio, you look it u%9al#ost as i" you were inde&ing into an array. *Ma%s are also called associative arra)s., To add ele#ents to a 1ap there s a p*tA B #ethod that takes a key and a value as argu#ents. The above e&a#%le only shows adding ele#ents and does not look the ele#ents u% a"ter they re added. That will be shown later. RFSURF STIJLT+(6PTE52TIH2U The overloaded fillA B #ethods "ill -ollections and 1aps, res%ectively. I" you look at the out%ut, you can see that the de"ault %rinting behavior *%rovided via the container s various to)tringA B #ethods, %roduces Auite readable results, so no additional %rinting su%%ort is necessary as it was with arrays=

N!og, !og, catO Ncat, !ogO @cat?5ags, !og?%"otA


6 -ollection is %rinted surrounded by sAuare braces, with each ele#ent se%arated by a co##a. 6 1ap is surrounded by curly braces, with each key and value associated with an eAual sign *keys on the le"t, values on the right,. RFSURFSTIJLT+(6PTE52TI3@U /ou can also i##ediately see the basic behavior o" the di""erent containers. The +ist holds the ob0ects e&actly as they are entered, without any reordering or editing. The )et, however, only acce%ts one o" each ob0ect and it uses its own internal ordering #ethod *in general, you are only concerned with whether or not so#ething is a #e#ber o" the )et, not the order in which it a%%ears9"or that you d use a +ist,. 6nd the 1ap also only acce%ts one o" each ty%e o" ite#, based on the key, and it also has its own internal ordering and does not care about the order in which you enter the ite#s. RFSURFSTIJLT+(6PTE52TI3MU

<illing containers
6lthough the %roble# o" %rinting the containers is taken care o", "illing containers su""ers "ro# the sa#e de"iciency as 8ava!*til!Arrays. Just like Arrays, there is a co#%anion class called -ollections containing static utility #ethods including one called fillA B. This fillA B also 0ust

45:

du%licates a single ob0ect re"erence throughout the container, and also only works "or +ist ob0ects and not )ets or 1aps=

//3 c'C3LillingLists.Hava // The Collections.fill-. #etho!. i#"ort Hava.util.B< "ublic class LillingLists @ "ublic static voi! #ain-%tringNO args. @ List list ? ne: 0rrayList-.< for-int i ? '< i P ('< iKK. list.a!!-88.< Collections.fill-list, 8Mello8.< %yste#.out."rintln-list.< A A ///3>
This #ethod is #ade even less use"ul by the "act that it can only re%lace ele#ents that are already in the +ist, and will not add new ele#ents. RF SURFSTIJLT+(6PTE52TI3KU To be able to create interesting e&a#%les, here is a co#%le#entary

-ollectionsI library *%art o" com!br*ceeckel!*til "or convenience, with a fillA B #ethod that uses a generator to add ele#ents, and allows you to s%eci"y the nu#ber o" ele#ents you want to a''A B. The "enerator interface de"ined %reviously will work "or -ollections, but the 1ap reAuires its own generator interface since a %air o" ob0ects *one key and one value, #ust be %roduced by each call to ne4tA B. (ere is the #air class= //3 co#3bruceeckel3util3Pair.Hava "ackage co#.bruceeckel.util< "ublic class Pair @ "ublic GbHect key, value< Pair-GbHect k, GbHect v. @ key ? k< value ? v< A A ///3>
Ce&t, the generator interface that %roduces the #air=

Cha ter ;! .olding Lour Ob>ects

45;

//3 co#3bruceeckel3util3Ja"aenerator.Hava "ackage co#.bruceeckel.util< "ublic interface Ja"aenerator @ Pair ne6t-.< A ///3>
:ith these, a set o" utilities "or working with the container classes can be develo%ed=

//3 co#3bruceeckel3util3Collections .Hava // To fill any ty"e of container // using a generator obHect. "ackage co#.bruceeckel.util< i#"ort Hava.util.B< "ublic class Collections @ // Lill an array using a generator3 "ublic static voi! fill-Collection c, aenerator gen, int count. @ for-int i ? '< i P count< iKK. c.a!!-gen.ne6t-..< A "ublic static voi! fill-Ja" #, Ja"aenerator gen, int count. @ for-int i ? '< i P count< iKK. @ Pair " ? gen.ne6t-.< #."ut-".key, ".value.< A A "ublic static class 5an!%tringPairaenerator i#"le#ents Ja"aenerator @ "rivate 0rrays .5an!%tringaenerator gen< "ublic 5an!%tringPairaenerator-int len. @ gen ? ne: 0rrays .5an!%tringaenerator-len.< A "ublic Pair ne6t-. @ return ne: Pair-gen.ne6t-., gen.ne6t-..< A A // Default obHect so you !on2t have // to create your o:n3 "ublic static 5an!%tringPairaenerator rs" ?

47=

ne: 5an!%tringPairaenerator-('.< "ublic static class %tringPairaenerator i#"le#ents Ja"aenerator @ "rivate int in!e6 ? -(< "rivate %tringNONO !< "ublic %tringPairaenerator-%tringNONO !ata. @ ! ? !ata< A "ublic Pair ne6t-. @ // Lorce the in!e6 to :ra"3 in!e6 ? -in!e6 K (. V !.length< return ne: Pair-!Nin!e6ON'O, !Nin!e6ON(O.< A "ublic %tringPairaenerator reset-. @ in!e6 ? -(< return this< A A // Yse a "re!efine! !ataset3 "ublic static %tringPairaenerator geogra"hy ? ne: %tringPairaeneratorCountryCa"itals."airs.< // Pro!uce a se=uence fro# a D array3 "ublic static class %tringaenerator i#"le#ents aenerator @ "rivate %tringNONO !< "rivate int "osition< "rivate int in!e6 ? -(< "ublic %tringaenerator-%tringNONO !ata, int "os. @ ! ? !ata< "osition ? "os< A "ublic GbHect ne6t-. @ // Lorce the in!e6 to :ra"3 in!e6 ? -in!e6 K (. V !.length< return !Nin!e6ON"ositionO< A "ublic %tringaenerator reset-. @ in!e6 ? -(< return this<

Cha ter ;! .olding Lour Ob>ects

471

A A // Yse a "re!efine! !ataset3 "ublic static %tringaenerator countries ? ne: %tringaenerator-CountryCa"itals."airs,'.< "ublic static %tringaenerator ca"itals ? ne: %tringaenerator-CountryCa"itals."airs,(.< A ///3>
Both versions o" fillA B take an argu#ent that deter#ines the nu#ber o" ite#s to add to the container. In addition, there are two generators "or the #a%= $an')tring#air"enerator, which creates any nu#ber o" %airs o" gibberish )trings with length deter#ined by the constructor argu#ent; and )tring#air"enerator, which %roduces %airs o" )trings given a two'di#ensional array o" )tring. The )tring"enerator also takes a two'di#ensional array o" )tring but generates single ite#s rather than #airs. The static rsp, geography, co*ntries, and capitals ob0ects %rovide %rebuilt generators, the last three using all the countries o" the world and their ca%itals. Cote that i" you try to create #ore %airs than are available, the generators will loo% around to the beginning, and i" you are %utting the %airs into a 1ap, the du%licates will 0ust be ignored. RFSURFSTIJLT+(6PTE52TI3LU (ere is the %rede"ined dataset, which consists o" country na#es and their ca%itals. It is set in a s#all "ont to %revent taking u% unnecessary s%ace=

//3 co#3bruceeckel3util3CountryCa"itals.Hava "ackage co#.bruceeckel.util<

"ublic class CountryCa"itals @ "ublic static final %tringNONO "airs ? @ // 0frica @80LaE5$08,80lgiers8A, @80&aGL08,8Luan!a8A, @8BE&$&8,8Porto-&ovo8A, @8BGT%\0&08,8aaberone8A, @8BY5`$&0 L0%G8,8Guaga!ougou8A, @8BY5Y&D$8,8BuHu#bura8A, @8C0JE5GG&8,8;aoun!e8A, @8C0PE WE5DE8,8Praia8A, @8CE&T50L 0L5$C0& 5EPYBL$C8,8Bangui8A, @8CM0D8,8&2!Ha#ena8A, @8CGJG5G%8,8Joroni8A, @8CG&aG8,8BraUUaville8A, @8DJ$BGYT$8,8DiHibouti8A, @8Ea;PT8,8Cairo8A, @8E/Y0TG5$0L aY$&E08,8Jalabo8A, @8E5$T5E08,80s#ara8A, @8ETM$GP$08,80!!is 0baba8A, @8a0BG&8,8Libreville8A, @8TME a0JB$08,8BanHul8A, @8aM0&08,80ccra8A, @8aY$&E08,8Conakry8A, @8aY$&E08,8-8A, @8B$%%0Y8,8Bissau8A, @8CETE D2$WG$5 -$WG5; CG0%T.8,8;a#oussoukro8A, @8`E&;08,8&airobi8A, @8LE%GTMG8,8Jaseru8A, @8L$BE5$08,8Jonrovia8A, @8L$B;08,8Tri"oli8A,

472

@8J0D0a0%C058,80ntananarivo8A, @8J0L0\$8,8Lilong:e8A, @8J0L$8,8Ba#ako8A, @8J0Y5$T0&$08,8&ouakchott8A, @8J0Y5$T$Y%8,8Port Louis8A, @8JG5GCCG8,85abat8A, @8JGT0JB$/YE8,8Ja"uto8A, @8&0J$B$08,8\in!hoek8A, @8&$aE58,8&ia#ey8A, @8&$aE5$08,80buHa8A, @85\0&D08,8`igali8A, @8%0G TGJE E P5$&C$PE8,8%ao To#e8A, @8%E&Ea0L8,8Dakar8A, @8%E;CMELLE%8,8Wictoria8A, @8%$E550 LEG&E8,8Lreeto:n8A, @8%GJ0L$08,8Joga!ishu8A, @8%GYTM 0L5$C08,8Pretoria/Ca"e To:n8A, @8%YD0&8,8`hartou#8A, @8%\0T$L0&D8,8Jbabane8A, @8T0&T0&$08,8Do!o#a8A, @8TGaG8,8Lo#e8A, @8TY&$%$08,8Tunis8A, @8Ya0&D08,8`a#"ala8A, @8DEJGC50T$C 5EPYBL$C GL TME CG&aG -T0$5E.8,8`inshasa8A, @8T0JB$08,8Lusaka8A, @8T$JB0B\E8,8Marare8A, // 0sia @80LaM0&$%T0&8,8`abul8A, @8B0M50$&8,8Jana#a8A, @8B0&aL0DE%M8,8Dhaka8A, @8BMYT0&8,8Thi#"hu8A, @8B5Y&E$8,8Ban!ar %eri Bega:an8A, @8C0JBGD$08,8Phno# Penh8A, @8CM$&08,8BeiHing8A, @8C;P5Y%8,8&icosia8A, @8$&D$08,8&e: Delhi8A, @8$&DG&E%$08,8Jakarta8A, @8$50&8,8Tehran8A, @8$50/8,8Bagh!a!8A, @8$%50EL8,8Jerusale#8A, @8J0P0&8,8Tokyo8A, @8JG5D0&8,80##an8A, @8`Y\0$T8,8`u:ait City8A, @8L0G%8,8Wientiane8A, @8LEB0&G&8,8Beirut8A, @8J0L0;%$08,8`uala Lu#"ur8A, @8TME J0LD$WE%8,8Jale8A, @8JG&aGL$08,8Ylan Bator8A, @8J;0&J05 -BY5J0.8,85angoon8A, @8&EP0L8,8`at#an!u8A, @8&G5TM `G5E08,8P2yongyang8A, @8GJ0&8,8Juscat8A, @8P0`$%T0&8,8$sla#aba!8A, @8PM$L$PP$&E%8,8Janila8A, @8/0T058,8Doha8A, @8%0YD$ 050B$08,85iya!h8A, @8%$&a0PG5E8,8%inga"ore8A, @8%GYTM `G5E08,8%eoul8A, @8%5$ L0&`08,8Colo#bo8A, @8%;5$08,8Da#ascus8A, @8T0$\0& -5EPYBL$C GL CM$&0.8,8Tai"ei8A, @8TM0$L0&D8,8Bangkok8A, @8TY5`E;8,80nkara8A, @8Y&$TED 050B EJ$50TE%8,80bu Dhabi8A, @8W$ET&0J8,8Manoi8A, @8;EJE&8,8%ana2a8A, // 0ustralia an! Gceania @80Y%T50L$08,8Canberra8A, @8L$J$8,8%uva8A, @8`$5$B0T$8,8Bairiki8A, @8J05%M0LL $%L0&D%8,8Dala"-Yliga-Darrit8A, @8J$C5G&E%$08,8Palikir8A, @8&0Y5Y8,8;aren8A, @8&E\ TE0L0&D8,8\ellington8A, @8P0L0Y8,8`oror8A, @8P0PY0 &E\ aY$&E08,8Port Joresby8A, @8%GLGJG& $%L0&D%8,8Monaira8A, @8TG&a08,8&uku2alofa8A, @8TYW0LY8,8Longafale8A, @8W0&Y0TY8,8P Port-Wila8A, @8\E%TE5& %0JG08,80"ia8A, // Eastern Euro"e an! for#er Y%%5 @805JE&$08,8;erevan8A, @80TE5B0$J0&8,8Baku8A, @8BEL05Y% -B;ELG5Y%%$0.8,8Jinsk8A, @8aEG5a$08,8Tbilisi8A, @8`0T0`%T0&8,80l#aty8A, @8`;5a;T%T0&8,80l#a-0ta8A, @8JGLDGW08,8Chisinau8A, @85Y%%$08,8Josco:8A, @8T0J$`$%T0&8,8Dushanbe8A, @8TY5`JE&$%T0&8,80shkaba!8A, @8Y`50$&E8,8`yiv8A, @8YTBE`$%T0&8,8Tashkent8A, // Euro"e @80LB0&$08,8Tirana8A, @80&DG5508,80n!orra la Wella8A, @80Y%T5$08,8Wienna8A, @8BELa$YJ8,8Brussels8A,

Cha ter ;! .olding Lour Ob>ects

473

@8BG%&$08,8-8A, @8ME5TEaGW$&08,8%araHevo8A, @8C5G0T$08,8Tagreb8A, @8CTECM 5EPYBL$C8,8Prague8A, @8DE&J05`8,8Co"enhagen8A, @8E%TG&$08,8Tallinn8A, @8L$&L0&D8,8Melsinki8A, @8L50&CE8,8Paris8A, @8aE5J0&;8,8Berlin8A, @8a5EECE8,80thens8A, @8MY&a05;8,8Bu!a"est8A, @8$CEL0&D8,85eykHavik8A, @8$5EL0&D8,8Dublin8A, @8$T0L;8,85o#e8A, @8L0TW$08,85iga8A, @8L$ECMTE&%TE$&8,8Wa!uU8A, @8L$TMY0&$08,8Wilnius8A, @8LY9EJBGY5a8,8Lu6e#bourg8A, @8J0CEDG&$08,8%ko"He8A, @8J0LT08,8Walletta8A, @8JG&0CG8,8Jonaco8A, @8JG&TE&Ea5G8,8Po!gorica8A, @8TME &ETME5L0&D%8,80#ster!a#8A, @8&G5\0;8,8Gslo8A, @8PGL0&D8,8\arsa:8A, @8PG5TYa0L8,8Lisbon8A, @85GJ0&$08,8Bucharest8A, @8%0& J05$&G8,8%an Jarino8A, @8%E5B$08,8Belgra!e8A, @8%LGW0`$08,8Bratislava8A, @8%LGWE&$08,8LHuHiana8A, @8%P0$&8,8Ja!ri!8A, @8%\EDE&8,8%tockhol#8A, @8%\$TTE5L0&D8,8Berne8A, @8Y&$TED `$&aDGJ8,8Lon!on8A, @8W0T$C0& C$T;8,8---8A, // &orth an! Central 0#erica @80&T$aY0 0&D B05BYD08,8%aint John2s8A, @8B0M0J0%8,8&assau8A, @8B05B0DG%8,8Bri!geto:n8A, @8BEL$TE8,8Bel#o"an8A, @8C0&0D08,8Gtta:a8A, @8CG%T0 5$C08,8%an Jose8A, @8CYB08,8Mavana8A, @8DGJ$&$C08,85oseau8A, @8DGJ$&$C0& 5EPYBL$C8,8%anto Do#ingo8A, @8EL %0LW0DG58,8%an %alva!or8A, @8a5E&0D08,8%aint aeorge2s8A, @8aY0TEJ0L08,8auate#ala City8A, @8M0$T$8,8Port-au-Prince8A, @8MG&DY50%8,8Tegucigal"a8A, @8J0J0$C08,8`ingston8A, @8JE9$CG8,8Je6ico City8A, @8&$C050aY08,8Janagua8A, @8P0&0J08,8Pana#a City8A, @8%T. `$TT%8,8-8A, @8&EW$%8,8Basseterre8A, @8%T. LYC$08,8Castries8A, @8%T. W$&CE&T 0&D TME a5E&0D$&E%8,8`ingsto:n8A, @8Y&$TED %T0TE% GL 0JE5$C08,8\ashington, D.C.8A, // %outh 0#erica @805aE&T$&08,8Buenos 0ires8A, @8BGL$W$08,8%ucre -legal./La PaU-a!#inistrative.8A, @8B50T$L8,8Brasilia8A, @8CM$LE8,8%antiago8A, @8CGLGJB$08,8Bogota8A, @8ECY0DG58,8/uito8A, @8aY;0&08,8aeorgeto:n8A, @8P050aY0;8,80suncion8A, @8PE5Y8,8Li#a8A, @8%Y5$&0JE8,8Para#aribo8A, @8T5$&$D0D 0&D TGB0aG8,8Port of %"ain8A, @8Y5YaY0;8,8Jontevi!eo8A, @8WE&ETYEL08,8Caracas8A, A< A ///3>

This is si#%ly a two'di#ensional array o" )tring data@. (ere s a si#%le test using the fillA B #ethods and generators= //3 c'C3LillTest.Hava i#"ort co#.bruceeckel.util.B<
@ This data was "ound on the Internet, then %rocessed by creating a Python %rogra# *see ,,,'P)thon'org,.

474

i#"ort Hava.util.B< "ublic class LillTest @ static aenerator sg ? ne: 0rrays .5an!%tringaenerator-*.< "ublic static voi! #ain-%tringNO args. @ List list ? ne: 0rrayList-.< Collections .fill-list, sg, ,.< %yste#.out."rintln-list K 8_n8.< List list ? ne: 0rrayList-.< Collections .fill-list , Collections .ca"itals, ,.< %yste#.out."rintln-list K 8_n8.< %et set ? ne: Mash%et-.< Collections .fill-set, sg, ,.< %yste#.out."rintln-set K 8_n8.< Ja" # ? ne: MashJa"-.< Collections .fill-#, Collections .rs", %yste#.out."rintln-# K 8_n8.< Ja" # ? ne: MashJa"-.< Collections .fill-# , Collections .geogra"hy, ,.< %yste#.out."rintln-# .< A A ///3>

,.<

:ith these tools you can easily test the various containers by "illing the# with interesting data. RFSURFSTIJLT+(6PTE52TI3?U

Container disadvantage: unknown t:.e


The !disadvantage$ to using the Java containers is that you lose ty%e in"or#ation when you %ut an ob0ect into a container. This ha%%ens because the %rogra##er o" that container class had no idea what s%eci"ic ty%e you wanted to %ut in the container, and #aking the container hold

Cha ter ;! .olding Lour Ob>ects

475

only your ty%e would %revent it "ro# being a general'%ur%ose tool. So instead, the container holds re"erences to .b8ect, which is the root o" all the classes so it holds any ty%e. *)" course, this doesn t include %ri#itive ty%es, since they aren t inherited "ro# anything., This is a great solution, e&ce%t= RFSURFSTIJLT+(6PTE52TI3HU

4,)

Since the ty%e in"or#ation is thrown away when you %ut an ob0ect re"erence into a container, there s no restriction on the ty%e o" ob0ect that can be %ut into your container, even i" you #ean it to hold only, say, cats. So#eone could 0ust as easily %ut a dog into the container. RFSURFSTIJLT+(6PTE52TI33U Since the ty%e in"or#ation is lost, the only thing the container knows that it holds is a re"erence to an ob0ect. /ou #ust %er"or# a cast to the correct ty%e be"ore you use it. RFSURF STIJLT+(6PTE52TI3GU

4-)

)n the u% side, Java won t let you misuse the ob0ects that you %ut into a container. I" you throw a dog into a container o" cats and then try to treat everything in the container as a cat, you ll get a run'ti#e e&ce%tion when you %ull the dog re"erence out o" the cat container and try to cast it to a cat. RFSURFSTIJLT+(6PTE52TI3IU (ere s an e&a#%le using the basic workhorse container, Array+ist. Eor starters, you can think o" Array+ist as !an array that auto#atically e&%ands itsel".$ 4sing an Array+ist is straight"orward= create one, %ut ob0ects in using a''A B, and later get the# out with getA B using an inde& 90ust like you would with an array but without the sAuare brackets @. Array+ist also has a #ethod si7eA B to let you know how #any ele#ents have been added so you don t inadvertently run o"" the end and cause an e&ce%tion. RFSURFSTIJLT+(6PTE52TI32U Eirst, -at and

og classes are created=

//3 c'C3Cat.Hava "ublic class Cat @ "rivate int cat&u#ber< Cat-int i. @ cat&u#ber ? i< A voi! "rint-. @
@ This is a %lace where o%erator overloading would be nice.

477

%yste#.out."rintln-8Cat S8 K cat&u#ber.< A A ///3> //3 c'C3Dog.Hava "ublic class Dog @ "rivate int !og&u#ber< Dog-int i. @ !og&u#ber ? i< A voi! "rint-. @ %yste#.out."rintln-8Dog S8 K !og&u#ber.< A A ///3> -ats and ogs are %laced into the container, then %ulled out=

//3 c'C3Cats0n!Dogs.Hava // %i#"le container e6a#"le. i#"ort Hava.util.B< "ublic class Cats0n!Dogs @ "ublic static voi! #ain-%tringNO args. @ 0rrayList cats ? ne: 0rrayList-.< for-int i ? '< i P *< iKK. cats.a!!-ne: Cat-i..< // &ot a "roble# to a!! a !og to cats3 cats.a!!-ne: Dog-*..< for-int i ? '< i P cats.siUe-.< iKK. --Cat.cats.get-i..."rint-.< // Dog is !etecte! only at run-ti#e A A ///3>
The classes -at and og are distinct9they have nothing in co##on e&ce%t that they are .b8ects. *I" you don t e&%licitly say what class you re inheriting "ro#, you auto#atically inherit "ro# .b8ect., Since Array+ist holds .b8ects, you can not only %ut -at ob0ects into this container using the Array+ist #ethod a''A B, but you can also add og ob0ects without co#%laint at either co#%ile'ti#e or run'ti#e. :hen you go to "etch out what you think are -at ob0ects using the Array+ist #ethod getA B, you get back a re"erence to an ob0ect that you #ust cast to a -at. Then you need to surround the entire e&%ression with %arentheses

Cha ter ;! .olding Lour Ob>ects

478

to "orce the evaluation o" the cast be"ore calling the printA B #ethod "or -at, otherwise you ll get a synta& error. Then, at run'ti#e, when you try to cast the og ob0ect to a -at, you ll get an e&ce%tion. RFSURF STIJLT+(6PTE52TIG@U This is #ore than 0ust an annoyance. It s so#ething that can create di""icult'to'"ind bugs. I" one %art *or several %arts, o" a %rogra# inserts ob0ects into a container, and you discover only in a se%arate %art o" the %rogra# through an e&ce%tion that a bad ob0ect was %laced in the container, then you #ust "ind out where the bad insert occurred. )n the u%side, it s convenient to start with so#e standardi1ed container classes "or %rogra##ing, des%ite the scarcity and awkwardness. RFSURF STIJLT+(6PTE52TIGMU

1ometimes it works an:wa:


It turns out that in so#e cases things see# to work correctly without casting back to your original ty%e. )ne case is Auite s%ecial= the )tring class has so#e e&tra hel% "ro# the co#%iler to #ake it work s#oothly. :henever the co#%iler e&%ects a )tring ob0ect and it hasn t got one, it will auto#atically call the to)tringA B #ethod that s de"ined in .b8ect and can be overridden by any Java class. This #ethod %roduces the desired )tring ob0ect, which is then used wherever it was wanted. RF SURFSTIJLT+(6PTE52TIGKU Thus, all you need to do to #ake ob0ects o" your class %rint is to override the to)tringA B #ethod, as shown in the "ollowing e&a#%le=

//3 c'C3Jouse.Hava // Gverri!ing to%tring-.. "ublic class Jouse @ "rivate int #ouse&u#ber< Jouse-int i. @ #ouse&u#ber ? i< A // Gverri!e GbHect.to%tring-.3 "ublic %tring to%tring-. @ return 8This is Jouse S8 K #ouse&u#ber< A "ublic int get&u#ber-. @ return #ouse&u#ber< A

47:

A ///3> //3 c'C3\orks0ny:ay.Hava // $n s"ecial cases, things Hust // see# to :ork correctly. i#"ort Hava.util.B< class JouseTra" @ static voi! caught;a-GbHect #. @ Jouse #ouse ? -Jouse.#< // Cast fro# GbHect %yste#.out."rintln-8Jouse3 8 K #ouse.get&u#ber-..< A A "ublic class \orks0ny:ay @ "ublic static voi! #ain-%tringNO args. @ 0rrayList #ice ? ne: 0rrayList-.< for-int i ? '< i P )< iKK. #ice.a!!-ne: Jouse-i..< for-int i ? '< i P #ice.siUe-.< iKK. @ // &o cast necessary, auto#atic // call to GbHect.to%tring-.3 %yste#.out."rintln8Lree #ouse3 8 K #ice.get-i..< JouseTra".caught;a-#ice.get-i..< A A A ///3>
/ou can see to)tringA B overridden in 1o*se. In the second for loo% in mainA B you "ind the state#ent=

%yste#.out."rintln-8Lree #ouse3 8 K #ice.get-i..<


6"ter the [L sign the co#%iler e&%ects to see a )tring ob0ect. getA B %roduces an .b8ect, so to get the desired )tring the co#%iler i#%licitly calls to)tringA B. 4n"ortunately, you can work this kind o" #agic only with )tring; it isn t available "or any other ty%e. RFSURF STIJLT+(6PTE52TIGLU

Cha ter ;! .olding Lour Ob>ects

47;

6 second a%%roach to hiding the cast has been %laced inside

1o*seTrap. The ca*ght:aA B #ethod acce%ts not a 1o*se, but an .b8ect, which it then casts to a 1o*se. This is Auite %resu#%tuous, o" course, since by acce%ting an .b8ect anything could be %assed to the
#ethod. (owever, i" the cast is incorrect9i" you %assed the wrong ty%e9 you ll get an e&ce%tion at run'ti#e. This is not as good as co#%ile'ti#e checking but it s still robust. Cote that in the use o" this #ethod=

JouseTra".caught;a-#ice.get-i..<
no cast is necessary. RFSURFSTIJLT+(6PTE52TIG?U

Making a t:.e@conscious Array#ist


/ou #ight not want to give u% on this issue 0ust yet. 6 #ore ironclad solution is to create a new class using the Array+ist, such that it will acce%t only your ty%e and %roduce only your ty%e=

//3 c'C3JouseList.Hava // 0 ty"e-conscious 0rrayList. i#"ort Hava.util.B< "ublic class JouseList @ "rivate 0rrayList list ? ne: 0rrayList-.< "ublic voi! a!!-Jouse #. @ list.a!!-#.< A "ublic Jouse get-int in!e6. @ return -Jouse.list.get-in!e6.< A "ublic int siUe-. @ return list.siUe-.< A A ///3>
(ere s a test "or the new container=

//3 c'C3JouseListTest.Hava "ublic class JouseListTest @ "ublic static voi! #ain-%tringNO args. @ JouseList #ice ? ne: JouseList-.< for-int i ? '< i P )< iKK. #ice.a!!-ne: Jouse-i..< for-int i ? '< i P #ice.siUe-.< iKK.

48=

JouseTra".caught;a-#ice.get-i..< A A ///3>
This is si#ilar to the %revious e&a#%le, e&ce%t that the new 1o*se+ist class has a private #e#ber o" ty%e Array+ist, and #ethods 0ust like Array+ist. (owever, it doesn t acce%t and %roduce generic .b8ects, only 1o*se ob0ects. RFSURFSTIJLT+(6PTE52TIGHU Cote that i" 1o*se+ist had instead been inherited "ro# Array+ist, the a''A1o*seB #ethod would si#%ly overload the e&isting a''A.b8ectB and there would still be no restriction on what ty%e o" ob0ects could be added. Thus, the 1o*se+ist beco#es a surrogate to the Array+ist, %er"or#ing so#e activities be"ore %assing on the res%onsibility *see Thinking in Patterns ,ith Java, downloadable at ,,,'0ruceEckel'com,. RFSURFSTIJLT+(6PTE52TIG3U Because a 1o*se+ist will acce%t only a 1o*se, i" you say=

#ice.a!!-ne: Pigeon-..<
you will get an error #essage at com ile/time. This a%%roach, while #ore tedious "ro# a coding stand%oint, will tell you i##ediately i" you re using a ty%e i#%ro%erly. RFSURFSTIJLT+(6PTE52TIGGU Cote that no cast is necessary when using getA B9it s always a 1o*se. RF SURFSTIJLT+(6PTE52TIGIU

arameteri?ed t:.es
This kind o" %roble# isn t isolated9there are nu#erous cases in which you need to create new ty%es based on other ty%es, and in which it is use"ul to have s%eci"ic ty%e in"or#ation at co#%ile'ti#e. This is the conce%t o" a arameteri?ed t) e. In +<<, this is directly su%%orted by the language with tem lates. It is likely that a "uture version o" Java will su%%ort so#e variation o" %ara#eteri1ed ty%es; the current "ront'runner auto#atically creates classes si#ilar to 1o*se+ist. RFSURF STIJLT+(6PTE52TIG2U

Cha ter ;! .olding Lour Ob>ects

481

Iterators
In any container class, you #ust have a way to %ut things in and a way to get things out. 6"ter all, that s the %ri#ary 0ob o" a container9to hold things. In the Array+ist, a''A B is the way that you insert ob0ects, and getA B is one way to get things out. Array+ist is Auite "le&ible9you can select anything at any ti#e, and select #ulti%le ele#ents at once using di""erent inde&es. RFSURFSTIJLT+(6PTE52TII@U I" you want to start thinking at a higher level, there s a drawback= you need to know the e&act ty%e o" the container in order to use it. This #ight not see# bad at "irst, but what i" you start out using an Array+ist, and later on in your %rogra# you discover that because o" the way you are using the container it would be #uch #ore e""icient to use a +inke'+ist insteadO )r su%%ose you d like to write a %iece o" generic code that doesn t know or care what ty%e o" container it s working with, so that it could be used on di""erent ty%es o" containers without rewriting that codeO RFSURFSTIJLT+(6PTE52TIIMU The conce%t o" an iterator can be used to achieve this abstraction. 6n iterator is an ob0ect whose 0ob is to #ove through a seAuence o" ob0ects and select each ob0ect in that seAuence without the client %rogra##er knowing or caring about the underlying structure o" that seAuence. In addition, an iterator is usually what s called a !light'weight$ ob0ect= one that s chea% to create. Eor that reason, you ll o"ten "ind see#ingly strange constraints "or iterators; "or e&a#%le, so#e iterators can #ove in only one direction. RFSURFSTIJLT+(6PTE52TIIKU The Java Iterator is an e&a#%le o" an iterator with these kinds o" constraints. There s not #uch you can do with one e&ce%t= RFSURF STIJLT+(6PTE52TIILU

44)

6sk a container to hand you an Iterator using a #ethod called iteratorA B. This Iterator will be ready to return the "irst ele#ent in the seAuence on your "irst call to its ne4tA B #ethod. 8et the ne&t ob0ect in the seAuence with ne4tA B. See i" there are any #ore ob0ects in the seAuence with has/e4tA B.

45) 46)

482

57)

5e#ove the last ele#ent returned by the iterator with removeA B.

That s all. It s a si#%le i#%le#entation o" an iterator, but still %ower"ul *and there s a #ore so%histicated +istIterator "or +ists,. To see how it works, let s revisit the -atsAn' ogs!8ava %rogra# "ro# earlier in this cha%ter. In the original version, the #ethod getA B was used to select each ele#ent, but in the "ollowing #odi"ied version an Iterator is used= RF SURFSTIJLT+(6PTE52TII?U

//3 c'C3Cats0n!Dogs .Hava // %i#"le container :ith $terator. i#"ort Hava.util.B< "ublic class Cats0n!Dogs @ "ublic static voi! #ain-%tringNO args. @ 0rrayList cats ? ne: 0rrayList-.< for-int i ? '< i P *< iKK. cats.a!!-ne: Cat-i..< $terator e ? cats.iterator-.< :hile-e.has&e6t-.. --Cat.e.ne6t-..."rint-.< A A ///3>
/ou can see that the last "ew lines now use an Iterator to ste% through the seAuence instead o" a for loo%. :ith the Iterator, you don t need to worry about the nu#ber o" ele#ents in the container. That s taken care o" "or you by has/e4tA B and ne4tA B. RFSURFSTIJLT+(6PTE52TIIHU 6s another e&a#%le, consider the creation o" a general'%ur%ose %rinting #ethod=

//3 c'C3Ma#sterJaUe.Hava // Ysing an $terator. i#"ort Hava.util.B< class Ma#ster @ "rivate int ha#ster&u#ber< Ma#ster-int i. @ ha#ster&u#ber ? i< A "ublic %tring to%tring-. @ return 8This is Ma#ster S8 K ha#ster&u#ber< A

Cha ter ;! .olding Lour Ob>ects

483

A class Printer @ static voi! "rint0ll-$terator e. @ :hile-e.has&e6t-.. %yste#.out."rintln-e.ne6t-..< A A "ublic class Ma#sterJaUe @ "ublic static voi! #ain-%tringNO args. @ 0rrayList v ? ne: 0rrayList-.< for-int i ? '< i P )< iKK. v.a!!-ne: Ma#ster-i..< Printer."rint0ll-v.iterator-..< A A ///3>
Dook closely at printAllA B. Cote that there s no in"or#ation about the ty%e o" seAuence. 6ll you have is an Iterator, and that s all you need to know about the seAuence= that you can get the ne&t ob0ect, and that you can know when you re at the end. This idea o" taking a container o" ob0ects and %assing through it to %er"or# an o%eration on each one is %ower"ul, and will be seen throughout this book. RFSURF STIJLT+(6PTE52TII3U The e&a#%le is even #ore generic, since it i#%licitly uses the .b8ect! to)tringA B #ethod. The printlnA B #ethod is overloaded "or all the %ri#itive ty%es as well as .b8ect; in each case a )tring is auto#atically %roduced by calling the a%%ro%riate to)tringA B #ethod. RFSURF STIJLT+(6PTE52TIIGU 6lthough it s unnecessary, you can be #ore e&%licit using a cast, which has the e""ect o" calling to)tringA B=

%yste#.out."rintln--%tring.e.ne6t-..<
In general, however, you ll want to do so#ething #ore than call .b8ect #ethods, so you ll run u% against the ty%e'casting issue again. /ou #ust assu#e you ve gotten an Iterator to a seAuence o" the %articular ty%e

484

you re interested in, and cast the resulting ob0ects to that ty%e *getting a run'ti#e e&ce%tion i" you re wrong,. RFSURFSTIJLT+(6PTE52TIIIU

Cnintended recursion
Because *like every other class,, the Java standard containers are inherited "ro# .b8ect, they contain a to)tringA B #ethod. This has been overridden so that they can %roduce a )tring re%resentation o" the#selves, including the ob0ects they hold. Inside Array+ist, "or e&a#%le, the to)tringA B ste%s through the ele#ents o" the Array+ist and calls to)tringA B "or each one. Su%%ose you d like to %rint the address o" your class. It see#s to #ake sense to si#%ly re"er to this *in %articular, +<< %rogra##ers are %rone to this a%%roach,=

//3 c'C3$nfinite5ecursion.Hava // 0cci!ental recursion. i#"ort Hava.util.B< "ublic class $nfinite5ecursion @ "ublic %tring to%tring-. @ return 8 $nfinite5ecursion a!!ress3 8 K this K 8_n8< A "ublic static voi! #ain-%tringNO args. @ 0rrayList v ? ne: 0rrayList-.< for-int i ? '< i P ('< iKK. v.a!!-ne: $nfinite5ecursion-..< %yste#.out."rintln-v.< A A ///3>
I" you si#%ly create an Infinite$ec*rsion ob0ect and then %rint it, you ll get an endless seAuence o" e&ce%tions. This is also true i" you %lace the Infinite$ec*rsion ob0ects in an Array+ist and %rint that Array+ist as shown here. :hat s ha%%ening is auto#atic ty%e conversion "or )trings. :hen you say=

8$nfinite5ecursion a!!ress3 8 K this


The co#%iler sees a )tring "ollowed by a [L and so#ething that s not a )tring, so it tries to convert this to a )tring. It does this conversion by

Cha ter ;! .olding Lour Ob>ects

485

calling to)tringA B, which %roduces a recursive call. RFSURF STIJLT+(6PTE52TII2U I" you really do want to %rint the address o" the ob0ect in this case, the solution is to call the .b8ect to)tringA B #ethod, which does 0ust that. So instead o" saying this, you d say s*per!to)tringA B. *This only works i" youVre directly inheriting "ro# .b8ect, or i" none o" your %arent classes have overridden the to)tringA B #ethod., RFSURF STIJLT+(6PTE52TI2@U

Container ta0onom:
-ollections and 1aps #ay be i#%le#ented in di""erent ways, according
to your %rogra##ing needs. It s hel%"ul to look at a diagra# o" the Java K containers=

487

Iterator

roduces

Collection

roduces

Ma.

&istIterator

roduces

AbstractMa. &ist 1et 1ortedMa.

AbstractCollection

1orted1et Abstract1et >ashMa.


Weak>ashMa.

Abstract&ist

#reeMa. >ashtable 8&egac:9 Ctilities

>ash1et

#ree1et

=ector 8&egac:9 1tack 8&egac:9

Arra:&ist

Abstract1e%uential&ist

Collections Arra:s

&inked&ist Com.arable Com.arator

This diagra# can be a bit overwhel#ing at "irst, but you ll see that there are really only three container co#%onents= 1ap, +ist, and )et, and only two or three i#%le#entations o" each one *with, ty%ically, a %re"erred version,. :hen you see this, the containers are not so daunting. RFSURF STIJLT+(6PTE52TI2MU The dotted bo&es re%resent interfaces, the dashed bo&es re%resent abstract classes, and the solid bo&es are regular *concrete, classes. The dotted'line arrows indicate that a %articular class is i#%le#enting an interface *or in the case o" an abstract class, %artially i#%le#enting that interface,. The solid arrows show that a class can %roduce ob0ects o" the class the arrow is %ointing to. Eor e&a#%le, any -ollection can %roduce an Iterator, while a +ist can %roduce a +istIterator *as well as an ordinary Iterator, since +ist is inherited "ro# -ollection,. RFSURF STIJLT+(6PTE52TI2KU

Cha ter ;! .olding Lour Ob>ects

488

The inter"aces that are concerned with holding ob0ects are -ollection, +ist, )et, and 1ap. Ideally, you ll write #ost o" your code to talk to these inter"aces, and the only %lace where you ll s%eci"y the %recise ty%e you re using is at the %oint o" creation. So you can create a +ist like this= RFSURF STIJLT+(6PTE52TI2LU

List 6 ? ne: Linke!List-.<


)" course, you can also decide to #ake 4 a +inke'+ist *instead o" a generic +ist, and carry the %recise ty%e in"or#ation around with 4. The beauty *and the intent, o" using the interface is that i" you decide you want to change your i#%le#entation, all you need to do is change it at the %oint o" creation, like this=

List 6 ? ne: 0rrayList-.<


The rest o" your code can re#ain untouched *so#e o" this genericity can also be achieved with iterators,. RFSURFSTIJLT+(6PTE52TI2?U In the class hierarchy, you can see a nu#ber o" classes whose na#es begin with ! Abstract,$ and these can see# a bit con"using at "irst. They are si#%ly tools that %artially i#%le#ent a %articular inter"ace. I" you were #aking your own )et, "or e&a#%le, you wouldn t start with the )et inter"ace and i#%le#ent all the #ethods, instead you d inherit "ro# Abstract)et and do the #ini#al necessary work to #ake your new class. (owever, the containers library contains enough "unctionality to satis"y your needs virtually all the ti#e. So "or our %ur%oses, you can ignore any class that begins with ! Abstract.$ RFSURFSTIJLT+(6PTE52TI2HU There"ore, when you look at the diagra#, you re really concerned with only those interfaces at the to% o" the diagra# and the concrete classes *those with solid bo&es around the#,. /ou ll ty%ically #ake an ob0ect o" a concrete class, u%cast it to the corres%onding interface, and then use the interface throughout the rest o" your code. In addition, you do not need to consider the legacy ele#ents when writing new code. There"ore, the diagra# can be greatly si#%li"ied to look like this=

48:

Iterator

roduces

Collection

roduces

Ma.

&istIterator
roduces

&ist

1et

>ashMa.

#reeMa.

Weak>ashMa.

Arra:&ist

&inked&ist

>ash1et

#ree1et

Ctilities Collections

Com.arable

Com.arator

Arra:s

Cow it only includes the inter"aces and classes that you will encounter on a regular basis, and also the ele#ents that we will "ocus on in this cha%ter. RFSURFSTIJLT+(6PTE52TI23U (ere s a si#%le e&a#%le, which "ills a -ollection *re%resented here with an Array+ist, with )tring ob0ects, and then %rints each ele#ent in the -ollection=

//3 c'C3%i#"leCollection.Hava // 0 si#"le e6a#"le using Java i#"ort Hava.util.B<

Collections.

"ublic class %i#"leCollection @ "ublic static voi! #ain-%tringNO args. @ // Y"cast because :e Hust :ant to // :ork :ith Collection features Collection c ? ne: 0rrayList-.< for-int i ? '< i P ('< iKK. c.a!!-$nteger.to%tring-i..< $terator it ? c.iterator-.< :hile-it.has&e6t-.. %yste#.out."rintln-it.ne6t-..< A A ///3>

Cha ter ;! .olding Lour Ob>ects

48;

The "irst line in mainA B creates an Array+ist ob0ect and then u%casts it to a -ollection. Since this e&a#%le uses only the -ollection #ethods, any ob0ect o" a class inherited "ro# -ollection would work, but Array+ist is the ty%ical workhorse -ollection. RFSURF STIJLT+(6PTE52TI2GU The a''A B #ethod, as its na#e suggests, %uts a new ele#ent in the -ollection. (owever, the docu#entation care"ully states that a''A B !ensures that this +ontainer contains the s%eci"ied ele#ent.$ This is to allow "or the #eaning o" )et, which adds the ele#ent only i" it isn t already there. :ith an Array+ist, or any sort o" +ist, a''A B always #eans !%ut it in,$ because +ists don t care i" there are du%licates. RFSURF STIJLT+(6PTE52TI2IU 6ll -ollections can %roduce an Iterator via their iteratorA B #ethod. (ere, an Iterator is created and used to traverse the -ollection, %rinting each ele#ent. RFSURFSTIJLT+(6PTE52TI22U

$ollection functionalit:
The "ollowing table shows everything you can do with a -ollection *not including the #ethods that auto#atically co#e through with .b8ect,, and thus, everything you can do with a )et or a +ist. * +ist also has additional "unctionality., 1aps are not inherited "ro# -ollection, and will be treated se%arately.

boolean a''A.b8ectB

boolean a''AllA-ollectionB voi' clearA B boolean containsA.b8ectB

Ensures that the container holds the argu#ent. 5eturns "alse i" it doesn t add the argu#ent. *This is an !o%tional$ #ethod, described later in this cha%ter., 6dds all the ele#ents in the argu#ent. 5eturns tr*e i" any ele#ents were added. *!)%tional.$, 5e#oves all the ele#ents in the container. *!)%tional.$, tr*e i" the container holds the argu#ent.

4:=

boolean containsAll A-ollectionB boolean is&mptyA B Iterator iteratorA B boolean removeA.b8ectB boolean removeAll A-ollectionB boolean retainAll A-ollectionB

int si7eA B .b8ect]^ toArrayA B .b8ect]^ toArrayA.b8ect]^ aB

tr*e i" the container holds all the ele#ents in the argu#ent. tr*e i" the container has no ele#ents. 5eturns an Iterator that you can use to #ove through the ele#ents in the container. I" the argu#ent is in the container, one instance o" that ele#ent is re#oved. 5eturns tr*e i" a re#oval occurred. *!)%tional.$, 5e#oves all the ele#ents that are contained in the argu#ent. 5eturns tr*e i" any re#ovals occurred. *!)%tional.$, 5etains only ele#ents that are contained in the argu#ent *an !intersection$ "ro# set theory,. 5eturns tr*e i" any changes occurred. *!)%tional.$, 5eturns the nu#ber o" ele#ents in the container. 5eturns an array containing all the ele#ents in the container. 5eturns an array containing all the ele#ents in the container, whose ty%e is that o" the array a rather than %lain .b8ect *you #ust cast the array to the right ty%e,.

Cotice that there s no getA B "unction "or rando#'access ele#ent selection. That s because -ollection also includes )et, which #aintains its own internal ordering *and thus #akes rando#'access looku% #eaningless,. Thus, i" you want to e&a#ine all the ele#ents o" a -ollection you #ust use an iterator; that s the only way to "etch things back. The "ollowing e&a#%le de#onstrates all o" these #ethods. 6gain, these work with anything that inherits "ro# -ollection, but an Array+ist is used as a kind o" !least'co##on deno#inator$= RFSURF STIJLT+(6PTE52TIM@@U

Cha ter ;! .olding Lour Ob>ects

4:1

//3 c'C3Collection(.Hava // Things you can !o :ith all Collections. i#"ort Hava.util.B< i#"ort co#.bruceeckel.util.B< "ublic class Collection( @ "ublic static voi! #ain-%tringNO args. @ Collection c ? ne: 0rrayList-.< Collections .fill-c, Collections .countries, ('.< c.a!!-8ten8.< c.a!!-8eleven8.< %yste#.out."rintln-c.< // Jake an array fro# the List3 GbHectNO array ? c.to0rray-.< // Jake a %tring array fro# the List3 %tringNO str ? -%tringNO.c.to0rray-ne: %tringN(O.< // Lin! #a6 an! #in ele#ents< this #eans // !ifferent things !e"en!ing on the :ay // the Co#"arable interface is i#"le#ente!3 %yste#.out."rintln-8Collections.#a6-c. ? 8 K Collections.#a6-c..< %yste#.out."rintln-8Collections.#in-c. ? 8 K Collections.#in-c..< // 0!! a Collection to another Collection Collection c ? ne: 0rrayList-.< Collections .fill-c , Collections .countries, ('.< c.a!!0ll-c .< %yste#.out."rintln-c.< c.re#ove-CountryCa"itals."airsN'ON'O.< %yste#.out."rintln-c.< c.re#ove-CountryCa"itals."airsN(ON'O.< %yste#.out."rintln-c.< // 5e#ove all co#"onents that are in the // argu#ent collection3 c.re#ove0ll-c .< %yste#.out."rintln-c.< c.a!!0ll-c .< %yste#.out."rintln-c.<

4:2

// $s an ele#ent in this Collection[ %tring val ? CountryCa"itals."airsN)ON'O< %yste#.out."rintln8c.contains-8 K val K 8. ? 8 K c.contains-val..< // $s a Collection in this Collection[ %yste#.out."rintln8c.contains0ll-c . ? 8K c.contains0ll-c ..< Collection c) ? --List.c..subList-), ,.< // `ee" all the ele#ents that are in both // c an! c) -an intersection of sets.3 c .retain0ll-c).< %yste#.out."rintln-c.< // Thro: a:ay all the ele#ents // in c that also a""ear in c)3 c .re#ove0ll-c).< %yste#.out."rintln-8c.isE#"ty-. ? 8 K c.isE#"ty-..< c ? ne: 0rrayList-.< Collections .fill-c, Collections .countries, ('.< %yste#.out."rintln-c.< c.clear-.< // 5e#ove all ele#ents %yste#.out."rintln-8after c.clear-.38.< %yste#.out."rintln-c.< A A ///3> Array+ists are created containing di""erent sets o" data and u%cast to -ollection ob0ects, so it s clear that nothing other than the -ollection inter"ace is being used. mainA B uses si#%le e&ercises to show all o" the #ethods in -ollection. RFSURFSTIJLT+(6PTE52TIM@MU
The "ollowing sections describe the various i#%le#entations o" +ist, )et, and 1ap and indicate in each case *with an asterisk, which one should be your de"ault choice. /ou ll notice that the legacy classes Vector, )tack, and Hashtable are not included because in all cases there are %re"erred classes within the Java K +ontainers. RFSURFSTIJLT+(6PTE52TIM@KU

Cha ter ;! .olding Lour Ob>ects

4:3

#ist functionalit:
The basic +ist is Auite si#%le to use, as you ve seen so "ar with Array+ist. 6lthough #ost o" the ti#e you ll 0ust use a''A B to insert ob0ects, getA B to get the# out one at a ti#e, and iteratorA B to get an Iterator to "or the seAuence, there s also a set o" other #ethods that can be use"ul. RFSURFSTIJLT+(6PTE52TIM@LU In addition, there are actually two ty%es o" +ist= the basic Array+ist, which e&cels at rando#ly accessing ele#ents, and the #uch #ore %ower"ul +inke'+ist *which is not designed "or "ast rando# access, but has a #uch #ore general set o" #ethods,.

+ist
*inter"ace,

Array+ist
B

+inke'+i st

)rder is the #ost i#%ortant "eature o" a +ist; it %ro#ises to #aintain ele#ents in a %articular seAuence. +ist adds a nu#ber o" #ethods to -ollection that allow insertion and re#oval o" ele#ents in the #iddle o" a +ist. *This is reco##ended only "or a +inke'+ist., 6 +ist will %roduce a +istIterator, and using this you can traverse the +ist in both directions, as well as insert and re#ove ele#ents in the #iddle o" the +ist. 6 +ist i#%le#ented with an array. 6llows ra%id rando# access to ele#ents, but is slow when inserting and re#oving ele#ents "ro# the #iddle o" a list. +istIterator should be used only "or back'and'"orth traversal o" an Array+ist, but not "or inserting and re#oving ele#ents, which is e&%ensive co#%ared to +inke'+ist. Provides o%ti#al seAuential access, with ine&%ensive insertions and deletions "ro# the #iddle o" the +ist. 5elatively slow "or rando# access. *4se Array+ist instead., 6lso has a''FirstA B, a''+astA B, getFirstA B, get+ast A B, removeFirstA B, and remove+astA B *which are not de"ined in any inter"aces or base classes, to allow it to be used as a stack, a Aueue, and a deAue.

4:4

The #ethods in the "ollowing e&a#%le each cover a di""erent grou% o" activities= things that every list can do * basicTestA B,, #oving around with an Iterator * iter1otionA B, versus changing things with an Iterator * iter1anip*lationA B,, seeing the e""ects o" +ist #ani%ulation * testVis*alA B,, and o%erations available only to +inke'+ists.

//3 c'C3List(.Hava // Things you can !o :ith Lists. i#"ort Hava.util.B< i#"ort co#.bruceeckel.util.B< "ublic class List( @ "ublic static List fill-List a. @ Collections .countries.reset-.< Collections .fill-a, Collections .countries, ('.< return a< A static boolean b< static GbHect o< static int i< static $terator it< static List$terator lit< "ublic static voi! basicTest-List a. @ a.a!!-(, 868.< // 0!! at location ( a.a!!-868.< // 0!! at en! // 0!! a collection3 a.a!!0ll-fill-ne: 0rrayList-...< // 0!! a collection starting at location )3 a.a!!0ll-), fill-ne: 0rrayList-...< b ? a.contains-8(8.< // $s it in there[ // $s the entire collection in there[ b ? a.contains0ll-fill-ne: 0rrayList-...< // Lists allo: ran!o# access, :hich is chea" // for 0rrayList, e6"ensive for Linke!List3 o ? a.get-(.< // aet obHect at location ( i ? a.in!e6Gf-8(8.< // Tell in!e6 of obHect b ? a.isE#"ty-.< // 0ny ele#ents insi!e[ it ? a.iterator-.< // Gr!inary $terator lit ? a.list$terator-.< // List$terator

Cha ter ;! .olding Lour Ob>ects

4:5

lit ? a.list$terator-).< // %tart at loc ) i ? a.last$n!e6Gf-8(8.< // Last #atch a.re#ove-(.< // 5e#ove location ( a.re#ove-8)8.< // 5e#ove this obHect a.set-(, 8y8.< // %et location ( to 8y8 // `ee" everything that2s in the argu#ent // -the intersection of the t:o sets.3 a.retain0ll-fill-ne: 0rrayList-...< // 5e#ove everything that2s in the argu#ent3 a.re#ove0ll-fill-ne: 0rrayList-...< i ? a.siUe-.< // Mo: big is it[ a.clear-.< // 5e#ove all ele#ents A "ublic static voi! iterJotion-List a. @ List$terator it ? a.list$terator-.< b ? it.has&e6t-.< b ? it.hasPrevious-.< o ? it.ne6t-.< i ? it.ne6t$n!e6-.< o ? it."revious-.< i ? it."revious$n!e6-.< A "ublic static voi! iterJani"ulation-List a. @ List$terator it ? a.list$terator-.< it.a!!-8I*8.< // Just #ove to an ele#ent after a!!-.3 it.ne6t-.< // 5e#ove the ele#ent that :as Hust "ro!uce!3 it.re#ove-.< // Just #ove to an ele#ent after re#ove-.3 it.ne6t-.< // Change the ele#ent that :as Hust "ro!uce!3 it.set-8I*8.< A "ublic static voi! testWisual-List a. @ %yste#.out."rintln-a.< List b ? ne: 0rrayList-.< fill-b.< %yste#.out."rint-8b ? 8.< %yste#.out."rintln-b.< a.a!!0ll-b.<

4:7

a.a!!0ll-fill-ne: 0rrayList-...< %yste#.out."rintln-a.< // $nsert, re#ove, an! re"lace ele#ents // using a List$terator3 List$terator 6 ? a.list$terator-a.siUe-./ .< 6.a!!-8one8.< %yste#.out."rintln-a.< %yste#.out."rintln-6.ne6t-..< 6.re#ove-.< %yste#.out."rintln-6.ne6t-..< 6.set-8I*8.< %yste#.out."rintln-a.< // Traverse the list back:ar!s3 6 ? a.list$terator-a.siUe-..< :hile-6.hasPrevious-.. %yste#.out."rint-6."revious-. K 8 8.< %yste#.out."rintln-.< %yste#.out."rintln-8testWisual finishe!8.< A // There are so#e things that only // Linke!Lists can !o3 "ublic static voi! testLinke!List-. @ Linke!List ll ? ne: Linke!List-.< fill-ll.< %yste#.out."rintln-ll.< // Treat it like a stack, "ushing3 ll.a!!Lirst-8one8.< ll.a!!Lirst-8t:o8.< %yste#.out."rintln-ll.< // Like 8"eeking8 at the to" of a stack3 %yste#.out."rintln-ll.getLirst-..< // Like "o""ing a stack3 %yste#.out."rintln-ll.re#oveLirst-..< %yste#.out."rintln-ll.re#oveLirst-..< // Treat it like a =ueue, "ulling ele#ents // off the tail en!3 %yste#.out."rintln-ll.re#oveLast-..< // \ith the above o"erations, it2s a !e=ueue4 %yste#.out."rintln-ll.< A "ublic static voi! #ain-%tringNO args. @

Cha ter ;! .olding Lour Ob>ects

4:8

// Jake an! fill a ne: list each ti#e3 basicTest-fill-ne: Linke!List-...< basicTest-fill-ne: 0rrayList-...< iterJotion-fill-ne: Linke!List-...< iterJotion-fill-ne: 0rrayList-...< iterJani"ulation-fill-ne: Linke!List-...< iterJani"ulation-fill-ne: 0rrayList-...< testWisual-fill-ne: Linke!List-...< testLinke!List-.< A A ///3>
In basicTestA B and iter1otionA B the calls are si#%ly #ade to show the %ro%er synta&, and while the return value is ca%tured, it is not used. In so#e cases, the return value isn t ca%tured since it isn t ty%ically used. /ou should look u% the "ull usage o" each o" these #ethods in the online docu#entation "ro# >ava'sun'com be"ore you use the#. RFSURF STIJLT+(6PTE52TIM@?U

Making a stack from a #inked#ist


6 stack is so#eti#es re"erred to as a !last'in, "irst'out$ *DIE), container. That is, whatever you !%ush$ on the stack last is the "irst ite# you can !%o%$ out. Dike all o" the other containers in Java, what you %ush and %o% are .b8ects, so you #ust cast what you %o%, unless you re 0ust using .b8ect behavior. RFSURFSTIJLT+(6PTE52TIM@HU The +inke'+ist has #ethods that directly i#%le#ent stack "unctionality, so you can also 0ust use a +inke'+ist rather than #aking a stack class. (owever, a stack class can so#eti#es tell the story better= RF SURFSTIJLT+(6PTE52TIM@3U

//3 c'C3%tackL.Hava // Jaking a stack fro# a Linke!List. i#"ort Hava.util.B< i#"ort co#.bruceeckel.util.B< "ublic class %tackL @ "rivate Linke!List list ? ne: Linke!List-.< "ublic voi! "ush-GbHect v. @ list.a!!Lirst-v.<

4::

A "ublic GbHect to"-. @ return list.getLirst-.< A "ublic GbHect "o"-. @ return list.re#oveLirst-.< A "ublic static voi! #ain-%tringNO args. @ %tackL stack ? ne: %tackL-.< for-int i ? '< i P ('< iKK. stack."ush-Collections .countries.ne6t-..< %yste#.out."rintln-stack.to"-..< %yste#.out."rintln-stack.to"-..< %yste#.out."rintln-stack."o"-..< %yste#.out."rintln-stack."o"-..< %yste#.out."rintln-stack."o"-..< A A ///3>
I" you want only stack behavior, inheritance is ina%%ro%riate here because it would %roduce a class with all the rest o" the +inke'+ist #ethods *you ll see later that this very #istake was #ade by the Java M.@ library designers with )tack,. RFSURFSTIJLT+(6PTE52TIM@GU

Making a %ueue from a #inked#ist


6 #ueue is a ! $irst/inD $irst/out$ *EIE), container. That is, you %ut things in at one end, and %ull the# out at the other. So the order in which you %ut the# in will be the sa#e order that they co#e out. +inke'+ist has #ethods to su%%ort Aueue behavior, so these can be used in a 3*e*e class=

//3 c'C3/ueue.Hava // Jaking a =ueue fro# a Linke!List. i#"ort Hava.util.B< "ublic class /ueue @ "rivate Linke!List list ? ne: Linke!List-.< "ublic voi! "ut-GbHect v. @ list.a!!Lirst-v.< A "ublic GbHect get-. @ return list.re#oveLast-.< A "ublic boolean isE#"ty-. @

Cha ter ;! .olding Lour Ob>ects

4:;

return list.isE#"ty-.< A "ublic static voi! #ain-%tringNO args. @ /ueue =ueue ? ne: /ueue-.< for-int i ? '< i P ('< iKK. =ueue."ut-$nteger.to%tring-i..< :hile-4=ueue.isE#"ty-.. %yste#.out."rintln-=ueue.get-..< A A ///3>
/ou can also easily create a de#ue *double'ended Aueue, "ro# a +inke'+ist. This is like a Aueue, but you can add and re#ove ele#ents "ro# either end. RFSURFSTIJLT+(6PTE52TIM@IU

Set functionalit:
)et has e&actly the sa#e inter"ace as -ollection, so there isn t any e&tra "unctionality like there is with the two di""erent +ists. Instead, the )et is e&actly a -ollection, it 0ust has di""erent behavior. *This is the ideal use o" inheritance and %oly#or%his#= to e&%ress di""erent behavior., 6 )et re"uses to hold #ore than one instance o" each ob0ect value *what constitutes the !value$ o" an ob0ect is #ore co#%le&, as you shall see,. )et
*inter"ace, Each ele#ent that you add to the )et #ust be uniAue; otherwise the )et doesn t add the du%licate ele#ent. .b8ects added to a )et #ust de"ine eC*alsA B to establish ob0ect uniAueness. )et has e&actly the sa#e inter"ace as -ollection. The )et inter"ace does not guarantee it will #aintain its ele#ents in any %articular order. Eor )ets where "ast looku% ti#e is i#%ortant. .b8ects #ust also de"ine hash-o'eA B. 6n ordered )et backed by a tree. This way, you can e&tract an ordered seAuence "ro# a )et.

Hash)etB Tree)et

The "ollowing e&a#%le does not show everything you can do with a )et, since the inter"ace is the sa#e as -ollection, and so was e&ercised in the %revious e&a#%le. Instead, this de#onstrates the behavior that #akes a )et uniAue=

4;=

//3 c'C3%et(.Hava // Things you can !o :ith %ets. i#"ort Hava.util.B< i#"ort co#.bruceeckel.util.B< "ublic class %et( @ static Collections .%tringaenerator gen ? Collections .countries< "ublic static voi! testWisual-%et a. @ Collections .fill-a, gen.reset-., ('.< Collections .fill-a, gen.reset-., ('.< Collections .fill-a, gen.reset-., ('.< %yste#.out."rintln-a.< // &o !u"licates4 // 0!! another set to this one3 a.a!!0ll-a.< a.a!!-8one8.< a.a!!-8one8.< a.a!!-8one8.< %yste#.out."rintln-a.< // Look so#ething u"3 %yste#.out."rintln-8a.contains-_8one_8.3 8 K a.contains-8one8..< A "ublic static voi! #ain-%tringNO args. @ %yste#.out."rintln-8Mash%et8.< testWisual-ne: Mash%et-..< %yste#.out."rintln-8Tree%et8.< testWisual-ne: Tree%et-..< A A ///3>
7u%licate values are added to the )et, but when it is %rinted you ll see the )et has acce%ted only one instance o" each value. RFSURF STIJLT+(6PTE52TIM@2U :hen you run this %rogra# you ll notice that the order #aintained by the

Hash)et is di""erent "ro# Tree)et, since each has a di""erent way o" storing ele#ents so they can be located later. * Tree)et kee%s the# sorted, while Hash)et uses a hashing "unction, which is designed
s%eci"ically "or ra%id looku%s., :hen creating your own ty%es, be aware that a )et needs a way to #aintain a storage order, which #eans you

Cha ter ;! .olding Lour Ob>ects

4;1

#ust i#%le#ent the -omparable inter"ace and de"ine the compareTo A B #ethod. (ere s an e&a#%le=

//3 c'C3%et .Hava // Putting your o:n ty"e in a %et. i#"ort Hava.util.B< class JyTy"e i#"le#ents Co#"arable @ "rivate int i< "ublic JyTy"e-int n. @ i ? n< A "ublic boolean e=uals-GbHect o. @ return -o instanceof JyTy"e. DD -i ?? --JyTy"e.o..i.< A "ublic int hashCo!e-. @ return i< A "ublic %tring to%tring-. @ return i K 8 8< A "ublic int co#"areTo-GbHect o. @ int i ? --JyTy"e.o..i< return -i P i [ -( 3 -i ?? i [ ' 3 (..< A A "ublic class %et @ "ublic static %et fill-%et a, int siUe. @ for-int i ? '< i P siUe< iKK. a.a!!-ne: JyTy"e-i..< return a< A "ublic static voi! test-%et a. @ fill-a, ('.< fill-a, ('.< // Try to a!! !u"licates fill-a, ('.< a.a!!0ll-fill-ne: Tree%et-., ('..< %yste#.out."rintln-a.< A "ublic static voi! #ain-%tringNO args. @ test-ne: Mash%et-..< test-ne: Tree%et-..< A A ///3>

4;2

The "or# "or the de"initions "or eC*alsA B and hash-o'eA B will be described later in this cha%ter. /ou #ust de"ine an eC*alsA B in both cases, but the hash-o'eA B is absolutely necessary only i" the class will be %laced in a Hash)et *which is likely, since that should generally be your "irst choice as a )et i#%le#entation,. (owever, as a %rogra##ing style you should always override hash-o'eA B when you override eC*alsA B. This %rocess will be "ully detailed later in this cha%ter. RFSURF STIJLT+(6PTE52TIMM@U In the compareToA B, note that I did not use the !si#%le and obvious$ "or# ret*rn i6iI. 6lthough this is a co##on %rogra##ing error, it would only work %ro%erly i" i and iI were !unsigned$ ints *i" Java had an !unsigned$ keyword, which it does not,. It breaks "or Java s signed int, which is not big enough to re%resent the di""erence o" two signed ints. I" i is a large %ositive integer and 8 is a large negative integer, i68 will over"low and return a negative value, which will not work. RFSURF STIJLT+(6PTE52TIMMMU

SortedSet
I" you have a )orte')et *o" which Tree)et is the only one available,, the ele#ents are guaranteed to be in sorted order which allows additional "unctionality to be %rovided with these #ethods in the )orte')et inter"ace= RFSURFSTIJLT+(6PTE52TIMMKU

-omparator comparatorAB< Produces the -omparator used "or this )et, or n*ll "or natural ordering. .b8ect firstAB< Produces the lowest ele#ent. .b8ect lastAB< Produces the highest ele#ent. )orte')et s*b)etAfrom&lement, to&lementB< Produces a view o" this )et with ele#ents "ro# from&lement, inclusive, to to&lement, e&clusive. )orte')et hea')etAto&lementB< Produces a view o" this )et with
ele#ents less than to&lement.

)orte')et tail)etAfrom&lementB< Produces a view o" this )et with ele#ents greater than or eAual to from&lement.

Cha ter ;! .olding Lour Ob>ects

4;3

3a

functionalit:

6n Array+ist allows you to select "ro# a seAuence o" ob0ects using a nu#ber, so in a sense it associates nu#bers to ob0ects. But what i" you d like to select "ro# a seAuence o" ob0ects using so#e other criterionO 6 stack is an e&a#%le= its selection criterion is !the last thing %ushed on the stack.$ 6 %ower"ul twist on this idea o" !selecting "ro# a seAuence$ is alternately ter#ed a ma , a dictionar)D or an associative arra). +once%tually, it see#s like an Array+ist, but instead o" looking u% ob0ects using a nu#ber, you look the# u% using another ob>ect. This is o"ten a key %rocess in a %rogra#. RFSURFSTIJLT+(6PTE52TIMMLU The conce%t shows u% in Java as the 1ap inter"ace. The p*tA.b8ect key, .b8ect val*eB #ethod adds a value *the thing you want,, and associates it with a key *the thing you look it u% with,. getA.b8ect keyB %roduces the value given the corres%onding key. /ou can also test a 1ap to see i" it contains a key or a value with contains%eyA B and containsVal*eA B. RFSURFSTIJLT+(6PTE52TIMM?U The standard Java library contains two di""erent ty%es o" 1aps= Hash1ap and Tree1ap. Both have the sa#e inter"ace *since they both i#%le#ent 1ap,, but they di""er in one distinct way= e""iciency. I" you look at what #ust be done "or a getA B, it see#s %retty slow to search through *"or e&a#%le, an Array+ist "or the key. This is where Hash1ap s%eeds things u%. Instead o" a slow search "or the key, it uses a s%ecial value called a hash code. The hash code is a way to take so#e in"or#ation in the ob0ect in Auestion and turn it into a !relatively uniAue$ int "or that ob0ect. 6ll Java ob0ects can %roduce a hash code, and hash-o'eA B is a #ethod in the root class .b8ect. 6 Hash1ap takes the hash-o'eA B o" the ob0ect and uses it to Auickly hunt "or the key. This results in a dra#atic %er"or#ance i#%rove#ent@.

@ I" these s%eedu%s still don t #eet your %er"or#ance needs, you can "urther accelerate table looku% by writing your own 1ap and custo#i1ing it to your %articular ty%es to avoid delays due to casting to and "ro# .b8ects. To reach even higher levels o" %er"or#ance, s%eed enthusiasts can use 7onald >nuth s The "rt o$ Com uter ProgrammingD Colume 3! Sorting and SearchingD Second Edition to re%lace over"low bucket lists with arrays that have two additional bene"its= they can be o%ti#i1ed "or disk storage characteristics and they can save #ost o" the ti#e o" creating and garbage collecting individual records.

4;4

1ap
*inter"ace ,

Maintains key'value associations *%airs,, so you can look u% a value using a key. I#%le#entation based on a hash table. *4se this instead o" Hashtable., Provides constant'ti#e %er"or#ance "or inserting and locating %airs. Per"or#ance can be ad0usted via constructors that allow you to set the ca acit) and load $actor o" the hash table. I#%le#entation based on a red'black tree. :hen you view the keys or the %airs, they will be in sorted order *deter#ined by -omparable or -omparator, discussed later,. The %oint o" a Tree1ap is that you get the results in sorted order. Tree1ap is the only 1ap with the s*b1apA B #ethod, which allows you to return a %ortion o" the tree.

Hash1a pB

Tree1a p

So#eti#es you ll also need to know the details o" how hashing works, so we ll look at that a little later. The "ollowing e&a#%le uses the -ollectionsI!fillA B #ethod and the test data sets that were %reviously de"ined= RFSURFSTIJLT+(6PTE52TIMMHU

//3 c'C3Ja"(.Hava // Things you can !o :ith Ja"s. i#"ort Hava.util.B< i#"ort co#.bruceeckel.util.B< "ublic class Ja"( @ static Collections .%tringPairaenerator geo ? Collections .geogra"hy< static Collections .5an!%tringPairaenerator rs" ? Collections .rs"< // Pro!ucing a %et of the keys3 "ublic static voi! "rint`eys-Ja" #. @ %yste#.out."rint-8%iUe ? 8 K #.siUe-. K8, 8.< %yste#.out."rint-8`eys3 8.< %yste#.out."rintln-#.key%et-..< A // Pro!ucing a Collection of the values3 "ublic static voi! "rintWalues-Ja" #. @

Cha ter ;! .olding Lour Ob>ects

4;5

%yste#.out."rint-8Walues3 8.< %yste#.out."rintln-#.values-..< A "ublic static voi! test-Ja" #. @ Collections .fill-#, geo, ,.< // Ja" has 2%et2 behavior for keys3 Collections .fill-#, geo.reset-., ,.< "rint`eys-#.< "rintWalues-#.< %yste#.out."rintln-#.< %tring key ? CountryCa"itals."airsNION'O< %tring value ? CountryCa"itals."airsNION(O< %yste#.out."rintln-8#.contains`ey-_88 K key K 8_8.3 8 K #.contains`ey-key..< %yste#.out."rintln-8#.get-_88 K key K 8_8.3 8 K #.get-key..< %yste#.out."rintln-8#.containsWalue-_88 K value K 8_8.3 8 K #.containsWalue-value..< Ja" # ? ne: TreeJa"-.< Collections .fill-# , rs", ,.< #."ut0ll-# .< "rint`eys-#.< key ? #.key%et-..iterator-..ne6t-..to%tring-.< %yste#.out."rintln-8Lirst key in #a"3 8Kkey.< #.re#ove-key.< "rint`eys-#.< #.clear-.< %yste#.out."rintln-8#.isE#"ty-.3 8 K #.isE#"ty-..< Collections .fill-#, geo.reset-., ,.< // G"erations on the %et change the Ja"3 #.key%et-..re#ove0ll-#.key%et-..< %yste#.out."rintln-8#.isE#"ty-.3 8 K #.isE#"ty-..< A "ublic static voi! #ain-%tringNO args. @ %yste#.out."rintln-8Testing MashJa"8.< test-ne: MashJa"-..< %yste#.out."rintln-8Testing TreeJa"8.< test-ne: TreeJa"-..<

4;7

A A ///3>
The print%eysA B and printVal*esA B #ethods are not only use"ul utilities, they also de#onstrate how to %roduce -ollection views o" a 1ap. The key)etA B #ethod %roduces a )et backed by the keys in the 1ap. Si#ilar treat#ent is given to val*esA B, which %roduces a -ollection containing all the values in the 1ap! *Cote that keys #ust be uniAue, while values #ay contain du%licates., Since these -ollections are backed by the 1ap, any changes in a -ollection will be re"lected in the associated 1ap. RFSURFSTIJLT+(6PTE52TIMM3U The rest o" the %rogra# %rovides si#%le e&a#%les o" each 1ap o%eration, and tests each ty%e o" 1ap. RFSURFSTIJLT+(6PTE52TIMMGU 6s an e&a#%le o" the use o" a Hash1ap, consider a %rogra# to check the rando#ness o" Java s 1ath!ran'omA B #ethod. Ideally, it would %roduce a %er"ect distribution o" rando# nu#bers, but to test this you need to generate a bunch o" rando# nu#bers and count the ones that "all in the various ranges. 6 Hash1ap is %er"ect "or this, since it associates ob0ects with ob0ects *in this case, the value ob0ect contains the nu#ber %roduced by 1ath!ran'omA B along with the nu#ber o" ti#es that nu#ber a%%ears,=

//3 c'C3%tatistics.Hava // %i#"le !e#onstration of MashJa". i#"ort Hava.util.B< class Counter @ int i ? (< "ublic %tring to%tring-. @ return $nteger.to%tring-i.< A A "ublic class %tatistics @ "ublic static voi! #ain-%tringNO args. @ MashJa" h# ? ne: MashJa"-.< for-int i ? '< i P (''''< iKK. @ // Pro!uce a nu#ber bet:een ' an! '3 $nteger r ?

Cha ter ;! .olding Lour Ob>ects

4;8

ne: $nteger--int.-Jath.ran!o#-. B if-h#.contains`ey-r.. --Counter.h#.get-r...iKK< else h#."ut-r, ne: Counter-..< A %yste#.out."rintln-h#.< A A ///3>

'..<

In mainA B, each ti#e a rando# nu#ber is generated it is wra%%ed inside an Integer ob0ect so that re"erence can be used with the Hash1ap. */ou can t use a %ri#itive with a container, only an ob0ect re"erence., The contains%eyA B #ethod checks to see i" this key is already in the container. *That is, has the nu#ber been "ound alreadyO, I" so, the getA B #ethod %roduces the associated value "or the key, which in this case is a -o*nter ob0ect. The value i inside the counter is incre#ented to indicate that one #ore o" this %articular rando# nu#ber has been "ound. RFSURF STIJLT+(6PTE52TIMMIU I" the key has not been "ound yet, the #ethod p*tA B will %lace a new key' value %air into the Hash1ap. Since -o*nter auto#atically initiali1es its variable i to one when it s created, it indicates the "irst occurrence o" this %articular rando# nu#ber. RFSURFSTIJLT+(6PTE52TIMM2U To dis%lay the Hash1ap, it is si#%ly %rinted. The Hash1ap to)tring A B #ethod #oves through all the key'value %airs and calls the to)tring A B "or each one. The Integer!to)tringA B is %rede"ined, and you can see the to)tringA B "or -o*nter. The out%ut "ro# one run *with so#e line breaks added, is=

@(C?, +, (1?,)), (*?I+', (+?,(), (,?, (, (I?IC,, ()?,( , ( ?I1), ((?I11, ('?I1*, C?,(I, 1?, ), *?IC*, +?I1*, ,?I1', I?I1C, )?,'C, ?,'), (?I*,, '?,',A
/ou #ight wonder at the necessity o" the class -o*nter, which see#s like it doesn t even have the "unctionality o" the wra%%er class Integer. :hy not use int or IntegerO :ell, you can t use an int because all o" the containers can hold only .b8ect re"erences. 6"ter seeing containers the wra%%er classes #ight begin to #ake a little #ore sense to you, since you

4;:

can t %ut any o" the %ri#itive ty%es in containers. (owever, the only thing you can do with the Java wra%%ers is to initiali1e the# to a %articular value and read that value. That is, there s no way to change a value once a wra%%er ob0ect has been created. This #akes the Integer wra%%er i##ediately useless to solve our %roble#, so we re "orced to create a new class that does satis"y the need. RFSURFSTIJLT+(6PTE52TIMK@U

Sorted3a
I" you have a )orte'1ap *o" which Tree1ap is the only one available,, the keys are guaranteed to be in sorted order which allows additional "unctionality to be %rovided with these #ethods in the )orte'1ap inter"ace= RFSURFSTIJLT+(6PTE52TIMKMU

-omparator comparatorAB< Produces the co#%arator used "or this 1ap, or n*ll "or natural ordering. .b8ect first%eyAB< Produces the lowest key. .b8ect last%eyAB< Produces the highest key. )orte'1ap s*b1apAfrom%ey, to%eyB< Produces a view o" this 1ap with keys "ro# from%ey, inclusive, to to%ey, e&clusive. )orte'1ap hea'1apAto%eyB< Produces a view o" this 1ap with
keys less than to%ey.

)orte'1ap tail1apAfrom%eyB< Produces a view o" this 1ap with keys greater than or eAual to from%ey.

>ashing and hash codes


In the %revious e&a#%le, a standard library class * Integer, was used as a key "or the Hash1ap. It worked "ine as a key, because it has all the necessary wiring to #ake it work correctly as a key. But a co##on %it"all occurs with Hash1aps when you create your own classes to be used as keys. Eor e&a#%le, consider a weather %redicting syste# that #atches "ro*n'hog ob0ects to #re'iction ob0ects. It see#s "airly straight"orward9you create the two classes, and use "ro*n'hog as the key and #re'iction as the value= RFSURFSTIJLT+(6PTE52TIMKKU

//3 c'C3%"ringDetector.Hava // Looks "lausible, but !oesn2t :ork.

Cha ter ;! .olding Lour Ob>ects

4;;

i#"ort Hava.util.B< class aroun!hog @ int gh&u#ber< aroun!hog-int n. @ gh&u#ber ? n< A A class Pre!iction @ boolean sha!o: ? Jath.ran!o#-. Q '.,< "ublic %tring to%tring-. @ if-sha!o:. return 8%i6 #ore :eeks of \inter48< else return 8Early %"ring48< A A "ublic class %"ringDetector @ "ublic static voi! #ain-%tringNO args. @ MashJa" h# ? ne: MashJa"-.< for-int i ? '< i P ('< iKK. h#."ut-ne: aroun!hog-i., ne: Pre!iction-..< %yste#.out."rintln-8h# ? 8 K h# K 8_n8.< %yste#.out."rintln8Looking u" "re!iction for aroun!hog S)38.< aroun!hog gh ? ne: aroun!hog-).< if-h#.contains`ey-gh.. %yste#.out."rintln--Pre!iction.h#.get-gh..< else %yste#.out."rintln-8`ey not foun!3 8 K gh.< A A ///3>
Each "ro*n'hog is given an identity nu#ber, so you can look u% a #re'iction in the Hash1ap by saying, !8ive #e the #re'iction associated with "ro*n'hog nu#ber L.$ The #re'iction class contains a boolean that is initiali1ed using 1ath!ran'omA B, and a to)tringA B that inter%rets the result "or you. In mainA B, a Hash1ap is "illed with "ro*n'hogs and their associated #re'ictions. The Hash1ap is %rinted so you can see that it has been "illed. Then a "ro*n'hog with an identity nu#ber o" L is used as a key to look u% the %rediction "or

5==

"ro*n'hog SL *which you can see #ust be in the 1ap,. RFSURF


STIJLT+(6PTE52TIMKLU It see#s si#%le enough, but it doesn t work. The %roble# is that

"ro*n'hog is inherited "ro# the co##on root class .b8ect *which is


what ha%%ens i" you don t s%eci"y a base class, thus all classes are ulti#ately inherited "ro# .b8ect,. It is .b8ect s hash-o'eA B #ethod that is used to generate the hash code "or each ob0ect, and by de"ault it 0ust uses the address o" its ob0ect. Thus, the "irst instance o" "ro*n'hog AJB does not %roduce a hash code eAual to the hash code "or the second instance o" "ro*n'hogAJB that we tried to use as a looku%. RFSURF STIJLT+(6PTE52TIMK?U /ou #ight think that all you need to do is write an a%%ro%riate override "or hash-o'eA B. But it still won t work until you ve done one #ore thing= override the eC*alsA B that is also %art o" .b8ect. This #ethod is used by the Hash1ap when trying to deter#ine i" your key is eAual to any o" the keys in the table. 6gain, the de"ault .b8ect!eC*alsA B si#%ly co#%ares ob0ect addresses, so one "ro*n'hogAJB is not eAual to another "ro*n'hogAJB. RFSURFSTIJLT+(6PTE52TIMKHU Thus, to use your own classes as keys in a Hash1ap, you #ust override both hash-o'eA B and eC*alsA B, as shown in the "ollowing solution to the %roble# above=

//3 c'C3%"ringDetector .Hava // 0 class that2s use! as a key in a MashJa" // #ust overri!e hashCo!e-. an! e=uals-.. i#"ort Hava.util.B< class aroun!hog @ int gh&u#ber< aroun!hog -int n. @ gh&u#ber ? n< A "ublic int hashCo!e-. @ return gh&u#ber< A "ublic boolean e=uals-GbHect o. @ return -o instanceof aroun!hog . DD -gh&u#ber ?? --aroun!hog .o..gh&u#ber.< A A "ublic class %"ringDetector @

Cha ter ;! .olding Lour Ob>ects

5=1

"ublic static voi! #ain-%tringNO args. @ MashJa" h# ? ne: MashJa"-.< for-int i ? '< i P ('< iKK. h#."ut-ne: aroun!hog -i.,ne: Pre!iction-..< %yste#.out."rintln-8h# ? 8 K h# K 8_n8.< %yste#.out."rintln8Looking u" "re!iction for groun!hog S)38.< aroun!hog gh ? ne: aroun!hog -).< if-h#.contains`ey-gh.. %yste#.out."rintln--Pre!iction.h#.get-gh..< A A ///3>
Cote that this uses the #re'iction class "ro# the %revious e&a#%le, so )pring etector!8ava #ust be co#%iled "irst or you ll get a co#%ile' ti#e error when you try to co#%ile )pring etectorI!8ava. RFSURF STIJLT+(6PTE52TIMK3U

"ro*n'hogI!hash-o'eA B returns the groundhog nu#ber as an identi"ier. In this e&a#%le, the %rogra##er is res%onsible "or ensuring that no two groundhogs e&ist with the sa#e I7 nu#ber. The hash-o'e A B is not reAuired to return a uniAue identi"ier *so#ething you ll understand better later in this cha%ter,, but the eC*alsA B #ethod #ust be able to strictly deter#ine whether two ob0ects are eAuivalent. RFSURF STIJLT+(6PTE52TIMKGU
Even though it a%%ears that the eC*alsA B #ethod is only checking to see whether the argu#ent is an instance o" "ro*n'hogI *using the instanceof keyword, which is "ully e&%lained in +ha%ter MK,, the instanceof actually Auietly does a second sanity check, to see i" the ob0ect is n*ll, since instanceof %roduces false i" the le"t'hand argu#ent is n*ll. 6ssu#ing it s the correct ty%e and not n*ll, the co#%arison is based on the actual gh/*mbers. This ti#e, when you run the %rogra#, you ll see it %roduces the correct out%ut. RFSURF STIJLT+(6PTE52TIMKIU :hen creating your own class to use in a Hash)et, you #ust %ay attention to the sa#e issues as when it is used as a key in a Hash1ap. RF SURFSTIJLT+(6PTE52TIMK2U

5=2

Cnderstanding hash$ode1 2
The above e&a#%le is only a start toward solving the %roble# correctly. It shows that i" you do not override hash-o'eA B and eC*alsA B "or your key, the hashed data structure * Hash)et or Hash1ap, will not be able to deal with your key %ro%erly. (owever, to get a good solution "or the %roble# you need to understand what s going on inside the hashed data structure. RFSURFSTIJLT+(6PTE52TIML@U Eirst, consider the #otivation behind hashing= you want to look u% an ob0ect using another ob0ect. But you can acco#%lish this with a Tree)et or Tree1ap, too. It s also %ossible to i#%le#ent your own 1ap. To do so, the 1ap!entry)etA B #ethod #ust be su%%lied to %roduce a set o" 1ap!&ntry ob0ects. 1#air will be de"ined as the new ty%e o" 1ap! &ntry. In order "or it to be %laced in a Tree)et it #ust i#%le#ent eC*alsA B and be -omparable=

//3 c'C3JPair.Hava // 0 Ja" i#"le#ente! :ith 0rrayListsne: ty"e of Ja". Entry. i#"ort Hava.util.B< "ublic class JPair i#"le#ents Ja".Entry, Co#"arable @ GbHect key, value< JPair-GbHect k, GbHect v. @ key ? k< value ? v< A "ublic GbHect get`ey-. @ return key< A "ublic GbHect getWalue-. @ return value< A "ublic GbHect setWalue-GbHect v.@ GbHect result ? value< value ? v< return result< A "ublic boolean e=uals-GbHect o. @ return key.e=uals---JPair.o..key.< A "ublic int co#"areTo-GbHect rv. @ return --Co#"arable.key..co#"areTo-

Cha ter ;! .olding Lour Ob>ects

5=3

--JPair.rv..key.< A A ///3> Cotice that the co#%arisons are only interested in the keys, so du%licate values are %er"ectly acce%table.
The "ollowing e&a#%le i#%le#ents a 1ap using a %air o" Array+ists= RF SURFSTIJLT+(6PTE52TIMLMU

//3 c'C3%lo:Ja".Hava // 0 Ja" i#"le#ente! :ith 0rrayLists. i#"ort Hava.util.B< i#"ort co#.bruceeckel.util.B< "ublic class %lo:Ja" e6ten!s 0bstractJa" @ "rivate 0rrayList keys ? ne: 0rrayList-., values ? ne: 0rrayList-.< "ublic GbHect "ut-GbHect key, GbHect value. @ GbHect result ? get-key.< if-4keys.contains-key.. @ keys.a!!-key.< values.a!!-value.< A else values.set-keys.in!e6Gf-key., value.< return result< A "ublic GbHect get-GbHect key. @ if-4keys.contains-key.. return null< return values.get-keys.in!e6Gf-key..< A "ublic %et entry%et-. @ %et entries ? ne: Mash%et-.< $terator ki ? keys.iterator-., vi ? values.iterator-.< :hile-ki.has&e6t-.. entries.a!!-ne: JPair-ki.ne6t-., vi.ne6t-...< return entries< A

5=4

"ublic static voi! #ain-%tringNO args. @ %lo:Ja" # ? ne: %lo:Ja"-.< Collections .fill-#, Collections .geogra"hy, ,.< %yste#.out."rintln-#.< A A ///3>
The p*tA B #ethod si#%ly %laces the keys and values in corres%onding Array+ists. In mainA B, a )lo(1ap is loaded and then %rinted to show that it works. This shows that it s not that hard to %roduce a new ty%e o" 1ap. But as the na#e suggests, a )lo(1ap isn t very "ast, so you %robably wouldn t use it i" you had an alternative available. The %roble# is in the looku% o" the key= there is no order so a si#%le linear search is used, which is the slowest way to look so#ething u%. RFSURFSTIJLT+(6PTE52TIMLKU The whole %oint o" hashing is s%eed= hashing allows the looku% to ha%%en Auickly. Since the bottleneck is in the s%eed o" the key looku%, one o" the solutions to the %roble# could be by kee%ing the keys sorted and then using -ollections!binary)earchA B to %er"or# the looku% *an e&ercise at the end o" this cha%ter will walk you through this %rocess,. RFSURF STIJLT+(6PTE52TIMLLU (ashing goes "urther by saying that all you want to do is to store the key

some,here so that it can be Auickly "ound. 6s you ve seen in this cha%ter,


the "astest structure in which to store a grou% o" ele#ents is an array, so that will be used "or re%resenting the key in"or#ation *note care"ully that I said !key in"or#ation,$ and not the key itsel",. 6lso seen in this cha%ter was the "act that an array, once allocated, cannot be resi1ed, so we have a %roble#= we want to be able to store any nu#ber o" values in the 1ap, but i" the nu#ber o" keys is "i&ed by the array si1e, how can this beO RF SURFSTIJLT+(6PTE52TIML?U The answer is that the array will not hold the keys. Ero# the key ob0ect, a nu#ber will be derived that will inde& into the array. This nu#ber is the hash code, %roduced by the hash-o'eA B #ethod *in co#%uter science %arlance, this is the hash $unction, de"ined in .b8ect and %resu#ably overridden by your class. To solve the %roble# o" the "i&ed'si1e array,

Cha ter ;! .olding Lour Ob>ects

5=5

#ore than one key #ay %roduce the sa#e inde&. That is, there #ay be collisions. Because o" this, it doesn t #atter how big the array is because each key ob0ect will land so#ewhere in that array. RFSURF STIJLT+(6PTE52TIMLHU So the %rocess o" looking u% a value starts by co#%uting the hash code and using it to inde& into the array. I" you could guarantee that there were no collisions *which could be %ossible i" you have a "i&ed nu#ber o" values, then you d have a er$ect hashing $unction, but that s a s%ecial case. In all other cases, collisions are handled by e*ternal chaining! the array %oints not directly to a value, but instead to a list o" values. These values are searched in a linear "ashion using the eC*alsA B #ethod. )" course, this as%ect o" the search is #uch slower, but i" the hash "unction is good there will only be a "ew values in each slot, at the #ost. So instead o" searching through the entire list, you Auickly 0u#% to a slot where you have to co#%are a "ew entries to "ind the value. This is #uch "aster, which is why the Hash1ap is so Auick. RFSURFSTIJLT+(6PTE52TIML3U >nowing the basics o" hashing, it s %ossible to i#%le#ent a si#%le hashed 1ap=

//3 c'C3%i#"leMashJa".Hava // 0 !e#onstration hashe! Ja". i#"ort Hava.util.B< i#"ort co#.bruceeckel.util.B< "ublic class %i#"leMashJa" e6ten!s 0bstractJa" @ // Choose a "ri#e nu#ber for the hash table // siUe, to achieve a unifor# !istribution3 "rivate final static int %T ? CC*< "rivate Linke!ListNO bucket? ne: Linke!ListN%TO< "ublic GbHect "ut-GbHect key, GbHect value. @ GbHect result ? null< int in!e6 ? key.hashCo!e-. V %T< if-in!e6 P '. in!e6 ? -in!e6< if-bucketNin!e6O ?? null. bucketNin!e6O ? ne: Linke!List-.< Linke!List "airs ? bucketNin!e6O< JPair "air ? ne: JPair-key, value.< List$terator it ? "airs.list$terator-.< boolean foun! ? false<

5=7

:hile-it.has&e6t-.. @ GbHect iPair ? it.ne6t-.< if-iPair.e=uals-"air.. @ result ? --JPair.iPair..getWalue-.< it.set-"air.< // 5e"lace ol! :ith ne: foun! ? true< break< A A if-4foun!. bucketNin!e6O.a!!-"air.< return result< A "ublic GbHect get-GbHect key. @ int in!e6 ? key.hashCo!e-. V %T< if-in!e6 P '. in!e6 ? -in!e6< if-bucketNin!e6O ?? null. return null< Linke!List "airs ? bucketNin!e6O< JPair #atch ? ne: JPair-key, null.< List$terator it ? "airs.list$terator-.< :hile-it.has&e6t-.. @ GbHect iPair ? it.ne6t-.< if-iPair.e=uals-#atch.. return --JPair.iPair..getWalue-.< A return null< A "ublic %et entry%et-. @ %et entries ? ne: Mash%et-.< for-int i ? '< i P bucket.length< iKK. @ if-bucketNiO ?? null. continue< $terator it ? bucketNiO.iterator-.< :hile-it.has&e6t-.. entries.a!!-it.ne6t-..< A return entries< A "ublic static voi! #ain-%tringNO args. @ %i#"leMashJa" # ? ne: %i#"leMashJa"-.< Collections .fill-#, Collections .geogra"hy, ,.<

Cha ter ;! .olding Lour Ob>ects

5=8

%yste#.out."rintln-#.< A A ///3>
Because the !slots$ in a hash table are o"ten re"erred to as bucketsD the array that re%resents the actual table is called b*cket. To %ro#ote even distribution, the nu#ber o" buckets is ty%ically a %ri#e nu#ber. Cotice that it is an array o" +inke'+ist, which auto#atically %rovides "or collisions9each new ite# is si#%ly added to the end o" the list. RFSURF STIJLT+(6PTE52TIMLGU The return value o" p*tA B is n*ll or, i" the key was already in the list, the old value associated with that key. The return value is res*lt, which is initiali1ed to n*ll, but i" a key is discovered in the list then res*lt is assigned to that key. RFSURFSTIJLT+(6PTE52TIMLIU Eor both p*tA B and getA B, the "irst thing that ha%%ens is that the hash-o'eA B is called "or the key, and the result is "orced to a %ositive nu#ber. Then it is "orced to "it into the b*cket array using the #odulus o%erator and the si1e o" the array. I" that location is n*ll, it #eans there are no ele#ents that hash to that location, so a new +inke'+ist is created to hold the ob0ect that 0ust did. (owever, the nor#al %rocess is to look through the list to see i" there are du%licates, and i" there are, the old value is %ut into res*lt and the new value re%laces the old. The fo*n' "lag kee%s track o" whether an old key'value %air was "ound and, i" not, the new %air is a%%ended to the end o" the list. RFSURF STIJLT+(6PTE52TIML2U In getA B, you ll see very si#ilar code as that contained in p*tA B, but si#%ler. The inde& is calculated into the b*cket array, and i" a +inke'+ist e&ists it is searched "or a #atch. RFSURF STIJLT+(6PTE52TIM?@U

entry)etA B #ust "ind and traverse all the lists, adding the# to the result )et. )nce this #ethod has been created, the 1ap can be tested by "illing
it with values and then %rinting the#. RFSURFSTIJLT+(6PTE52TIM?MU

Hash3a

.erformance factors

To understand the issues, so#e ter#inology is necessary=

Ca'acit!! The nu#ber o" buckets in the table.

5=:

Initial ca'acit!! The nu#ber o" buckets when the table is created. Hash1ap and Hash)et= have constructors that allow you to s%eci"y
the initial ca%acity.

*i%e! The nu#ber o" entries currently in the table. 5oad factor! si1eFca%acity. 6 load "actor o" @ is an e#%ty table, @.H
is a hal"'"ull table, etc. 6 lightly'loaded table will have "ew collisions and so is o%ti#al "or insertions and looku%s *but will slow down the %rocess o" traversing with an iterator,. Hash1ap and Hash)et have constructors that allow you to s%eci"y the load "actor, which #eans that when this load "actor is reached the container will auto#atically increase the ca%acity *the nu#ber o" buckets, by roughly doubling it, and will redistribute the e&isting ob0ects into the new set o" buckets *this is called rehashing,. The de"ault load "actor used by Hash1ap is @.GH *it doesn t rehash until the table is f "ull,. This see#s to be a good trade'o"" between ti#e and s%ace costs. 6 higher load "actor decreases the s%ace reAuired by the table but increases the looku% cost, which is i#%ortant because looku% is what you do #ost o" the ti#e *including both getA B and p*tA B,. RFSURF STIJLT+(6PTE52TIM?KU I" you know that you ll be storing #any entries in a Hash1ap, creating it with an a%%ro%riately large initial ca%acity will %revent the overhead o" auto#atic rehashing. RFSURFSTIJLT+(6PTE52TIM?LU

Overriding hash$ode1 2
Cow that you understand what s involved in the "unction o" the Hash1ap, the issues involved in writing a hash-o'eA B will #ake #ore sense. RFSURFSTIJLT+(6PTE52TIM??U Eirst o" all, you don t have control o" the creation o" the actual value that s used to inde& into the array o" buckets. That is de%endent on the ca%acity o" the %articular Hash1ap ob0ect, and that ca%acity changes de%ending on how "ull the container is, and what the load "actor is. The value %roduced by your hash-o'eA B will be "urther %rocessed in order to create the bucket inde& *in )impleHash1ap the calculation is 0ust a #odulo by the si1e o" the bucket array,. RFSURF STIJLT+(6PTE52TIM?HU

Cha ter ;! .olding Lour Ob>ects

5=;

The #ost i#%ortant "actor in creating a hash-o'eA B is that, regardless o" when hash-o'eA B is called, it %roduces the sa#e value "or a %articular ob0ect every ti#e it is called. I" you end u% with an ob0ect that %roduces one hash-o'eA B value when it is p*tA B into a Hash1ap, and another during a getA B, you won t be able to retrieve the ob0ects. So i" your hash-o'eA B de%ends on #utable data in the ob0ect the user #ust be #ade aware that changing the data will e""ectively %roduce a di""erent key by generating a di""erent hash-o'eA B. RFSURF STIJLT+(6PTE52TIM?3U In addition, you will %robably not want to generate a hash-o'eA B that is based on uniAue ob0ect in"or#ation9in %articular, the value o" this #akes a bad hash-o'eA B because then you can t generate a new identical key to the one used to p*tA B the original key'value %air. This was the %roble# that occurred in )pring etector!8ava because the de"ault i#%le#entation o" hash-o'eA B does use the ob0ect address. So you ll want to use in"or#ation in the ob0ect that identi"ies the ob0ect in a #eaning"ul way. RFSURFSTIJLT+(6PTE52TIM?GU )ne e&a#%le is "ound in the )tring class. )trings have the s%ecial characteristic that i" a %rogra# has several )tring ob0ects that contain identical character seAuences, then those )tring ob0ects all #a% to the sa#e #e#ory *the #echanis# "or this is described in 6%%endi& 6,. So it #akes sense that the hash-o'eA B %roduced by two se%arate instances o" ne( )tringAahellobB should be identical. /ou can see it by running this %rogra#=

//3 c'C3%tringMashCo!e.Hava "ublic class %tringMashCo!e @ "ublic static voi! #ain-%tringNO args. @ %yste#.out."rintln-8Mello8.hashCo!e-..< %yste#.out."rintln-8Mello8.hashCo!e-..< A A ///3>
Eor this to work, the hash-o'eA B "or )tring #ust be based on the contents o" the )tring. RFSURFSTIJLT+(6PTE52TIM?IU So "or a hash-o'eA B to be e""ective, it #ust be "ast and it #ust be #eaning"ul= that is, it #ust generate a value based on the contents o" the

51=

ob0ect. 5e#e#ber that this value doesn t have to be uniAue9you should lean toward s%eed rather than uniAueness9but between hash-o'eA B and eC*alsA B the identity o" the ob0ect #ust be co#%letely resolved. RF SURFSTIJLT+(6PTE52TIM?2U Because the hash-o'eA B is "urther %rocessed be"ore the bucket inde& is %roduced, the range o" values is not i#%ortant; it 0ust needs to generate an int. RFSURFSTIJLT+(6PTE52TIMH@U There s one other "actor= a good hash-o'eA B should result in an even distribution o" values. I" the values tend to cluster, then the Hash1ap or Hash)et will be #ore heavily loaded in so#e areas and will not be as "ast as it could be with an evenly distributed hashing "unction. RFSURF STIJLT+(6PTE52TIMHMU (ere s an e&a#%le that "ollows these guidelines=

//3 c'C3Counte!%tring.Hava // Creating a goo! hashCo!e-.. i#"ort Hava.util.B< "ublic class Counte!%tring @ "rivate %tring s< "rivate int i! ? '< "rivate static 0rrayList create! ? ne: 0rrayList-.< "ublic Counte!%tring-%tring str. @ s ? str< create!.a!!-s.< $terator it ? create!.iterator-.< // $! is the total nu#ber of instances // of this string in use by Counte!%tring3 :hile-it.has&e6t-.. if-it.ne6t-..e=uals-s.. i!KK< A "ublic %tring to%tring-. @ return 8%tring3 8 K s K 8 i!3 8 K i! K 8 hashCo!e-.3 8 K hashCo!e-. K 8_n8< A "ublic int hashCo!e-. @

Cha ter ;! .olding Lour Ob>ects

511

return s.hashCo!e-. B i!< A "ublic boolean e=uals-GbHect o. @ return -o instanceof Counte!%tring. DD s.e=uals---Counte!%tring.o..s. DD i! ?? --Counte!%tring.o..i!< A "ublic static voi! #ain-%tringNO args. @ MashJa" # ? ne: MashJa"-.< Counte!%tringNO cs ? ne: Counte!%tringN('O< for-int i ? '< i P cs.length< iKK. @ csNiO ? ne: Counte!%tring-8hi8.< #."ut-csNiO, ne: $nteger-i..< A %yste#.out."rintln-#.< for-int i ? '< i P cs.length< iKK. @ %yste#.out."rint-8Looking u" 8 K csNiO.< %yste#.out."rintln-#.get-csNiO..< A A A ///3> -o*nte')tring includes a )tring and an i' that re%resents the nu#ber o" -o*nte')tring ob0ects that contain an identical )tring. The counting is acco#%lished in the constructor by iterating through the static Array+ist where all the )trings are stored. RFSURF STIJLT+(6PTE52TIMHKU
Both hash-o'eA B and eC*alsA B %roduce results based on both "ields; i" they were 0ust based on the )tring alone or the i' alone there would be du%licate #atches "or distinct values. RFSURFSTIJLT+(6PTE52TIMHLU Cote how si#%le the hash-o'eA B is= )tring s hash-o'eA B is #ulti%lied by the i'. S#aller is generally better *and "aster, "or hash-o'eA B. RFSURFSTIJLT+(6PTE52TIMH?U In mainA B, a bunch o" -o*nte')tring ob0ects are created, using the sa#e )tring to show that the du%licates create uniAue values because o" the count i'. The Hash1ap is dis%layed so that you can see how it is stored internally *no discernible orders, and then each key is looked u%

512

individually to de#onstrate that the looku% #echanis# is working %ro%erly. RFSURFSTIJLT+(6PTE52TIMHHU

>olding references
The 8ava!lang!ref library contains a set o" classes that allow greater "le&ibility in garbage collection, which are es%ecially use"ul when you have large ob0ects that #ay cause #e#ory e&haustion. There are three classes inherited "ro# the abstract class $eference= )oft$eference, 0eak$eference, and #hantom$eference. Each o" these %rovides a di""erent level o" indirection "or the garbage collector, i" the ob0ect in Auestion is onl) reachable through one o" these $eference ob0ects. RF SURFSTIJLT+(6PTE52TIMH3U I" an ob0ect is reachable it #eans that so#ewhere in your %rogra# the ob0ect can be "ound. This could #ean that you have an ordinary re"erence on the stack that goes right to the ob0ect, but you #ight also have a re"erence to an ob0ect that has a re"erence to the ob0ect in Auestion; there could be #any inter#ediate links. I" an ob0ect is reachable, the garbage collector cannot release it because it s still in use by your %rogra#. I" an ob0ect isn t reachable, there s no way "or your %rogra# to use it so it s sa"e to garbage'collect that ob0ect. RFSURFSTIJLT+(6PTE52TIMHGU /ou use $eference ob0ects when you want to continue to hold onto a re"erence to that ob0ect9you want to be able to reach that ob0ect9but you also want to allow the garbage collector to release that ob0ect. Thus, you have a way to go on using the ob0ect, but i" #e#ory e&haustion is i##inent you allow that ob0ect to be released. RFSURF STIJLT+(6PTE52TIMHIU /ou acco#%lish this by using a $eference ob0ect as an inter#ediary between you and the ordinary re"erence, and there #ust be no ordinary re"erences to the ob0ect *ones that are not wra%%ed inside $eference ob0ects,. I" the garbage collector discovers that an ob0ect is reachable through an ordinary re"erence, it will not release that ob0ect. RFSURF STIJLT+(6PTE52TIMH2U In the order )oft$eference, 0eak$eference, and #hantom$eference, each one is !weaker$ than the last, and

Cha ter ;! .olding Lour Ob>ects

513

corres%onds to a di""erent level o" reachability. So"t re"erences are "or i#%le#enting #e#ory'sensitive caches. :eak re"erences are "or i#%le#enting !canonicali1ing #a%%ings$9where instances o" ob0ects can be si#ultaneously used in #ulti%le %laces in a %rogra#, to save storage9 that do not %revent their keys *or values, "ro# being reclai#ed. Phanto# re"erences are "or scheduling %re'#orte# cleanu% actions in a #ore "le&ible way than is %ossible with the Java "inali1ation #echanis#. RF SURFSTIJLT+(6PTE52TIM3@U :ith )oft$eferences and 0eak$eferences, you have a choice about whether to %lace the# on a $eference3*e*e *the device used "or %re#orte# cleanu% actions,, but a #hantom$eference can only be built on a $eference3*e*e. (ere s a si#%le de#onstration=

//3 c'C35eferences.Hava // De#onstrates 5eference obHects i#"ort Hava.lang.ref.B< class WeryBig @ static final int %T ? (''''< !oubleNO ! ? ne: !oubleN%TO< %tring i!ent< "ublic WeryBig-%tring i!. @ i!ent ? i!< A "ublic %tring to%tring-. @ return i!ent< A "ublic voi! finaliUe-. @ %yste#.out."rintln-8LinaliUing 8 K i!ent.< A A "ublic class 5eferences @ static 5eference/ueue r=? ne: 5eference/ueue-.< "ublic static voi! check/ueue-. @ GbHect in= ? r=."oll-.< if-in= 4? null. %yste#.out."rintln-8$n =ueue3 8 K -WeryBig.--5eference.in=..get-..< A "ublic static voi! #ain-%tringNO args. @ int siUe ? ('< // Gr, choose siUe via the co##an! line3 if-args.length Q '.

514

siUe ? $nteger."arse$nt-argsN'O.< %oft5eferenceNO sa ? ne: %oft5eferenceNsiUeO< for-int i ? '< i P sa.length< iKK. @ saNiO ? ne: %oft5eferencene: WeryBig-8%oft 8 K i., r=.< %yste#.out."rintln-8Just create!3 8 K -WeryBig.saNiO.get-..< check/ueue-.< A \eak5eferenceNO :a ? ne: \eak5eferenceNsiUeO< for-int i ? '< i P :a.length< iKK. @ :aNiO ? ne: \eak5eferencene: WeryBig-8\eak 8 K i., r=.< %yste#.out."rintln-8Just create!3 8 K -WeryBig.:aNiO.get-..< check/ueue-.< A %oft5eference s ? ne: %oft5eferencene: WeryBig-8%oft8..< \eak5eference : ? ne: \eak5eferencene: WeryBig-8\eak8..< %yste#.gc-.< Phanto#5eferenceNO "a ? ne: Phanto#5eferenceNsiUeO< for-int i ? '< i P "a.length< iKK. @ "aNiO ? ne: Phanto#5eferencene: WeryBig-8Phanto# 8 K i., r=.< %yste#.out."rintln-8Just create!3 8 K -WeryBig."aNiO.get-..< check/ueue-.< A A A ///3>
:hen you run this %rogra# *you ll want to %i%e the out%ut through a !#ore$ utility so that you can view the out%ut in %ages,, you ll see that the ob0ects are garbage'collected, even though you still have access to the# through the $eference ob0ect *to get the actual ob0ect re"erence, you use getA B,. /ou ll also see that the $eference3*e*e always %roduces a

Cha ter ;! .olding Lour Ob>ects

515

$eference containing a n*ll ob0ect. To #ake use o" this, you can inherit "ro# the %articular $eference class you re interested in and add #ore use"ul #ethods to the new ty%e o" $eference. RFSURF
STIJLT+(6PTE52TIM3MU

#he 4eakHash3a
The containers library has a s%ecial 1ap to hold weak re"erences= the 0eakHash1ap. This class is designed to #ake the creation o" canonicali1ed #a%%ings easier. In such a #a%%ing, you are saving storage by #aking only one instance o" a %articular value. :hen the %rogra# needs that value, it looks u% the e&isting ob0ect in the #a%%ing and uses that *rather than creating one "ro# scratch,. The #a%%ing #ay #ake the values as %art o" its initiali1ation, but it s #ore likely that the values are #ade on de#and. RFSURFSTIJLT+(6PTE52TIM3KU Since this is a storage'saving techniAue, it s very convenient that the 0eakHash1ap allows the garbage collector to auto#atically clean u% the keys and values. /ou don t have to do anything s%ecial to the keys and values you want to %lace in the 0eakHash1ap; these are auto#atically wra%%ed in 0eak$eferences by the #a%. The trigger to allow cleanu% is i" the key is no longer in use, as de#onstrated here=

//3 c'C3CanonicalJa""ing.Hava // De#onstrates \eakMashJa". i#"ort Hava.util.B< i#"ort Hava.lang.ref.B< class `ey @ %tring i!ent< "ublic `ey-%tring i!. @ i!ent ? i!< A "ublic %tring to%tring-. @ return i!ent< A "ublic int hashCo!e-. @ return i!ent.hashCo!e-.< A "ublic boolean e=uals-GbHect r. @ return -r instanceof `ey. DD i!ent.e=uals---`ey.r..i!ent.< A "ublic voi! finaliUe-. @

517

%yste#.out."rintln-8LinaliUing `ey 8K i!ent.< A A class Walue @ %tring i!ent< "ublic Walue-%tring i!. @ i!ent ? i!< A "ublic %tring to%tring-. @ return i!ent< A "ublic voi! finaliUe-. @ %yste#.out."rintln-8LinaliUing Walue 8Ki!ent.< A A "ublic class CanonicalJa""ing @ "ublic static voi! #ain-%tringNO args. @ int siUe ? ('''< // Gr, choose siUe via the co##an! line3 if-args.length Q '. siUe ? $nteger."arse$nt-argsN'O.< `eyNO keys ? ne: `eyNsiUeO< \eakMashJa" :h# ? ne: \eakMashJa"-.< for-int i ? '< i P siUe< iKK. @ `ey k ? ne: `ey-$nteger.to%tring-i..< Walue v ? ne: Walue-$nteger.to%tring-i..< if-i V ) ?? '. keysNiO ? k< // %ave as 8real8 references :h#."ut-k, v.< A %yste#.gc-.< A A ///3>
The %ey class #ust have a hash-o'eA B and an eC*alsA B since it is being used as a key in a hashed data structure, as described %reviously in this cha%ter. RFSURFSTIJLT+(6PTE52TIM3LU :hen you run the %rogra# you ll see that the garbage collector will ski% every third key, because an ordinary re"erence to that key has also been %laced in the keys array and thus those ob0ects cannot be garbage' collected. RFSURFSTIJLT+(6PTE52TIM3?U

Cha ter ;! .olding Lour Ob>ects

518

Iterators revisited
:e can now de#onstrate the true %ower o" the Iterator= the ability to se%arate the o%eration o" traversing a seAuence "ro# the underlying structure o" that seAuence. In the "ollowing e&a#%le, the class #rint ata uses an Iterator to #ove through a seAuence and call the to)tringA B #ethod "or every ob0ect. Two di""erent ty%es o" containers are created9an Array+ist and a Hash1ap9and they are each "illed with, res%ectively, 1o*se and Hamster ob0ects. *These classes are de"ined earlier in this cha%ter., Because an Iterator hides the structure o" the underlying container, #rint ata doesn t know or care what kind o" container the Iterator co#es "ro#=

//3 c'C3$terators .Hava // 5evisiting $terators. i#"ort Hava.util.B< class PrintData @ static voi! "rint-$terator e. @ :hile-e.has&e6t-.. %yste#.out."rintln-e.ne6t-..< A A "ublic class $terators @ "ublic static voi! #ain-%tringNO args. @ 0rrayList v ? ne: 0rrayList-.< for-int i ? '< i P ,< iKK. v.a!!-ne: Jouse-i..< MashJa" # ? ne: MashJa"-.< for-int i ? '< i P ,< iKK. #."ut-ne: $nteger-i., ne: Ma#ster-i..< %yste#.out."rintln-80rrayList8.< PrintData."rint-v.iterator-..< %yste#.out."rintln-8MashJa"8.< PrintData."rint-#.entry%et-..iterator-..< A A ///3>

51:

Eor the Hash1ap, the entry)etA B #ethod %roduces a )et o" 1ap! entry ob0ects, which contain both the key and the value "or each entry, so you see both o" the# %rinted. RFSURFSTIJLT+(6PTE52TIM3HU Cote that #rint ata!printA B takes advantage o" the "act that the ob0ects in these containers are o" class .b8ect so the call to)tringA B by )ystem!o*t!printlnA B is auto#atic. It s #ore likely that in your %roble#, you #ust #ake the assu#%tion that your Iterator is walking through a container o" so#e s%eci"ic ty%e. Eor e&a#%le, you #ight assu#e that everything in the container is a )hape with a 'ra(A B #ethod. Then you #ust downcast "ro# the .b8ect that Iterator!ne4t A B returns to %roduce a )hape. RFSURFSTIJLT+(6PTE52TIM33U

Choosing an im.lementation
By now you should understand that there are really only three container co#%onents= 1ap, +ist, and )et, and only two or three i#%le#entations o" each inter"ace. I" you need to use the "unctionality o""ered by a %articular interface, how do you decide which %articular i#%le#entation to useO RFSURFSTIJLT+(6PTE52TIM3GU To understand the answer, you #ust be aware that each di""erent i#%le#entation has its own "eatures, strengths, and weaknesses. Eor e&a#%le, you can see in the diagra# that the !"eature$ o" Hashtable, Vector, and )tack is that they are legacy classes, so that old code doesn t break. )n the other hand, it s best i" you don t use those "or new *Java K, code. RFSURFSTIJLT+(6PTE52TIM3IU The distinction between the other containers o"ten co#es down to what they are !backed by$; that is, the data structures that %hysically i#%le#ent your desired interface. This #eans that, "or e&a#%le, Array+ist and +inke'+ist i#%le#ent the +ist inter"ace so your %rogra# will %roduce the sa#e results regardless o" the one you use. (owever, Array+ist is backed by an array, while the +inke'+ist is i#%le#ented in the usual way "or a doubly linked list, as individual ob0ects each containing data along with re"erences to the %revious and

Cha ter ;! .olding Lour Ob>ects

51;

ne&t ele#ents in the list. Because o" this, i" you want to do #any insertions and re#ovals in the #iddle o" a list, a +inke'+ist is the a%%ro%riate choice. * +inke'+ist also has additional "unctionality that is established in Abstract)eC*ential+ist., I" not, an Array+ist is ty%ically "aster. RFSURFSTIJLT+(6PTE52TIM32U 6s another e&a#%le, a )et can be i#%le#ented as either a Tree)et or a Hash)et. 6 Tree)et is backed by a Tree1ap and is designed to %roduce a constantly sorted set. (owever, i" you re going to have larger Auantities in your )et, the %er"or#ance o" Tree)et insertions will get slow. :hen you re writing a %rogra# that needs a )et, you should choose Hash)et by de"ault, and change to Tree)et when itVs #ore i#%ortant to have a constantly sorted set. RFSURFSTIJLT+(6PTE52TIMG@U

Choosing between #ists


The #ost convincing way to see the di""erences between the i#%le#entations o" +ist is with a %er"or#ance test. The "ollowing code establishes an inner base class to use as a test "ra#ework, then creates an array o" anony#ous inner classes, one "or each di""erent test. Each o" these inner classes is called by the testA B #ethod. This a%%roach allows you to easily add and re#ove new kinds o" tests.

//3 c'C3ListPerfor#ance.Hava // De#onstrates "erfor#ance !ifferences in Lists. i#"ort Hava.util.B< i#"ort co#.bruceeckel.util.B< "ublic class ListPerfor#ance @ "rivate abstract static class Tester @ %tring na#e< int siUe< // Test =uantity Tester-%tring na#e, int siUe. @ this.na#e ? na#e< this.siUe ? siUe< A abstract voi! test-List a, int re"s.< A "rivate static TesterNO tests ? @ ne: Tester-8get8, )''. @

52=

voi! test-List a, int re"s. @ for-int i ? '< i P re"s< iKK. @ for-int H ? '< H P a.siUe-.< HKK. a.get-H.< A A A, ne: Tester-8iteration8, )''. @ voi! test-List a, int re"s. @ for-int i ? '< i P re"s< iKK. @ $terator it ? a.iterator-.< :hile-it.has&e6t-.. it.ne6t-.< A A A, ne: Tester-8insert8, ,'''. @ voi! test-List a, int re"s. @ int half ? a.siUe-./ < %tring s ? 8test8< List$terator it ? a.list$terator-half.< for-int i ? '< i P siUe B ('< iKK. it.a!!-s.< A A, ne: Tester-8re#ove8, ,'''. @ voi! test-List a, int re"s. @ List$terator it ? a.list$terator-).< :hile-it.has&e6t-.. @ it.ne6t-.< it.re#ove-.< A A A, A< "ublic static voi! test-List a, int re"s. @ // 0 trick to "rint out the class na#e3 %yste#.out."rintln-8Testing 8 K a.getClass-..get&a#e-..< for-int i ? '< i P tests.length< iKK. @ Collections .fill-a,

Cha ter ;! .olding Lour Ob>ects

521

Collections .countries.reset-., testsNiO.siUe.< %yste#.out."rint-testsNiO.na#e.< long t( ? %yste#.currentTi#eJillis-.< testsNiO.test-a, re"s.< long t ? %yste#.currentTi#eJillis-.< %yste#.out."rintln-83 8 K -t - t(..< A A "ublic static voi! test0rray-int re"s. @ %yste#.out."rintln-8Testing array as List8.< // Can only !o first t:o tests on an array3 for-int i ? '< i P < iKK. @ %tringNO sa ? ne: %tringNtestsNiO.siUeO< 0rrays .fill-sa, Collections .countries.reset-..< List a ? 0rrays.asList-sa.< %yste#.out."rint-testsNiO.na#e.< long t( ? %yste#.currentTi#eJillis-.< testsNiO.test-a, re"s.< long t ? %yste#.currentTi#eJillis-.< %yste#.out."rintln-83 8 K -t - t(..< A A "ublic static voi! #ain-%tringNO args. @ int re"s ? ,''''< // Gr, choose the nu#ber of re"etitions // via the co##an! line3 if-args.length Q '. re"s ? $nteger."arse$nt-argsN'O.< %yste#.out."rintln-re"s K 8 re"etitions8.< test0rray-re"s.< test-ne: 0rrayList-., re"s.< test-ne: Linke!List-., re"s.< test-ne: Wector-., re"s.< A A ///3>
The inner class Tester is abstract, to %rovide a base class "or the s%eci"ic tests. It contains a )tring to be %rinted when the test starts, a si7e %ara#eter to be used by the test "or Auantity o" ele#ents or re%etitions o"

522

tests, a constructor to initiali1e the "ields, and an abstract #ethod test A B that does the work. 6ll the di""erent ty%es o" tests are collected in one %lace, the array tests, which is initiali1ed with di""erent anony#ous inner classes that inherit "ro# Tester. To add or re#ove tests, si#%ly add or re#ove an inner class de"inition "ro# the array, and everything else ha%%ens auto#atically. RFSURFSTIJLT+(6PTE52TIMGMU To co#%are array access to container access *%ri#arily against

Array+ist,, a s%ecial test is created "or arrays by wra%%ing one as a +ist using Arrays!as+istA B. Cote that only the "irst two tests can be
%er"or#ed in this case, because you cannot insert or re#ove ele#ents "ro# an array. RFSURFSTIJLT+(6PTE52TIMGKU The +ist that s handed to testA B is "irst "illed with ele#ents, then each test in the tests array is ti#ed. The results will vary "ro# #achine to #achine; they are intended to give only an order o" #agnitude co#%arison between the %er"or#ance o" the di""erent containers. (ere is a su##ary o" one run=

Type
array

"et
M?L@ L@G@ M3LK @ ?I2@

Iteratio n
LIH@ MKK@@ 2MM@ M3KH@

Inser t
na H@@ MM@ HH@

$emov e
na ?3IH@ 3@ ?3IH@

Array+ist +inke'+is t Vector

6s e&%ected, arrays are "aster than any container "or rando#'access looku%s and iteration. /ou can see that rando# accesses * getA B, are chea% "or Array+ists and e&%ensive "or +inke'+ists. *)ddly, iteration is $aster "or a +inke'+ist than an Array+ist, which is a bit counterintuitive., )n the other hand, insertions and re#ovals "ro# the #iddle o" a list are dra#atically chea%er "or a +inke'+ist than "or an Array+ist9 es eciall) re#ovals. Vector is generally not as "ast as Array+ist, and it should be avoided; it s only in the library "or legacy code su%%ort *the only reason it works in this %rogra# is because it was ada%ted to be a +ist in Java K,. The best a%%roach is %robably to choose an Array+ist as your de"ault, and to change to a +inke'+ist i" you discover %er"or#ance %roble#s due to #any insertions and re#ovals

Cha ter ;! .olding Lour Ob>ects

523

"ro# the #iddle o" the list. 6nd o" course, i" you are working with a "i&ed' si1ed grou% o" ele#ents, use an array.

Choosing between Sets


/ou can choose between a Tree)et and a Hash)et, de%ending on the si1e o" the )et *i" you need to %roduce an ordered seAuence "ro# a )et, use Tree)et,. The "ollowing test %rogra# gives an indication o" this trade'o""= RFSURFSTIJLT+(6PTE52TIMGLU

//3 c'C3%etPerfor#ance.Hava i#"ort Hava.util.B< i#"ort co#.bruceeckel.util.B< "ublic class %etPerfor#ance @ "rivate abstract static class Tester @ %tring na#e< Tester-%tring na#e. @ this.na#e ? na#e< A abstract voi! test-%et s, int siUe, int re"s.< A "rivate static TesterNO tests ? @ ne: Tester-8a!!8. @ voi! test-%et s, int siUe, int re"s. @ for-int i ? '< i P re"s< iKK. @ s.clear-.< Collections .fill-s, Collections .countries.reset-.,siUe.< A A A, ne: Tester-8contains8. @ voi! test-%et s, int siUe, int re"s. @ for-int i ? '< i P re"s< iKK. for-int H ? '< H P siUe< HKK. s.contains-$nteger.to%tring-H..< A A, ne: Tester-8iteration8. @ voi! test-%et s, int siUe, int re"s. @ for-int i ? '< i P re"s B ('< iKK. @ $terator it ? s.iterator-.<

524

:hile-it.has&e6t-.. it.ne6t-.< A A A, A< "ublic static voi! test-%et s, int siUe, int re"s. @ %yste#.out."rintln-8Testing 8 K s.getClass-..get&a#e-. K 8 siUe 8 K siUe.< Collections .fill-s, Collections .countries.reset-., siUe.< for-int i ? '< i P tests.length< iKK. @ %yste#.out."rint-testsNiO.na#e.< long t( ? %yste#.currentTi#eJillis-.< testsNiO.test-s, siUe, re"s.< long t ? %yste#.currentTi#eJillis-.< %yste#.out."rintln-83 8 K --!ouble.-t - t(./-!ouble.siUe..< A A "ublic static voi! #ain-%tringNO args. @ int re"s ? ,''''< // Gr, choose the nu#ber of re"etitions // via the co##an! line3 if-args.length Q '. re"s ? $nteger."arse$nt-argsN'O.< // %#all3 test-ne: Tree%et-., (', re"s.< test-ne: Mash%et-., (', re"s.< // Je!iu#3 test-ne: Tree%et-., ('', re"s.< test-ne: Mash%et-., ('', re"s.< // Large3 test-ne: Tree%et-., (''', re"s.< test-ne: Mash%et-., (''', re"s.< A A ///3>

Cha ter ;! .olding Lour Ob>ects

525

The "ollowing table shows the results o" one run. *)" course, this will be di""erent according to the co#%uter and JVM you are using; you should run the test yoursel" as well,=

Type

Test si7e
M@

A' '
ML I.@ MI 2.H MH @.3 HH. @ ?H. 3 L3. M?

-ontai ns
MMH.@ MHM.M MGG.? IK.@ 2@.@ M@3.H

Iterati on
MIG.@ K@3.H ?@.@? M2K.@ K@K.K L2.L2

Tree) et

M@@ M@@@ M@

Hash )et

M@@ M@@@

The %er"or#ance o" Hash)et is generally su%erior to Tree)et "or all o%erations *but in %articular addition and looku%, the two #ost i#%ortant o%erations,. The only reason Tree)et e&ists is because it #aintains its ele#ents in sorted order, so you only use it when you need a sorted )et.

Choosing between 3a s
:hen choosing between i#%le#entations o" 1ap, the si1e o" the 1ap is what #ost strongly a""ects %er"or#ance, and the "ollowing test %rogra# gives an indication o" this trade'o""= RFSURFSTIJLT+(6PTE52TIMG?U

//3 c'C3Ja"Perfor#ance.Hava // De#onstrates "erfor#ance !ifferences in Ja"s. i#"ort Hava.util.B< i#"ort co#.bruceeckel.util.B< "ublic class Ja"Perfor#ance @ "rivate abstract static class Tester @ %tring na#e< Tester-%tring na#e. @ this.na#e ? na#e< A

527

abstract voi! test-Ja" #, int siUe, int re"s.< A "rivate static TesterNO tests ? @ ne: Tester-8"ut8. @ voi! test-Ja" #, int siUe, int re"s. @ for-int i ? '< i P re"s< iKK. @ #.clear-.< Collections .fill-#, Collections .geogra"hy.reset-., siUe.< A A A, ne: Tester-8get8. @ voi! test-Ja" #, int siUe, int re"s. @ for-int i ? '< i P re"s< iKK. for-int H ? '< H P siUe< HKK. #.get-$nteger.to%tring-H..< A A, ne: Tester-8iteration8. @ voi! test-Ja" #, int siUe, int re"s. @ for-int i ? '< i P re"s B ('< iKK. @ $terator it ? #.entry%et-..iterator-.< :hile-it.has&e6t-.. it.ne6t-.< A A A, A< "ublic static voi! test-Ja" #, int siUe, int re"s. @ %yste#.out."rintln-8Testing 8 K #.getClass-..get&a#e-. K 8 siUe 8 K siUe.< Collections .fill-#, Collections .geogra"hy.reset-., siUe.< for-int i ? '< i P tests.length< iKK. @ %yste#.out."rint-testsNiO.na#e.< long t( ? %yste#.currentTi#eJillis-.< testsNiO.test-#, siUe, re"s.< long t ? %yste#.currentTi#eJillis-.< %yste#.out."rintln-83 8 K

Cha ter ;! .olding Lour Ob>ects

528

--!ouble.-t A

- t(./-!ouble.siUe..<

A "ublic static voi! #ain-%tringNO args. @ int re"s ? ,''''< // Gr, choose the nu#ber of re"etitions // via the co##an! line3 if-args.length Q '. re"s ? $nteger."arse$nt-argsN'O.< // %#all3 test-ne: TreeJa"-., (', re"s.< test-ne: MashJa"-., (', re"s.< test-ne: Mashtable-., (', re"s.< // Je!iu#3 test-ne: TreeJa"-., ('', re"s.< test-ne: MashJa"-., ('', re"s.< test-ne: Mashtable-., ('', re"s.< // Large3 test-ne: TreeJa"-., (''', re"s.< test-ne: MashJa"-., (''', re"s.< test-ne: Mashtable-., (''', re"s.< A A ///3>
Because the si1e o" the #a% is the issue, you ll see that the ti#ing tests divide the ti#e by the si1e to nor#ali1e each #easure#ent. (ere is one set o" results. */ours will %robably be di""erent.,

Type

Tes t si7 e
M@

#*t

"et

Iteratio n

Tree1a p

M@@ M@@ @ M@

M?L .@ K@M .M KKK .I 33. @

MM@.@ MII.? K@H.K IL.@

MI3.@ KI@.M ?@.G M2G.@

52:

Type

Tes t si7 e
M@@ M@@ @ M@

#*t

"et

Iteratio n

Hash1a p

Hashtab le

M@@ M@@ @

I@. G ?I. K 3M. @ 2@. 3 H?. M

MLH.G M@H.G 2L.@ M?L.L MM@.2 H

KGI.H ?M.? L@K.@ LK2.@ ?G.L

6s you #ight e&%ect, Hashtable %er"or#ance is roughly eAuivalent to Hash1ap. */ou can also see that Hash1ap is generally a bit "aster. Hash1ap is intended to re%lace Hashtable., The Tree1ap is generally slower than the Hash1ap, so why would you use itO So you could use it not as a 1ap, but as a way to create an ordered list. The behavior o" a tree is such that it s always in order and doesn t have to be s%ecially sorted. )nce you "ill a Tree1ap, you can call key)etA B to get a )et view o" the keys, then toArrayA B to %roduce an array o" those keys. /ou can then use the static #ethod Arrays!binary)earchA B *discussed later, to ra%idly "ind ob0ects in your sorted array. )" course, you would %robably only do this i", "or so#e reason, the behavior o" a Hash1ap was unacce%table, since Hash1ap is designed to ra%idly "ind things. 6lso, you can easily create a Hash1ap "ro# a Tree1ap with a single ob0ect creation In the end, when you re using a 1ap your "irst choice should be Hash1ap, and only i" you need a constantly sorted 1ap will you need Tree1ap.

1orting and searching #ists


4tilities to %er"or# sorting and searching "or +ists have the sa#e na#es and signatures as those "or sorting arrays o" ob0ects, but are static

Cha ter ;! .olding Lour Ob>ects

52;

#ethods o" -ollections instead o" Arrays. (ere s an e&a#%le, #odi"ied "ro# Array)earching!8ava=

//3 c'C3List%ort%earch.Hava // %orting an! searching Lists :ith 2Collections.2 i#"ort co#.bruceeckel.util.B< i#"ort Hava.util.B< "ublic class List%ort%earch @ "ublic static voi! #ain-%tringNO args. @ List list ? ne: 0rrayList-.< Collections .fill-list, Collections .ca"itals, ,.< %yste#.out."rintln-list K 8_n8.< Collections.shuffle-list.< %yste#.out."rintln-80fter shuffling3 8Klist.< Collections.sort-list.< %yste#.out."rintln-list K 8_n8.< GbHect key ? list.get-( .< int in!e6 ? Collections.binary%earch-list, key.< %yste#.out."rintln-8Location of 8 K key K 8 is 8 K in!e6 K 8, list.get-8 K in!e6 K 8. ? 8 K list.get-in!e6..< 0l"habeticCo#"arator co#" ? ne: 0l"habeticCo#"arator-.< Collections.sort-list, co#".< %yste#.out."rintln-list K 8_n8.< key ? list.get-( .< in!e6 ? Collections.binary%earch-list, key, co#".< %yste#.out."rintln-8Location of 8 K key K 8 is 8 K in!e6 K 8, list.get-8 K in!e6 K 8. ? 8 K list.get-in!e6..< A A ///3>
The use o" these #ethods is identical to the ones in Arrays, but you re using a +ist instead o" an array. Just like searching and sorting with arrays, i" you sort using a -omparator you #ust binary)earchA B using the sa#e -omparator. RFSURFSTIJLT+(6PTE52TIMGHU

53=

This %rogra# also de#onstrates the sh*ffleA B #ethod in -ollections, which rando#i1es the order o" a +ist. RFSURFSTIJLT+(6PTE52TIMG3U

Ctilities
There are a nu#ber o" other use"ul utilities in the -ollections class=

en*merationA-ollectionB ma4A-ollectionB minA-ollectionB

ma4A-ollection, -omparatorB minA-ollection, -omparatorB reverseA B copyA+ist 'est, +ist srcB fillA+ist list, .b8ect oB n-opiesAint n, .b8ect oB

Produces an old'style &n*meration "or the argu#ent. Produces the #a&i#u# or #ini#u# ele#ent in the argu#ent using the natural co#%arison #ethod o" the ob0ects in the -ollection. Produces the #a&i#u# or #ini#u# ele#ent in the -ollection using the -omparator. 5everses all the ele#ents in %lace. +o%ies ele#ents "ro# src to dest. 5e%laces all the ele#ents o" list with o. 5eturns an i##utable +ist o" si1e n whose re"erences all %oint to o.

Cote that minA B and ma4A B work with -ollection ob0ects, not with +ists, so you don t need to worry about whether the -ollection should be sorted or not. *6s #entioned earlier, you do need to sortA B a +ist or an array be"ore %er"or#ing a binary)earchA B., RFSURF STIJLT+(6PTE52TIMGGU

Cha ter ;! .olding Lour Ob>ects

531

Making a $ollection or 3a unmodifiable


)"ten it is convenient to create a read'only version o" a -ollection or 1ap. The -ollections class allows you to do this by %assing the original container into a #ethod that hands back a read'only version. There are "our variations on this #ethod, one each "or -ollection *i" you don t want to treat a -ollection as a #ore s%eci"ic ty%e,, +ist, )et, and 1ap. This e&a#%le shows the %ro%er way to build read'only versions o" each=

//3 c'C35ea!Gnly.Hava // Ysing the Collections.un#o!ifiable #etho!s. i#"ort Hava.util.B< i#"ort co#.bruceeckel.util.B< "ublic class 5ea!Gnly @ static Collections .%tringaenerator gen ? Collections .countries< "ublic static voi! #ain-%tringNO args. @ Collection c ? ne: 0rrayList-.< Collections .fill-c, gen, ,.< // $nsert !ata c ? Collections.un#o!ifiableCollection-c.< %yste#.out."rintln-c.< // 5ea!ing is G` c.a!!-8one8.< // Can2t change it List a ? ne: 0rrayList-.< Collections .fill-a, gen.reset-., ,.< a ? Collections.un#o!ifiableList-a.< List$terator lit ? a.list$terator-.< %yste#.out."rintln-lit.ne6t-..< // 5ea!ing G` lit.a!!-8one8.< // Can2t change it %et s ? ne: Mash%et-.< Collections .fill-s, gen.reset-., ,.< s ? Collections.un#o!ifiable%et-s.< %yste#.out."rintln-s.< // 5ea!ing G` //4 s.a!!-8one8.< // Can2t change it Ja" # ? ne: MashJa"-.< Collections .fill-#,

532

Collections .geogra"hy, ,.< # ? Collections.un#o!ifiableJa"-#.< %yste#.out."rintln-#.< // 5ea!ing G` //4 #."ut-85al"h8, 8Mo:!y48.< A A ///3>
In each case, you #ust "ill the container with #eaning"ul data be$ore you #ake it read'only. )nce it is loaded, the best a%%roach is to re%lace the e&isting re"erence with the re"erence that is %roduced by the !un#odi"iable$ call. That way, you don t run the risk o" accidentally changing the contents once you ve #ade it un#odi"iable. )n the other hand, this tool also allows you to kee% a #odi"iable container as private within a class and to return a read'only re"erence to that container "ro# a #ethod call. So you can change it "ro# within the class, but everyone else can only read it. RFSURFSTIJLT+(6PTE52TIMGIU +alling the !un#odi"iable$ #ethod "or a %articular ty%e does not cause co#%ile'ti#e checking, but once the trans"or#ation has occurred, any calls to #ethods that #odi"y the contents o" a %articular container will %roduce an Uns*pporte'.peration&4ception. RFSURF STIJLT+(6PTE52TIMG2U

1:nchroni?ing a $ollection or 3a
The synchroni7e' keyword is an i#%ortant %art o" the sub0ect o" multithreading, a #ore co#%licated to%ic that will not be introduced until +ha%ter M?. (ere, I shall note only that the -ollections class contains a way to auto#atically synchroni1e an entire container. The synta& is si#ilar to the !un#odi"iable$ #ethods=

//3 c'C3%ynchroniUation.Hava // Ysing the Collections.synchroniUe! #etho!s. i#"ort Hava.util.B< "ublic class %ynchroniUation @ "ublic static voi! #ain-%tringNO args. @ Collection c ? Collections.synchroniUe!Collectionne: 0rrayList-..<

Cha ter ;! .olding Lour Ob>ects

533

List list ? Collections.synchroniUe!Listne: 0rrayList-..< %et s ? Collections.synchroniUe!%etne: Mash%et-..< Ja" # ? Collections.synchroniUe!Ja"ne: MashJa"-..< A A ///3>
In this case, you i##ediately %ass the new container through the a%%ro%riate !synchroni1ed$ #ethod; that way there s no chance o" accidentally e&%osing the unsynchroni1ed version. RFSURF STIJLT+(6PTE52TIMI@U

<ail fast
The Java containers also have a #echanis# to %revent #ore than one %rocess "ro# #odi"ying the contents o" a container. The %roble# occurs i" you re iterating through a container and so#e other %rocess ste%s in and inserts, re#oves, or changes an ob0ect in that container. Maybe you ve already %assed that ob0ect, #aybe it s ahead o" you, #aybe the si1e o" the container shrinks a"ter you call si7eA B9there are #any scenarios "or disaster. The Java containers library incor%orates a $ail/$ast #echanis# that looks "or any changes to the container other than the ones your %rocess is %ersonally res%onsible "or. I" it detects that so#eone else is #odi"ying the container, it i##ediately %roduces a -onc*rrent1o'ification&4ception. This is the !"ail'"ast$ as%ect9it doesn t try to detect a %roble# later on using a #ore co#%le& algorith#. RFSURFSTIJLT+(6PTE52TIMIMU It s Auite easy to see the "ail'"ast #echanis# in o%eration9all you have to do is create an iterator and then add so#ething to the collection that the iterator is %ointing to, like this=

//3 c'C3LailLast.Hava // De#onstrates the 8fail fast8 behavior. i#"ort Hava.util.B< "ublic class LailLast @ "ublic static voi! #ain-%tringNO args. @ Collection c ? ne: 0rrayList-.<

534

$terator it ? c.iterator-.< c.a!!-80n obHect8.< // Causes an e6ce"tion3 %tring s ? -%tring.it.ne6t-.< A A ///3>


The e&ce%tion ha%%ens because so#ething is %laced in the container a$ter the iterator is acAuired "ro# the container. The %ossibility that two %arts o" the %rogra# could be #odi"ying the sa#e container %roduces an uncertain state, so the e&ce%tion noti"ies you that you should change your code9in this case, acAuire the iterator a$ter you have added all the ele#ents to the container. RFSURFSTIJLT+(6PTE52TIMIKU Cote that you cannot bene"it "ro# this kind o" #onitoring when you re accessing the ele#ents o" a +ist using getA B. RFSURF STIJLT+(6PTE52TIMILU

Cnsu..orted o.erations
It s %ossible to turn an array into a +ist with the Arrays!as+istA B #ethod=

//3 c'C3Ynsu""orte!.Hava // %o#eti#es #etho!s !efine! in the // Collection interfaces !on2t :ork4 i#"ort Hava.util.B< "ublic class Ynsu""orte! @ "rivate static %tringNO s ? @ 8one8, 8t:o8, 8three8, 8four8, 8five8, 8si68, 8seven8, 8eight8, 8nine8, 8ten8, A< static List a ? 0rrays.asList-s.< static List a ? a.subList-), +.< "ublic static voi! #ain-%tringNO args. @ %yste#.out."rintln-a.< %yste#.out."rintln-a .< %yste#.out."rintln8a.contains-8 K sN'O K 8. ? 8 K

Cha ter ;! .olding Lour Ob>ects

535

a.contains-sN'O..< %yste#.out."rintln8a.contains0ll-a . ? 8 K a.contains0ll-a ..< %yste#.out."rintln-8a.isE#"ty-. ? 8 K a.isE#"ty-..< %yste#.out."rintln8a.in!e6Gf-8 K sN,O K 8. ? 8 K a.in!e6Gf-sN,O..< // Traverse back:ar!s3 List$terator lit ? a.list$terator-a.siUe-..< :hile-lit.hasPrevious-.. %yste#.out."rint-lit."revious-. K 8 8.< %yste#.out."rintln-.< // %et the ele#ents to !ifferent values3 for-int i ? '< i P a.siUe-.< iKK. a.set-i, 8I*8.< %yste#.out."rintln-a.< // Co#"iles, but :on2t run3 lit.a!!-898.< // Ynsu""orte! o"eration a.clear-.< // Ynsu""orte! a.a!!-8eleven8.< // Ynsu""orte! a.a!!0ll-a .< // Ynsu""orte! a.retain0ll-a .< // Ynsu""orte! a.re#ove-sN'O.< // Ynsu""orte! a.re#ove0ll-a .< // Ynsu""orte! A A ///3>
/ou ll discover that only a %ortion o" the -ollection and +ist inter"aces are actually i#%le#ented. The rest o" the #ethods cause the unwelco#e a%%earance o" so#ething called an Uns*pporte'.peration&4ception. /ou ll learn all about e&ce%tions in the ne&t cha%ter, but the short story is that the -ollection interface 9as well as so#e o" the other interfaces in the Java containers library9 contain !o%tional$ #ethods, which #ight or #ight not be !su%%orted$ in the concrete class that implements that interface. +alling an unsu%%orted #ethod causes an Uns*pporte'.peration&4ception to indicate a %rogra##ing error. RFSURFSTIJLT+(6PTE52TIMI?U

537

!:hatO.O$ you say, incredulous. !The whole %oint o" interfaces and base classes is that they %ro#ise these #ethods will do so#ething #eaning"ul. This breaks that %ro#ise9it says that not only will calling so#e #ethods not %er"or# a #eaning"ul behavior, they will sto% the %rogra#. Ty%e sa"ety was 0ust thrown out the window.$ RFSURF STIJLT+(6PTE52TIMIHU It s not Auite that bad. :ith a -ollection, +ist, )et, or 1ap, the co#%iler still restricts you to calling only the #ethods in that interface, so it s not like S#alltalk *in which you can call any #ethod "or any ob0ect, and "ind out only when you run the %rogra# whether your call does anything,. In addition, #ost #ethods that take a -ollection as an argu#ent only read "ro# that -ollection9all the !read$ #ethods o" -ollection are not o%tional. RFSURFSTIJLT+(6PTE52TIMI3U This a%%roach %revents an e&%losion o" inter"aces in the design. )ther designs "or container libraries always see# to end u% with a con"using %lethora o" inter"aces to describe each o" the variations on the #ain the#e and are thus di""icult to learn. It s not even %ossible to ca%ture all o" the s%ecial cases in interfaces, because so#eone can always invent a new interface. The !unsu%%orted o%eration$ a%%roach achieves an i#%ortant goal o" the Java containers library= the containers are si#%le to learn and use; unsu%%orted o%erations are a s%ecial case that can be learned later. Eor this a%%roach to work, however= RFSURF STIJLT+(6PTE52TIMIGU

5()

The Uns*pporte'.peration&4ception #ust be a rare event. That is, "or #ost classes all o%erations should work, and only in s%ecial cases should an o%eration be unsu%%orted. This is true in the Java containers library, since the classes you ll use 22 %ercent o" the ti#e9 Array+ist, +inke'+ist, Hash)et, and Hash1ap, as well as the other concrete i#%le#entations9su%%ort all o" the o%erations. The design does %rovide a !back door$ i" you want to create a new -ollection without %roviding #eaning"ul de"initions "or all the #ethods in the -ollection interface, and yet still "it it into the e&isting library. RFSURFSTIJLT+(6PTE52TIMIIU :hen an o%eration is unsu%%orted, there should be reasonable likelihood that an Uns*pporte'.peration&4ception will

5!)

Cha ter ;! .olding Lour Ob>ects

538

a%%ear at i#%le#entation ti#e, rather than a"ter you ve shi%%ed the %roduct to the custo#er. 6"ter all, it indicates a %rogra##ing error= you ve used an i#%le#entation incorrectly. This %oint is less certain, and is where the e&%eri#ental nature o" this design co#es into %lay. )nly over ti#e will we "ind out how well it works. RF SURFSTIJLT+(6PTE52TIMI2U In the e&a#%le above, Arrays!as+istA B %roduces a +ist that is backed by a "i&ed'si1e array. There"ore it #akes sense that the only su%%orted o%erations are the ones that don t change the si1e o" the array. I", on the other hand, a new interface were reAuired to e&%ress this di""erent kind o" behavior *called, %erha%s, ! Fi4e')i7e+ist$,, it would throw o%en the door to co#%le&ity and soon you wouldn t know where to start when trying to use the library. RFSURFSTIJLT+(6PTE52TIM2@U The docu#entation "or a #ethod that takes a -ollection, +ist, )et, or 1ap as an argu#ent should s%eci"y which o" the o%tional #ethods #ust be i#%le#ented. Eor e&a#%le, sorting reAuires the setA B and Iterator! setA B #ethods, but not a''A B and removeA B. RFSURF STIJLT+(6PTE52TIM2MU

"ava ()7D()( containers


4n"ortunately, a lot o" code was written using the Java M.@FM.M containers, and even new code is so#eti#es written using these classes. So although you should never use the old containers when writing new code, you ll still need to be aware o" the#. (owever, the old containers were Auite li#ited, so there s not that #uch to say about the#. *Since they are in the %ast, I will try to re"rain "ro# overe#%hasi1ing so#e o" the hideous design decisions., RFSURFSTIJLT+(6PTE52TIM2KU

=ector L /numeration
The only sel"'e&%anding seAuence in Java M.@FM.M was the Vector, and so it saw a lot o" use. Its "laws are too nu#erous to describe here *see the "irst edition o" this book, available on this book s +7 5)M and as a "ree download "ro# ,,,'0ruceEckel'com,. Basically, you can think o" it as an Array+ist with long, awkward #ethod na#es. In the Java K container

53:

library, Vector was ada%ted so that it could "it as a -ollection and a +ist, so in the "ollowing e&a#%le the -ollectionsI!fillA B #ethod is success"ully used. This turns out to be a bit %erverse, as it #ay con"use so#e %eo%le into thinking that Vector has gotten better, when it is actually included only to su%%ort %re'Java K code. RFSURF STIJLT+(6PTE52TIM2LU The Java M.@FM.M version o" the iterator chose to invent a new na#e, !enu#eration,$ instead o" using a ter# that everyone was already "a#iliar with. The &n*meration inter"ace is s#aller than Iterator, with only two #ethods, and it uses longer #ethod na#es= boolean has1ore&lementsA B %roduces tr*e i" this enu#eration contains #ore ele#ents, and .b8ect ne4t&lementA B returns the ne&t ele#ent o" this enu#eration i" there are any #ore *otherwise it throws an e&ce%tion,. RF SURFSTIJLT+(6PTE52TIM2?U

&n*meration is only an inter"ace, not an i#%le#entation, and even new libraries so#eti#es still use the old &n*meration9which is
un"ortunate but generally har#less. Even though you should always use Iterator when you can in your own code, you #ust be %re%ared "or libraries that want to hand you an &n*meration. RFSURF STIJLT+(6PTE52TIM2HU In addition, you can %roduce an &n*meration "or any -ollection by using the -ollections!en*merationA B #ethod, as seen in this e&a#%le=

//3 c'C3Enu#erations.Hava // Java (.'/(.( Wector an! Enu#eration. i#"ort Hava.util.B< i#"ort co#.bruceeckel.util.B< "ublic class Enu#erations @ "ublic static voi! #ain-%tringNO args. @ Wector v ? ne: Wector-.< Collections .fillv, Collections .countries, (''.< Enu#eration e ? v.ele#ents-.< :hile-e.hasJoreEle#ents-.. %yste#.out."rintln-e.ne6tEle#ent-..<

Cha ter ;! .olding Lour Ob>ects

53;

// Pro!uce an Enu#eration fro# a Collection3 e ? Collections.enu#eration-ne: 0rrayList-..< A A ///3>


The Java M.@FM.M Vector has only an a''&lementA B #ethod, but fillA B uses the a''A B #ethod that was %asted on as Vector was turned into a +ist. To %roduce an &n*meration, you call elementsA B, then you can use it to %er"or# a "orward iteration. RFSURFSTIJLT+(6PTE52TIM23U The last line creates an Array+ist and uses en*merationA B to ada%t an &n*meration "ro# the Array+ist Iterator. Thus, i" you have old code that wants an &n*meration, you can still use the new containers. RF SURFSTIJLT+(6PTE52TIM2GU

>ashtable
6s you ve seen in the %er"or#ance co#%arison in this cha%ter, the basic Hashtable is very si#ilar to the Hash1ap, even down to the #ethod na#es. There s no reason to use Hashtable instead o" Hash1ap in new code. RFSURFSTIJLT+(6PTE52TIM2IU

1tack
The conce%t o" the stack was introduced earlier, with the +inke'+ist. :hat s rather odd about the Java M.@FM.M )tack is that instead o" using a Vector as a building block, )tack is inherited "ro# Vector. So it has all o" the characteristics and behaviors o" a Vector %lus so#e e&tra )tack behaviors. It s di""icult to know whether the designers e&%licitly decided that this was an es%ecially use"ul way o" doing things, or whether it was 0ust a naive design. RFSURFSTIJLT+(6PTE52TIM22U (ere s a si#%le de#onstration o" )tack that %ushes each line "ro# a )tring array=

//3 c'C3%tacks.Hava // De#onstration of %tack Class. i#"ort Hava.util.B< "ublic class %tacks @

54=

static %tringNO #onths ? @ 8January8, 8Lebruary8, 8Jarch8, 80"ril8, 8Jay8, 8June8, 8July8, 80ugust8, 8%e"te#ber8, 8Gctober8, 8&ove#ber8, 8Dece#ber8 A< "ublic static voi! #ain-%tringNO args. @ %tack stk ? ne: %tack-.< for-int i ? '< i P #onths.length< iKK. stk."ush-#onthsNiO K 8 8.< %yste#.out."rintln-8stk ? 8 K stk.< // Treating a stack as a Wector3 stk.a!!Ele#ent-8The last line8.< %yste#.out."rintln8ele#ent , ? 8 K stk.ele#ent0t-,..< %yste#.out."rintln-8"o""ing ele#ents38.< :hile-4stk.e#"ty-.. %yste#.out."rintln-stk."o"-..< A A ///3>
Each line in the months array is inserted into the )tack with p*shA B, and later "etched "ro# the to% o" the stack with a popA B. To #ake a %oint, Vector o%erations are also %er"or#ed on the )tack ob0ect. This is %ossible because, by virtue o" inheritance, a )tack is a Vector. Thus, all o%erations that can be %er"or#ed on a Vector can also be %er"or#ed on a )tack, such as elementAtA B. RFSURFSTIJLT+(6PTE52TIK@@U 6s #entioned earlier, you should use a +inke'+ist when you want stack behavior. RFSURFSTIJLT+(6PTE52TIK@MU

;it1et
6 2it)et is used i" you want to e""iciently store a lot o" on'o"" in"or#ation. It s e""icient only "ro# the stand%oint o" si1e; i" you re looking "or e""icient access, it is slightly slower than using an array o" so#e native ty%e. RFSURFSTIJLT+(6PTE52TIK@KU In addition, the #ini#u# si1e o" the 2it)et is that o" a long= 3? bits. This i#%lies that i" you re storing anything s#aller, like I bits, a 2it)et will be waste"ul; you re better o"" creating your own class, or 0ust an array, to hold your "lags i" si1e is an issue. RFSURFSTIJLT+(6PTE52TIK@LU

Cha ter ;! .olding Lour Ob>ects

541

6 nor#al container e&%ands as you add #ore ele#ents, and the 2it)et does this as well. The "ollowing e&a#%le shows how the 2it)et works=

//3 c'C3Bits.Hava // De#onstration of Bit%et. i#"ort Hava.util.B< "ublic class Bits @ static voi! "rintBit%et-Bit%et b. @ %yste#.out."rintln-8bits3 8 K b.< %tring bbits ? ne: %tring-.< for-int H ? '< H P b.siUe-. < HKK. bbits K? -b.get-H. [ 8(8 3 8'8.< %yste#.out."rintln-8bit "attern3 8 K bbits.< A "ublic static voi! #ain-%tringNO args. @ 5an!o# ran! ? ne: 5an!o#-.< // Take the L%B of ne6t$nt-.3 byte bt ? -byte.ran!.ne6t$nt-.< Bit%et bb ? ne: Bit%et-.< for-int i ? *< i Q?'< i--. if---( PP i. D bt. 4? '. bb.set-i.< else bb.clear-i.< %yste#.out."rintln-8byte value3 8 K bt.< "rintBit%et-bb.< short st ? -short.ran!.ne6t$nt-.< Bit%et bs ? ne: Bit%et-.< for-int i ? (,< i Q?'< i--. if---( PP i. D st. 4? '. bs.set-i.< else bs.clear-i.< %yste#.out."rintln-8short value3 8 K st.< "rintBit%et-bs.< int it ? ran!.ne6t$nt-.< Bit%et bi ? ne: Bit%et-.< for-int i ? )(< i Q?'< i--.

542

if---( PP i. D it. 4? '. bi.set-i.< else bi.clear-i.< %yste#.out."rintln-8int value3 8 K it.< "rintBit%et-bi.< // Test bitsets Q? +I bits3 Bit%et b( * ? ne: Bit%et-.< b( *.set-( *.< %yste#.out."rintln-8set bit ( *3 8 K b( *.< Bit%et b ,, ? ne: Bit%et-+,.< b ,,.set- ,,.< %yste#.out."rintln-8set bit ,,3 8 K b ,,.< Bit%et b(' ) ? ne: Bit%et-,( .< b(' ).set-(' ).< b(' ).set-(' I.< %yste#.out."rintln-8set bit (' )3 8 K b(' ).< A A ///3>
The rando# nu#ber generator is used to create a rando# byte, short, and int, and each one is trans"or#ed into a corres%onding bit %attern in a 2it)et. This works "ine because a 2it)et is 3? bits, so none o" these cause it to increase in si1e. Then a 2it)et o" HMK bits is created. The constructor allocates storage "or twice that nu#ber o" bits. (owever, you can still set bit M@K? or greater. RFSURFSTIJLT+(6PTE52TIK@?U

1ummar:
To review the containers %rovided in the standard Java library= RFSURF STIJLT+(6PTE52TIK@HU

5*)

6n array associates nu#erical indices to ob0ects. It holds ob0ects o" a known ty%e so that you don t have to cast the result when you re looking u% an ob0ect. It can be #ultidi#ensional, and it can hold %ri#itives. (owever, its si1e cannot be changed once you create it. RFSURFSTIJLT+(6PTE52TIK@3U

Cha ter ;! .olding Lour Ob>ects

543

5+) 5,)

6 -ollection holds single ele#ents, while a 1ap holds associated %airs. RFSURFSTIJLT+(6PTE52TIK@GU Dike an array, a +ist also associates nu#erical indices to ob0ects9 you can think o" arrays and +ists as ordered containers. The +ist auto#atically resi1es itsel" as you add #ore ele#ents. But a +ist can hold only .b8ect references, so it won t hold %ri#itives and you #ust always cast the result when you %ull an .b8ect re"erence out o" a container. RFSURFSTIJLT+(6PTE52TIK@IU 4se an Array+ist i" you re doing a lot o" rando# accesses, and a +inke'+ist i" you will be doing a lot o" insertions and re#ovals in the #iddle o" the list. RFSURFSTIJLT+(6PTE52TIK@2U The behavior o" Aueues, deAues, and stacks is %rovided via the +inke'+ist. RFSURFSTIJLT+(6PTE52TIKM@U 6 1ap is a way to associate not nu#bers, but ob>ects with other ob0ects. The design o" a Hash1ap is "ocused on ra%id access, while a Tree1ap kee%s its keys in sorted order, and thus is not as "ast as a Hash1ap. RFSURFSTIJLT+(6PTE52TIKMMU 6 )et only acce%ts one o" each ty%e o" ob0ect. Hash)ets %rovide #a&i#ally "ast looku%s, while Tree)ets kee% the ele#ents in sorted order. RFSURFSTIJLT+(6PTE52TIKMKU There s no need to use the legacy classes Vector, Hashtable and )tack in new code. RFSURFSTIJLT+(6PTE52TIKMLU

5-)

54) 55)

56)

67)

The containers are tools that you can use on a day'to'day basis to #ake your %rogra#s si#%ler, #ore %ower"ul, and #ore e""ective. RFSURF STIJLT+(6PTE52TIKM?U

/0ercises
Solutions to selected e&ercises can be "ound in the electronic docu#entThe Thinking in Java "nnotated Solution @uide, available "or a s#all "ee "ro# ,,,'0ruceEckel'com.

(!+) +reate an array o" 'o*ble and fillA B it using


$an' o*ble"enerator. Print the results. RFSURF
STIJLT+(6PTE52TIKMHU

544

(!,) +reate a new class called "erbil with an int gerbil/*mber


that s initiali1ed in the constructor *si#ilar to the 1o*se e&a#%le in this cha%ter,. 8ive it a #ethod called hopA B that %rints out which gerbil nu#ber this is, and that it s ho%%ing. +reate an Array+ist and add a bunch o" "erbil ob0ects to the +ist. Cow use the getA B #ethod to #ove through the +ist and call hopA B "or each "erbil. RFSURFSTIJLT+(6PTE52TIKM3U

(!-) Modi"y E&ercise K so you use an Iterator to #ove through the


+ist while calling hopA B. RFSURFSTIJLT+(6PTE52TIKMGU

(!4) Take the "erbil class in E&ercise K and %ut it into a 1ap
instead, associating the na#e o" the "erbil as a )tring *the key, "or each "erbil *the value, you %ut in the table. 8et an Iterator "or the key)etA B and use it to #ove through the 1ap, looking u% the "erbil "or each key and %rinting out the key and telling the gerbil to hopA B. RFSURFSTIJLT+(6PTE52TIKMIU

(!5) +reate a +ist *try both Array+ist and +inke'+ist, and "ill it
using -ollectionsI!co*ntries. Sort the list and %rint it, then a%%ly -ollections!sh*ffleA B to the list re%eatedly, %rinting it each ti#e so that you can see how the sh*ffleA B #ethod rando#i1es the list di""erently each ti#e. RFSURF STIJLT+(6PTE52TIKM2U

(!6) 7e#onstrate that you can t add anything but a 1o*se to a


1o*se+ist. RFSURFSTIJLT+(6PTE52TIKK@U

(*7) Modi"y 1o*se+ist!8ava so that it inherits "ro# Array+ist


instead o" using co#%osition. 7e#onstrate the %roble# with this a%%roach. RFSURFSTIJLT+(6PTE52TIKKMU

(*() 5e%air -atsAn' ogs!8ava by creating a -ats container


*utili1ing Array+ist, that will only acce%t and retrieve -at ob0ects. RFSURFSTIJLT+(6PTE52TIKKKU

(*!) +reate a container that enca%sulates an array o" )tring, and


that only adds )trings and gets )trings, so that there are no casting issues during use. I" the internal array isn t big enough "or the ne&t add, your container should auto#atically resi1e it. In

Cha ter ;! .olding Lour Ob>ects

545

mainA B, co#%are the %er"or#ance o" your container with an Array+ist holding )trings. RFSURFSTIJLT+(6PTE52TIKKLU

(**) 5e%eat E&ercise 2 "or a container o" int, and co#%are the
%er"or#ance to an Array+ist holding Integer ob0ects. In your %er"or#ance co#%arison, include the %rocess o" incre#enting each ob0ect in the container. RFSURFSTIJLT+(6PTE52TIKK?U

(*+) 4sing the utilities in com!br*ceeckel!*til, create an array o"


each %ri#itive ty%e and o" )tring, then "ill each array using an a%%ro%riate generator, and %rint each array using the a%%ro%riate printA B #ethod. RFSURFSTIJLT+(6PTE52TIKKHU

(*,) +reate a generator that %roduces character na#es "ro# your


"avorite #ovies *you can use Sno, Bhite or Star Bars as a "allback,, and loo%s around to the beginning when it runs out o" na#es. 4se the utilities in com!br*ceeckel!*til to "ill an array, an Array+ist, a +inke'+ist and both ty%es o" )et, then %rint each container. RFSURFSTIJLT+(6PTE52TIKK3U

(*-) +reate a class containing two )tring ob0ects, and #ake it


-omparable so that the co#%arison only cares about the "irst )tring. Eill an array and an Array+ist with ob0ects o" your class, using the geography generator. 7e#onstrate that sorting works %ro%erly. Cow #ake a -omparator that only cares about the second )tring and de#onstrate that sorting works %ro%erly; also %er"or# a binary search using your -omparator. RFSURF
STIJLT+(6PTE52TIKKGU

(*4) Modi"y E&ercise ML so that an al%habetic sort is used. RFSURF


STIJLT+(6PTE52TIKKIU

(*5) 4se ArraysI!$an')tring"enerator to "ill a Tree)et but


using al%habetic ordering. Print the Tree)et to veri"y the sort order. RFSURFSTIJLT+(6PTE52TIKK2U

(*6) +reate both an Array+ist and a +inke'+ist, and "ill each


using the -ollectionsI!capitals generator. Print each list using an ordinary Iterator, then insert one list into the other using a +istIterator, inserting at every other location. Cow %er"or# the

547

insertion starting at the end o" the "irst list and #oving backward. RFSURFSTIJLT+(6PTE52TIKL@U

(+7) :rite a #ethod that uses an Iterator to ste% through a


-ollection and %rint the hash-o'eA B o" each ob0ect in the container. Eill all the di""erent ty%es o" -ollections with ob0ects
and a%%ly your #ethod to each container. RFSURF STIJLT+(6PTE52TIKLMU

(+() 5e%air the %roble# in Infinite$ec*rsion!8ava. RFSURF


STIJLT+(6PTE52TIKLKU

(+!) +reate a class, then #ake an initiali1ed array o" ob0ects o" your
class. Eill a +ist "ro# your array. +reate a subset o" your +ist using s*b+istA B, and then re#ove this subset "ro# your +ist using removeAllA B. RFSURFSTIJLT+(6PTE52TIKLLU

(+*) +hange E&ercise 3 in +ha%ter G to use an Array+ist to hold the


$o'ents and an Iterator to #ove through the seAuence o" $o'ents. 5e#e#ber that an Array+ist holds only .b8ects so you #ust use a cast when accessing individual $o'ents. RFSURF
STIJLT+(6PTE52TIKL?U

(++) Eollowing the 3*e*e!8ava e&a#%le, create a


test it. RFSURFSTIJLT+(6PTE52TIKLHU

eC*e class and

(+,) 4se a Tree1ap in )tatistics!8ava. Cow add code that tests


the %er"or#ance di""erence between Hash1ap and Tree1ap in that %rogra#. RFSURFSTIJLT+(6PTE52TIKL3U

(+-) Produce a 1ap and a )et containing all the countries that
begin with [6. RFSURFSTIJLT+(6PTE52TIKLGU

(+4) 4sing -ollectionsI!co*ntries, "ill a )et #ulti%le ti#es with


the sa#e data and veri"y that the )et ends u% with only one o" each instance. Try this with both kinds o" )et. RFSURF STIJLT+(6PTE52TIKLIU

(+5) Starting with )tatistics!8ava, create a %rogra# that runs the


test re%eatedly and looks to see i" any one nu#ber tends to a%%ear

Cha ter ;! .olding Lour Ob>ects

548

#ore than the others in the results. RFSURF STIJLT+(6PTE52TIKL2U

(+6) 5ewrite )tatistics!8ava using a Hash)et o" -o*nter ob0ects


*you ll have to #odi"y -o*nter so that it will work in the Hash)et,. :hich a%%roach see#s betterO RFSURF STIJLT+(6PTE52TIK?@U

(,7) Modi"y the class in E&ercise ML so that it will work with


Hash)ets and as a key in Hash1aps. RFSURF
STIJLT+(6PTE52TIK?MU

(,() 4sing )lo(1ap!8ava "or ins%iration, create a )lo()et. RF


SURFSTIJLT+(6PTE52TIK?KU

(,!) 6%%ly the tests in 1ap>!8ava to )lo(1ap to veri"y that it


works. Ei& anything in )lo(1ap that doesn t work correctly. RF SURFSTIJLT+(6PTE52TIK?LU

(,*) I#%le#ent the rest o" the 1ap inter"ace "or )lo(1ap. RF
SURFSTIJLT+(6PTE52TIK??U

(,+) Modi"y 1ap#erformance!8ava to include tests o"


)lo(1ap. RFSURFSTIJLT+(6PTE52TIK?HU

(,,) Modi"y )lo(1ap so that instead o" two Array+ists, it holds a


single Array+ist o" 1#air ob0ects. Veri"y that the #odi"ied version works correctly. 4sing 1ap#erformance!8ava, test the s%eed o" your new 1ap. Cow change the p*tA B #ethod so that it %er"or#s a sortA B a"ter each %air is entered, and #odi"y getA B to use -ollections!binary)earchA B to look u% the key. +o#%are the %er"or#ance o" the new version with the old ones. RFSURF STIJLT+(6PTE52TIK?3U

(,-) 6dd a char "ield to -o*nte')tring that is also initiali1ed in


the constructor, and #odi"y the hash-o'eA B and eC*alsA B #ethods to include the value o" this char. RFSURF STIJLT+(6PTE52TIK?GU

54:

(,4) Modi"y )impleHash1ap so that it re%orts collisions, and test


this by adding the sa#e data set twice so that you see collisions. RFSURFSTIJLT+(6PTE52TIK?IU

(,5) Modi"y )impleHash1ap so that it re%orts the nu#ber o"


!%robes$ necessary when collisions occur. That is, how #any calls to ne4tA B #ust be #ade on the Iterators that walk the +inke'+ists looking "or #atchesO RFSURF STIJLT+(6PTE52TIK?2U

(,6) I#%le#ent the clearA B and removeA B #ethods "or


)impleHash1ap. RFSURFSTIJLT+(6PTE52TIKH@U

(-7) I#%le#ent the rest o" the 1ap inter"ace "or


)impleHash1ap. RFSURFSTIJLT+(6PTE52TIKHMU

(-() 6dd a private rehashA B #ethod to )impleHash1ap that is


invoked when the load "actor e&ceeds @.GH. 7uring rehashing, double the nu#ber o" buckets, then search "or the "irst %ri#e nu#ber greater than that to deter#ine the new nu#ber o" buckets. RFSURFSTIJLT+(6PTE52TIKHKU

(-!) Eollowing the e&a#%le in )impleHash1ap!8ava, create and


test a )impleHash)et. RFSURFSTIJLT+(6PTE52TIKHLU

(-*) Modi"y )impleHash1ap to use Array+ists instead o"


+inke'+ists. Modi"y 1ap#erformance!8ava to co#%are the
%er"or#ance o" the two i#%le#entations. RFSURF STIJLT+(6PTE52TIKH?U

(-+) 4sing the (TMD docu#entation "or the J7> *downloadable


"ro# >ava'sun'com,, look u% the Hash1ap class. +reate a Hash1ap, "ill it with ele#ents, and deter#ine the load "actor. Test the looku% s%eed with this #a%, then atte#%t to increase the s%eed by #aking a new Hash1ap with a larger initial ca%acity and co%ying the old #a% into the new one, running your looku% s%eed test again on the new #a%. RFSURF STIJLT+(6PTE52TIKHHU

(-,) In +ha%ter I, locate the "reenho*se-ontrols!8ava e&a#%le,


which consists o" three "iles. In -ontroller!8ava, the class

Cha ter ;! .olding Lour Ob>ects

54;

&vent)et is 0ust a container. +hange the code to use a +inke'+ist instead o" an &vent)et. This will reAuire #ore than 0ust re%lacing &vent)et with +inke'+ist; you ll also need to use an Iterator to cycle through the set o" events. RFSURF
STIJLT+(6PTE52TIKH3U

(--) *+hallenging,. :rite your own hashed #a% class, custo#i1ed


"or a %articular key ty%e= )tring "or this e&a#%le. 7o not inherit it "ro# 1ap. Instead, du%licate the #ethods so that the p*tA B and getA B #ethods s%eci"ically take )tring ob0ects, not .b8ects, as keys. Everything that involves keys should not use generic ty%es, but instead work with )trings, to avoid the cost o" u%casting and downcasting. /our goal is to #ake the "astest %ossible custo# i#%le#entation. Modi"y 1ap#erformance!8ava to test your i#%le#entation vs. a Hash1ap. RFSURF STIJLT+(6PTE52TIKHGU

(-4) *+hallenging,. Eind the source code "or +ist in the Java source
code library that co#es with all Java distributions. +o%y this code and #ake a s%ecial version called int+ist that holds only ints. +onsider what it would take to #ake a s%ecial version o" +ist "or all the %ri#itive ty%es. Cow consider what ha%%ens i" you want to #ake a linked list class that works with all the %ri#itive ty%es. I" %ara#eteri1ed ty%es are ever i#%le#ented in Java, they will %rovide a way to do this work "or you auto#atically *as well as #any other bene"its,. RFSURFSTIJLT+(6PTE52TIKHIU

(-5) Modi"y cDY<1onthI!8ava to #ake it i#%le#ent the


-omparable inter"ace. RFSURFSTIJLT+(6PTE52TIKH2U

(-6) Modi"y the hash-o'eA B in -o*nte')tring!8ava by


re#oving the #ulti%lication by i', and de#onstrate that -o*nte')tring still works as a key. :hat is the %roble# with this a%%roachO RFSU

55=

(7: /rror >andling with /0ce.tions


RFSTIJLT+(6PTE5M@TI@UThe basic %hiloso%hy o" Java is that !badly "or#ed code will not be run.$
The ideal ti#e to catch an error is at co#%ile'ti#e, be"ore you even try to run the %rogra#. (owever, not all errors can be detected at co#%ile'ti#e. The rest o" the %roble#s #ust be handled at run'ti#e, through so#e "or#ality that allows the originator o" the error to %ass a%%ro%riate in"or#ation to a reci%ient who will know how to handle the di""iculty %ro%erly. RFSURFSTIJLT+(6PTE5M@TIMU In + and other earlier languages, there could be several o" these "or#alities, and they were generally established by convention and not as %art o" the %rogra##ing language. Ty%ically, you returned a s%ecial value or set a "lag, and the reci%ient was su%%osed to look at the value or the "lag and deter#ine that so#ething was a#iss. (owever, as the years %assed, it was discovered that %rogra##ers who use a library tend to think o" the#selves as invincible9as in, !/es, errors #ight ha%%en to others, but not in m) code.$ So, not too sur%risingly, they wouldn t check "or the error conditions *and so#eti#es the error conditions were too silly to check "or @,. I" you ,ere thorough enough to check "or an error every ti#e you called a #ethod, your code could turn into an unreadable night#are. Because %rogra##ers could still coa& syste#s out o" these languages they were resistant to ad#itting the truth= This a%%roach to handling errors was a #a0or li#itation to creating large, robust, #aintainable %rogra#s. RFSURFSTIJLT+(6PTE5M@TIKU

@ The + %rogra##er can look u% the return value o" printfA B "or an e&a#%le o" this.

551

The solution is to take the casual nature out o" error handling and to en"orce "or#ality. This actually has a long history, since i#%le#entations o" e*ce tion handling go back to o%erating syste#s in the M23@s, and even to B6SI+ s ! on error goto.$ But +<< e&ce%tion handling was based on 6da, and Java s is based %ri#arily on +<< *although it looks even #ore like )b0ect Pascal,. RFSURFSTIJLT+(6PTE5M@TILU The word !e&ce%tion$ is #eant in the sense o" !I take e&ce%tion to that.$ 6t the %oint where the %roble# occurs you #ight not know what to do with it, but you do know that you can t 0ust continue on #errily; you #ust sto% and so#ebody, so#ewhere, #ust "igure out what to do. But you don t have enough in"or#ation in the current conte&t to "i& the %roble#. So you hand the %roble# out to a higher conte&t where so#eone is Auali"ied to #ake the %ro%er decision *#uch like a chain o" co##and,. RF SURFSTIJLT+(6PTE5M@TI?U The other rather signi"icant bene"it o" e&ce%tions is that they clean u% error handling code. Instead o" checking "or a %articular error and dealing with it at #ulti%le %laces in your %rogra#, you no longer need to check at the %oint o" the #ethod call *since the e&ce%tion will guarantee that so#eone catches it,. 6nd, you need to handle the %roble# in only one %lace, the so'called e*ce tion handler. This saves you code, and it se%arates the code that describes what you want to do "ro# the code that is e&ecuted when things go awry. In general, reading, writing, and debugging code beco#es #uch clearer with e&ce%tions than when using the old way o" error handling. RFSURFSTIJLT+(6PTE5M@TIHU Because e&ce%tion handling is en"orced by the Java co#%iler, there are only so #any e&a#%les that can be written in this book without learning about e&ce%tion handling. This cha%ter introduces you to the code you need to write to %ro%erly handle e&ce%tions, and the way you can generate your own e&ce%tions i" one o" your #ethods gets into trouble. RFSURF STIJLT+(6PTE5M@TI3U

;asic e0ce.tions
6n e*ce tional condition is a %roble# that %revents the continuation o" the #ethod or sco%e that you re in. It s i#%ortant to distinguish an

552

Thinking in Java

,,,'0ruceEckel'com

e&ce%tional condition "ro# a nor#al %roble#, in which you have enough in"or#ation in the current conte&t to so#ehow co%e with the di""iculty. :ith an e&ce%tional condition, you cannot continue %rocessing because you don t have the in"or#ation necessary to deal with the %roble# in the current conte*t. 6ll you can do is 0u#% out o" the current conte&t and relegate that %roble# to a higher conte&t. This is what ha%%ens when you throw an e&ce%tion. RFSURFSTIJLT+(6PTE5M@TIGU 6 si#%le e&a#%le is a divide. I" you re about to divide by 1ero, it s worth checking to #ake sure you don t go ahead and %er"or# the divide. But what does it #ean that the deno#inator is 1eroO Maybe you know, in the conte&t o" the %roble# you re trying to solve in that %articular #ethod, how to deal with a 1ero deno#inator. But i" it s an une&%ected value, you can t deal with it and so #ust throw an e&ce%tion rather than continuing along that %ath. RFSURFSTIJLT+(6PTE5M@TIIU :hen you throw an e&ce%tion, several things ha%%en. Eirst, the e&ce%tion ob0ect is created in the sa#e way that any Java ob0ect is created= on the hea%, with ne(. Then the current %ath o" e&ecution *the one you couldn t continue, is sto%%ed and the re"erence "or the e&ce%tion ob0ect is e0ected "ro# the current conte&t. 6t this %oint the e&ce%tion handling #echanis# takes over and begins to look "or an a%%ro%riate %lace to continue e&ecuting the %rogra#. This a%%ro%riate %lace is the e*ce tion handlerD whose 0ob is to recover "ro# the %roble# so the %rogra# can either try another tack or 0ust continue. RFSURFSTIJLT+(6PTE5M@TI2U 6s a si#%le e&a#%le o" throwing an e&ce%tion, consider an ob0ect re"erence called t. It s %ossible that you #ight be %assed a re"erence that hasn t been initiali1ed, so you #ight want to check be"ore trying to call a #ethod using that ob0ect re"erence. /ou can send in"or#ation about the error into a larger conte&t by creating an ob0ect re%resenting your in"or#ation and !throwing$ it out o" your current conte&t. This is called thro,ing an e*ce tion' (ere s what it looks like=

if-t ?? null. thro: ne: &ullPointerE6ce"tion-.<


This throws the e&ce%tion, which allows you9in the current conte&t9to abdicate res%onsibility "or thinking about the issue "urther. It s 0ust

553

#agically handled so#ewhere else. Precisely ,here will be shown shortly. RFSURFSTIJLT+(6PTE5M@TIM@U

/0ce.tion arguments
Dike any ob0ect in Java, you always create e&ce%tions on the hea% using ne(, which allocates storage and calls a constructor. There are two constructors in all standard e&ce%tions= the "irst is the de"ault constructor, and the second takes a string argu#ent so you can %lace %ertinent in"or#ation in the e&ce%tion=

if-t ?? null. thro: ne: &ullPointerE6ce"tion-8t ? null8.<


This string can later be e&tracted using various #ethods, as you ll see. RF SURFSTIJLT+(6PTE5M@TIMMU The keyword thro( causes a nu#ber o" relatively #agical things to ha%%en. Ty%ically, you ll "irst use ne( to create an ob0ect that re%resents the error condition. /ou give the resulting re"erence to thro(. The ob0ect is, in e""ect, !returned$ "ro# the #ethod, even though that ob0ect ty%e isn t nor#ally what the #ethod is designed to return. 6 si#%listic way to think about e&ce%tion handling is as an alternate return #echanis#, although you get into trouble i" you take that analogy too "ar. /ou can also e&it "ro# ordinary sco%es by throwing an e&ce%tion. But a value is returned, and the #ethod or sco%e e&its. RFSURF STIJLT+(6PTE5M@TIMKU 6ny si#ilarity to an ordinary return "ro# a #ethod ends here, because

,here you return is so#e%lace co#%letely di""erent "ro# where you


return "or a nor#al #ethod call. */ou end u% in an a%%ro%riate e&ce%tion handler that #ight be #iles away9#any levels lower on the call stack9 "ro# where the e&ce%tion was thrown., RFSURF STIJLT+(6PTE5M@TIMLU In addition, you can throw any ty%e o" Thro(able ob0ect that you want. Ty%ically, you ll throw a di""erent class o" e&ce%tion "or each di""erent ty%e o" error. The in"or#ation about the error is re%resented both inside the e&ce%tion ob0ect and i#%licitly in the ty%e o" e&ce%tion ob0ect chosen, so so#eone in the bigger conte&t can "igure out what to do with your

554

Thinking in Java

,,,'0ruceEckel'com

e&ce%tion. *)"ten, the only in"or#ation is the ty%e o" e&ce%tion ob0ect, and nothing #eaning"ul is stored within the e&ce%tion ob0ect., RFSURF STIJLT+(6PTE5M@TIM?U

Catching an e0ce.tion
I" a #ethod throws an e&ce%tion, it #ust assu#e that e&ce%tion is !caught$ and dealt with. )ne o" the advantages o" Java e&ce%tion handling is that it allows you to concentrate on the %roble# you re trying to solve in one %lace, and then deal with the errors "ro# that code in another %lace. RFSURFSTIJLT+(6PTE5M@TIMHU To see how an e&ce%tion is caught, you #ust "irst understand the conce%t o" a guarded regionD which is a section o" code that #ight %roduce e&ce%tions, and which is "ollowed by the code to handle those e&ce%tions. RFSURFSTIJLT+(6PTE5M@TIM3U

#he try block


I" you re inside a #ethod and you throw an e&ce%tion *or another #ethod you call within this #ethod throws an e&ce%tion,, that #ethod will e&it in the %rocess o" throwing. I" you don t want a thro( to e&it the #ethod, you can set u% a s%ecial block within that #ethod to ca%ture the e&ce%tion. This is called the tr) block because you !try$ your various #ethod calls there. The try block is an ordinary sco%e, %receded by the keyword try=

try @ // Co!e that #ight generate e6ce"tions A


I" you were checking "or errors care"ully in a %rogra##ing language that didn t su%%ort e&ce%tion handling, you d have to surround every #ethod call with setu% and error testing code, even i" you call the sa#e #ethod several ti#es. :ith e&ce%tion handling, you %ut everything in a try block and ca%ture all the e&ce%tions in one %lace. This #eans your code is a lot easier to write and easier to read because the goal o" the code is not con"used with the error checking. RFSURFSTIJLT+(6PTE5M@TIMGU

555

/0ce.tion handlers
)" course, the thrown e&ce%tion #ust end u% so#e%lace. This !%lace$ is the e*ce tion handlerD and there s one "or every e&ce%tion ty%e you want to catch. E&ce%tion handlers i##ediately "ollow the try block and are denoted by the keyword catch=

try @ // Co!e that #ight generate e6ce"tions A catch-Ty"e( i!(. @ // Man!le e6ce"tions of Ty"e( A catch-Ty"e i! . @ // Man!le e6ce"tions of Ty"e A catch-Ty"e) i!). @ // Man!le e6ce"tions of Ty"e) A // etc...
Each catch clause *e&ce%tion handler, is like a little #ethod that takes one and only one argu#ent o" a %articular ty%e. The identi"ier * i'>, i'I, and so on, can be used inside the handler, 0ust like a #ethod argu#ent. So#eti#es you never use the identi"ier because the ty%e o" the e&ce%tion gives you enough in"or#ation to deal with the e&ce%tion, but the identi"ier #ust still be there. RFSURFSTIJLT+(6PTE5M@TIMIU The handlers #ust a%%ear directly a"ter the try block. I" an e&ce%tion is thrown, the e&ce%tion handling #echanis# goes hunting "or the "irst handler with an argu#ent that #atches the ty%e o" the e&ce%tion. Then it enters that catch clause, and the e&ce%tion is considered handled. The search "or handlers sto%s once the catch clause is "inished. )nly the #atching catch clause e&ecutes; it s not like a s(itch state#ent in which you need a break a"ter each case to %revent the re#aining ones "ro# e&ecuting. RFSURFSTIJLT+(6PTE5M@TIM2U Cote that, within the try block, a nu#ber o" di""erent #ethod calls #ight generate the sa#e e&ce%tion, but you need only one handler. RFSURF STIJLT+(6PTE5M@TIK@U

557

Thinking in Java

,,,'0ruceEckel'com

#ermination vs) resum.tion


There are two basic #odels in e&ce%tion handling theory. In termination *which is what Java and +<< su%%ort,, you assu#e the error is so critical that there s no way to get back to where the e&ce%tion occurred. :hoever threw the e&ce%tion decided that there was no way to salvage the situation, and they don t ,ant to co#e back. RFSURF STIJLT+(6PTE5M@TIKMU The alternative is called resum tion. It #eans that the e&ce%tion handler is e&%ected to do so#ething to recti"y the situation, and then the "aulting #ethod is retried, %resu#ing success the second ti#e. I" you want resu#%tion, it #eans you still ho%e to continue e&ecution a"ter the e&ce%tion is handled. In this case, your e&ce%tion is #ore like a #ethod call9which is how you should set u% situations in Java in which you want resu#%tion'like behavior. *That is, don t throw an e&ce%tion; call a #ethod that "i&es the %roble#., 6lternatively, %lace your try block inside a (hile loo% that kee%s reentering the try block until the result is satis"actory. RFSURFSTIJLT+(6PTE5M@TIKKU (istorically, %rogra##ers using o%erating syste#s that su%%orted resu#%tive e&ce%tion handling eventually ended u% using ter#ination' like code and ski%%ing resu#%tion. So although resu#%tion sounds attractive at "irst, it isn t Auite so use"ul in %ractice. The do#inant reason is %robably the cou ling that results= your handler #ust o"ten be aware o" where the e&ce%tion is thrown "ro# and contain nongeneric code s%eci"ic to the throwing location. This #akes the code di""icult to write and #aintain, es%ecially "or large syste#s where the e&ce%tion can be generated "ro# #any %oints. RFSURFSTIJLT+(6PTE5M@TIKLU

Creating :our own e0ce.tions


/ou re not stuck using the e&isting Java e&ce%tions. This is i#%ortant because you ll o"ten need to create your own e&ce%tions to denote a s%ecial error that your library is ca%able o" creating, but which was not

558

"oreseen when the Java e&ce%tion hierarchy was created. RFSURF STIJLT+(6PTE5M@TIK?U To create your own e&ce%tion class, you re "orced to inherit "ro# an e&isting ty%e o" e&ce%tion, %re"erably one that is close in #eaning to your new e&ce%tion *this is o"ten not %ossible, however,. The #ost trivial way to create a new ty%e o" e&ce%tion is 0ust to let the co#%iler create the de"ault constructor "or you, so it reAuires al#ost no code at all=

//3 c('3%i#"leE6ce"tionDe#o.Hava // $nheriting your o:n e6ce"tions. class %i#"leE6ce"tion e6ten!s E6ce"tion @A "ublic class %i#"leE6ce"tionDe#o @ "ublic voi! f-. thro:s %i#"leE6ce"tion @ %yste#.out."rintln8Thro:ing %i#"leE6ce"tion fro# f-.8.< thro: ne: %i#"leE6ce"tion -.< A "ublic static voi! #ain-%tringNO args. @ %i#"leE6ce"tionDe#o se! ? ne: %i#"leE6ce"tionDe#o-.< try @ se!.f-.< A catch-%i#"leE6ce"tion e. @ %yste#.err."rintln-8Caught it48.< A A A ///3>
:hen the co#%iler creates the de"ault constructor, it which auto#atically *and invisibly, calls the base'class de"ault constructor. )" course, in this case you don t get a )imple&4ceptionA)tringB constructor, but in %ractice that isn t used #uch. 6s you ll see, the #ost i#%ortant thing about an e&ce%tion is the class na#e, so #ost o" the ti#e an e&ce%tion like the one shown above is satis"actory. RFSURFSTIJLT+(6PTE5M@TIKHU (ere, the result is %rinted to the console standard error strea# by writing to )ystem!err. This is usually a better %lace to send error in"or#ation than )ystem!o*t, which #ay be redirected. I" you send

55:

Thinking in Java

,,,'0ruceEckel'com

out%ut to )ystem!err it will not be redirected along with )ystem!o*t so the user is #ore likely to notice it. RFSURFSTIJLT+(6PTE5M@TIK3U +reating an e&ce%tion class that also has a constructor that takes a )tring is also Auite si#%le=

//3 c('3LullConstructors.Hava // $nheriting your o:n e6ce"tions. class JyE6ce"tion e6ten!s E6ce"tion @ "ublic JyE6ce"tion-. @A "ublic JyE6ce"tion-%tring #sg. @ su"er-#sg.< A A "ublic class LullConstructors @ "ublic static voi! f-. thro:s JyE6ce"tion @ %yste#.out."rintln8Thro:ing JyE6ce"tion fro# f-.8.< thro: ne: JyE6ce"tion-.< A "ublic static voi! g-. thro:s JyE6ce"tion @ %yste#.out."rintln8Thro:ing JyE6ce"tion fro# g-.8.< thro: ne: JyE6ce"tion-8Griginate! in g-.8.< A "ublic static voi! #ain-%tringNO args. @ try @ f-.< A catch-JyE6ce"tion e. @ e."rint%tackTrace-%yste#.err.< A try @ g-.< A catch-JyE6ce"tion e. @ e."rint%tackTrace-%yste#.err.< A A A ///3>

55;

The added code is s#all9the addition o" two constructors that de"ine the way 1y&4ception is created. In the second constructor, the base'class constructor with a )tring argu#ent is e&%licitly invoked by using the s*per keyword. RFSURFSTIJLT+(6PTE5M@TIKGU The stack trace in"or#ation is sent to )ystem!err so that it s #ore likely it will be noticed in the event that )ystem!o*t has been redirected. RF SURFSTIJLT+(6PTE5M@TIKIU The out%ut o" the %rogra# is=
Thro:ing JyE6ce"tion fro# f-. JyE6ce"tion at LullConstructors.f-LullConstructors.Hava3(+. at LullConstructors.#ain-LullConstructors.Hava3 I. Thro:ing JyE6ce"tion fro# g-. JyE6ce"tion3 Griginate! in g-. at LullConstructors.g-LullConstructors.Hava3 '. at LullConstructors.#ain-LullConstructors.Hava3 C.

/ou can see the absence o" the detail #essage in the 1y&4ception thrown "ro# fA B. RFSURFSTIJLT+(6PTE5M@TIK2U The %rocess o" creating your own e&ce%tions can be taken "urther. /ou can add e&tra constructors and #e#bers=

//3 c('3E6traLeatures.Hava // Lurther e#bellish#ent of e6ce"tion classes. class JyE6ce"tion e6ten!s E6ce"tion @ "ublic JyE6ce"tion -. @A "ublic JyE6ce"tion -%tring #sg. @ su"er-#sg.< A "ublic JyE6ce"tion -%tring #sg, int 6. @ su"er-#sg.< i ? 6< A "ublic int val-. @ return i< A "rivate int i< A

57=

Thinking in Java

,,,'0ruceEckel'com

"ublic class E6traLeatures @ "ublic static voi! f-. thro:s JyE6ce"tion @ %yste#.out."rintln8Thro:ing JyE6ce"tion fro# f-.8.< thro: ne: JyE6ce"tion -.< A "ublic static voi! g-. thro:s JyE6ce"tion @ %yste#.out."rintln8Thro:ing JyE6ce"tion fro# g-.8.< thro: ne: JyE6ce"tion -8Griginate! in g-.8.< A "ublic static voi! h-. thro:s JyE6ce"tion @ %yste#.out."rintln8Thro:ing JyE6ce"tion fro# h-.8.< thro: ne: JyE6ce"tion 8Griginate! in h-.8, I*.< A "ublic static voi! #ain-%tringNO args. @ try @ f-.< A catch-JyE6ce"tion e. @ e."rint%tackTrace-%yste#.err.< A try @ g-.< A catch-JyE6ce"tion e. @ e."rint%tackTrace-%yste#.err.< A try @ h-.< A catch-JyE6ce"tion e. @ e."rint%tackTrace-%yste#.err.< %yste#.err."rintln-8e.val-. ? 8 K e.val-..< A A A ///3>
6 data #e#ber i has been added, along with a #ethod that reads that value and an additional constructor that sets it. The out%ut is= RFSURF STIJLT+(6PTE5M@TIL@U

571

Thro:ing JyE6ce"tion fro# f-. JyE6ce"tion at E6traLeatures.f-E6traLeatures.Hava3 . at E6traLeatures.#ain-E6traLeatures.Hava3)I. Thro:ing JyE6ce"tion fro# g-. JyE6ce"tion 3 Griginate! in g-. at E6traLeatures.g-E6traLeatures.Hava3 +. at E6traLeatures.#ain-E6traLeatures.Hava3)C. Thro:ing JyE6ce"tion fro# h-. JyE6ce"tion 3 Griginate! in h-. at E6traLeatures.h-E6traLeatures.Hava3)'. at E6traLeatures.#ain-E6traLeatures.Hava3II. e.val-. ? I*
Since an e&ce%tion is 0ust another kind o" ob0ect, you can continue this %rocess o" e#bellishing the %ower o" your e&ce%tion classes. >ee% in #ind, however, that all this dressing'u% #ight be lost on the client %rogra##ers using your %ackages, since they #ight si#%ly look "or the e&ce%tion to be thrown and nothing #ore. *That s the way #ost o" the Java library e&ce%tions are used., RFSURFSTIJLT+(6PTE5M@TILMU

#he e0ce.tion s.ecification


In Java, you re reAuired to in"or# the client %rogra##er, who calls your #ethod, o" the e&ce%tions that #ight be thrown "ro# your #ethod. This is civili1ed, because the caller can know e&actly what code to write to catch all %otential e&ce%tions. )" course, i" source code is available, the client %rogra##er could hunt through and look "or thro( state#ents, but o"ten a library doesn t co#e with sources. To %revent this "ro# being a %roble#, Java %rovides synta& *and $orces you to use that synta&, to allow you to %olitely tell the client %rogra##er what e&ce%tions this #ethod throws, so the client %rogra##er can handle the#. This is the e*ce tion s eci$icationD and it s %art o" the #ethod declaration, a%%earing a"ter the argu#ent list. RFSURFSTIJLT+(6PTE5M@TILKU

572

Thinking in Java

,,,'0ruceEckel'com

The e&ce%tion s%eci"ication uses an additional keyword, thro(s, "ollowed by a list o" all the %otential e&ce%tion ty%es. So your #ethod de"inition #ight look like this=

voi! f-. thro:s TooBig, Too%#all, DivTero @ //...


I" you say

voi! f-. @ // ...


it #eans that no e&ce%tions are thrown "ro# the #ethod. * E*ce t "or the e&ce%tions o" ty%e $*ntime&4ception, which can reasonably be thrown anywhere9this will be described later., RFSURF STIJLT+(6PTE5M@TILLU /ou can t lie about an e&ce%tion s%eci"ication9i" your #ethod causes e&ce%tions and doesn t handle the#, the co#%iler will detect this and tell you that you #ust either handle the e&ce%tion or indicate with an e&ce%tion s%eci"ication that it #ay be thrown "ro# your #ethod. By en"orcing e&ce%tion s%eci"ications "ro# to% to botto#, Java guarantees that e&ce%tion correctness can be ensured at com ile/time@. RFSURF STIJLT+(6PTE5M@TIL?U There is one %lace you can lie= you can clai# to throw an e&ce%tion that you really don t. The co#%iler takes your word "or it, and "orces the users o" your #ethod to treat it as i" it really does throw that e&ce%tion. This has the bene"icial e""ect o" being a %laceholder "or that e&ce%tion, so you can actually start throwing the e&ce%tion later without reAuiring changes to e&isting code. It s also i#%ortant "or creating abstract base classes and interfaces whose derived classes or i#%le#entations #ay need to throw e&ce%tions. RFSURFSTIJLT+(6PTE5M@TILHU

Catching an: e0ce.tion


It is %ossible to create a handler that catches any ty%e o" e&ce%tion. /ou do this by catching the base'class e&ce%tion ty%e &4ception *there are other ty%es o" base e&ce%tions, but &4ception is the base that s %ertinent to virtually all %rogra##ing activities,=
@ This is a signi"icant i#%rove#ent over +<< e&ce%tion handling, which doesn t catch violations o" e&ce%tion s%eci"ications until run ti#e, when it s not very use"ul.

573

catch-E6ce"tion e. @ %yste#.err."rintln-8Caught an e6ce"tion8.< A


This will catch any e&ce%tion, so i" you use it you ll want to %ut it at the end o" your list o" handlers to avoid %ree#%ting any e&ce%tion handlers that #ight otherwise "ollow it. RFSURFSTIJLT+(6PTE5M@TIL3U Since the &4ception class is the base o" all the e&ce%tion classes that are i#%ortant to the %rogra##er, you don t get #uch s%eci"ic in"or#ation about the e&ce%tion, but you can call the #ethods that co#e "ro# its base ty%e Thro(able=

)tring get1essageA B )tring get+ocali7e'1essageA B


8ets the detail #essage, or a #essage ad0usted "or this %articular locale. RFSURFSTIJLT+(6PTE5M@TILGU

)tring to)tringA B
5eturns a short descri%tion o" the Throwable, including the detail #essage i" there is one. RFSURFSTIJLT+(6PTE5M@TILIU

voi' print)tackTraceA B voi' print)tackTraceA#rint)treamB voi' print)tackTraceA#rint0riterB


Prints the Throwable and the Throwable s call stack trace. The call stack shows the seAuence o" #ethod calls that brought you to the %oint at which the e&ce%tion was thrown. The "irst version %rints to standard error, the second and third %rints to a strea# o" your choice *in +ha%ter MM, you ll understand why there are two ty%es o" strea#s,. RFSURF STIJLT+(6PTE5M@TIL2U

Thro(able fillIn)tackTraceA B
5ecords in"or#ation within this Thro(able ob0ect about the current state o" the stack "ra#es. 4se"ul when an a%%lication is rethrowing an error or e&ce%tion *#ore about this shortly,. RFSURF STIJLT+(6PTE5M@TI?@U In addition, you get so#e other #ethods "ro# Thro(able s base ty%e .b8ect *everybody s base ty%e,. The one that #ight co#e in handy "or e&ce%tions is get-lassA B, which returns an ob0ect re%resenting the class

574

Thinking in Java

,,,'0ruceEckel'com

o" this ob0ect. /ou can in turn Auery this -lass ob0ect "or its na#e with get/ameA B or to)tringA B. /ou can also do #ore so%histicated things with -lass ob0ects that aren t necessary in e&ce%tion handling. -lass ob0ects will be studied later in this book. RFSURF STIJLT+(6PTE5M@TI?MU (ere s an e&a#%le that shows the use o" the basic &4ception #ethods=

//3 c('3E6ce"tionJetho!s.Hava // De#onstrating the E6ce"tion Jetho!s. "ublic class E6ce"tionJetho!s @ "ublic static voi! #ain-%tringNO args. @ try @ thro: ne: E6ce"tion-8Mere2s #y E6ce"tion8.< A catch-E6ce"tion e. @ %yste#.err."rintln-8Caught E6ce"tion8.< %yste#.err."rintln8e.getJessage-.3 8 K e.getJessage-..< %yste#.err."rintln8e.getLocaliUe!Jessage-.3 8 K e.getLocaliUe!Jessage-..< %yste#.err."rintln-8e.to%tring-.3 8 K e.< %yste#.err."rintln-8e."rint%tackTrace-.38.< e."rint%tackTrace-%yste#.err.< A A A ///3>
The out%ut "or this %rogra# is=

Caught E6ce"tion e.getJessage-.3 Mere2s #y E6ce"tion e.getLocaliUe!Jessage-.3 Mere2s #y E6ce"tion e.to%tring-.3 Hava.lang.E6ce"tion3 Mere2s #y E6ce"tion e."rint%tackTrace-.3 Hava.lang.E6ce"tion3 Mere2s #y E6ce"tion at E6ce"tionJetho!s.#ain-E6ce"tionJetho!s.Hava3*. Hava.lang.E6ce"tion3 Mere2s #y E6ce"tion at E6ce"tionJetho!s.#ain-E6ce"tionJetho!s.Hava3*.

575

/ou can see that the #ethods %rovide successively #ore in"or#ation9 each is e""ectively a su%erset o" the %revious one. RFSURF STIJLT+(6PTE5M@TI?KU

$ethrowing an e0ce.tion
So#eti#es you ll want to rethrow the e&ce%tion that you 0ust caught, %articularly when you use &4ception to catch any e&ce%tion. Since you already have the re"erence to the current e&ce%tion, you can si#%ly rethrow that re"erence=

catch-E6ce"tion e. @ %yste#.err."rintln-80n e6ce"tion :as thro:n8.< thro: e< A


5ethrowing an e&ce%tion causes the e&ce%tion to go to the e&ce%tion handlers in the ne&t'higher conte&t. 6ny "urther catch clauses "or the sa#e try block are still ignored. In addition, everything about the e&ce%tion ob0ect is %reserved, so the handler at the higher conte&t that catches the s%eci"ic e&ce%tion ty%e can e&tract all the in"or#ation "ro# that ob0ect. RFSURFSTIJLT+(6PTE5M@TI?LU I" you si#%ly rethrow the current e&ce%tion, the in"or#ation that you %rint about that e&ce%tion in print)tackTraceA B will %ertain to the e&ce%tion s origin, not the %lace where you rethrow it. I" you want to install new stack trace in"or#ation, you can do so by calling fillIn)tackTraceA B, which returns an e&ce%tion ob0ect that it creates by stu""ing the current stack in"or#ation into the old e&ce%tion ob0ect. (ere s what it looks like=

//3 c('35ethro:ing.Hava // De#onstrating fill$n%tackTrace-. "ublic class 5ethro:ing @ "ublic static voi! f-. thro:s E6ce"tion @ %yste#.out."rintln8originating the e6ce"tion in f-.8.< thro: ne: E6ce"tion-8thro:n fro# f-.8.< A

577

Thinking in Java

,,,'0ruceEckel'com

"ublic static voi! g-. thro:s Thro:able @ try @ f-.< A catch-E6ce"tion e. @ %yste#.err."rintln8$nsi!e g-., e."rint%tackTrace-.8.< e."rint%tackTrace-%yste#.err.< thro: e< // (* // thro: e.fill$n%tackTrace-.< // (1 A A "ublic static voi! #ain-%tringNO args. thro:s Thro:able @ try @ g-.< A catch-E6ce"tion e. @ %yste#.err."rintln8Caught in #ain, e."rint%tackTrace-.8.< e."rint%tackTrace-%yste#.err.< A A A ///3>
The i#%ortant line nu#bers are #arked as co##ents. :ith line MG unco##ented *as shown,, the out%ut is=

originating the e6ce"tion in f-. $nsi!e g-., e."rint%tackTrace-. Hava.lang.E6ce"tion3 thro:n fro# f-. at 5ethro:ing.f-5ethro:ing.Hava31. at 5ethro:ing.g-5ethro:ing.Hava3( . at 5ethro:ing.#ain-5ethro:ing.Hava3 I. Caught in #ain, e."rint%tackTrace-. Hava.lang.E6ce"tion3 thro:n fro# f-. at 5ethro:ing.f-5ethro:ing.Hava31. at 5ethro:ing.g-5ethro:ing.Hava3( . at 5ethro:ing.#ain-5ethro:ing.Hava3 I.
So the e&ce%tion stack trace always re#e#bers its true %oint o" origin, no #atter how #any ti#es it gets rethrown. RFSURF STIJLT+(6PTE5M@TI??U

578

:ith line MG co##ented and line MI unco##ented, fillIn)tackTraceA B is used instead, and the result is=

originating the e6ce"tion in f-. $nsi!e g-., e."rint%tackTrace-. Hava.lang.E6ce"tion3 thro:n fro# f-. at 5ethro:ing.f-5ethro:ing.Hava31. at 5ethro:ing.g-5ethro:ing.Hava3( . at 5ethro:ing.#ain-5ethro:ing.Hava3 I. Caught in #ain, e."rint%tackTrace-. Hava.lang.E6ce"tion3 thro:n fro# f-. at 5ethro:ing.g-5ethro:ing.Hava3(1. at 5ethro:ing.#ain-5ethro:ing.Hava3 I.
Because o" fillIn)tackTraceA B, line MI beco#es the new %oint o" origin o" the e&ce%tion. RFSURFSTIJLT+(6PTE5M@TI?HU The class Thro(able #ust a%%ear in the e&ce%tion s%eci"ication "or gA B and mainA B because fillIn)tackTraceA B %roduces a re"erence to a Thro(able ob0ect. Since Thro(able is a base class o" &4ception, it s %ossible to get an ob0ect that s a Thro(able but not an &4ception, so the handler "or &4ception in mainA B #ight #iss it. To #ake sure everything is in order, the co#%iler "orces an e&ce%tion s%eci"ication "or Thro(able. Eor e&a#%le, the e&ce%tion in the "ollowing %rogra# is not caught in mainA B= RFSURFSTIJLT+(6PTE5M@TI?3U

//3 c('3Thro:Gut.Hava "ublic class Thro:Gut @ "ublic static voi! #ain-%tringNO args. thro:s Thro:able @ try @ thro: ne: Thro:able-.< A catch-E6ce"tion e. @ %yste#.err."rintln-8Caught in #ain-.8.< A A A ///3>
It s also %ossible to rethrow a di""erent e&ce%tion "ro# the one you caught. I" you do this, you get a si#ilar e""ect as when you use fillIn)tackTraceA B9the in"or#ation about the original site o" the

57:

Thinking in Java

,,,'0ruceEckel'com

e&ce%tion is lost, and what you re le"t with is the in"or#ation %ertaining to the new thro(= RFSURFSTIJLT+(6PTE5M@TI?GU

//3 c('35ethro:&e:.Hava // 5ethro: a !ifferent obHect // fro# the one that :as caught. class GneE6ce"tion e6ten!s E6ce"tion @ "ublic GneE6ce"tion-%tring s. @ su"er-s.< A A class T:oE6ce"tion e6ten!s E6ce"tion @ "ublic T:oE6ce"tion-%tring s. @ su"er-s.< A A "ublic class 5ethro:&e: @ "ublic static voi! f-. thro:s GneE6ce"tion @ %yste#.out."rintln8originating the e6ce"tion in f-.8.< thro: ne: GneE6ce"tion-8thro:n fro# f-.8.< A "ublic static voi! #ain-%tringNO args. thro:s T:oE6ce"tion @ try @ f-.< A catch-GneE6ce"tion e. @ %yste#.err."rintln8Caught in #ain, e."rint%tackTrace-.8.< e."rint%tackTrace-%yste#.err.< thro: ne: T:oE6ce"tion-8fro# #ain-.8.< A A A ///3>
The out%ut is=

originating the e6ce"tion in f-. Caught in #ain, e."rint%tackTrace-. GneE6ce"tion3 thro:n fro# f-. at 5ethro:&e:.f-5ethro:&e:.Hava3(*. at 5ethro:&e:.#ain-5ethro:&e:.Hava3 . E6ce"tion in threa! 8#ain8 T:oE6ce"tion3 fro# #ain-.

57;

at 5ethro:&e:.#ain-5ethro:&e:.Hava3 *.
The "inal e&ce%tion knows only that it ca#e "ro# mainA B, and not "ro# f

A B. RFSURFSTIJLT+(6PTE5M@TI?IU
/ou never have to worry about cleaning u% the %revious e&ce%tion, or any e&ce%tions "or that #atter. They re all hea%'based ob0ects created with ne(, so the garbage collector auto#atically cleans the# all u%. RFSURF STIJLT+(6PTE5M@TI?2U

1tandard "ava e0ce.tions


The Java class Thro(able describes anything that can be thrown as an e&ce%tion. There are two general ty%es o" Thro(able ob0ects *!ty%es o"$ \ !inherited "ro#$,. &rror re%resents co#%ile'ti#e and syste# errors that you don t worry about catching *e&ce%t in s%ecial cases,. &4ception is the basic ty%e that can be thrown "ro# any o" the standard Java library class #ethods and "ro# your #ethods and run'ti#e accidents. So the Java %rogra##er s base ty%e o" interest is &4ception. RFSURF STIJLT+(6PTE5M@TIH@U The best way to get an overview o" the e&ce%tions is to browse the (TMD Java docu#entation that you can download "ro# >ava'sun'com' It s worth doing this once 0ust to get a "eel "or the various e&ce%tions, but you ll soon see that there isn t anything s%ecial between one e&ce%tion and the ne&t e&ce%t "or the na#e. 6lso, the nu#ber o" e&ce%tions in Java kee%s e&%anding; basically it s %ointless to %rint the# in a book. 6ny new library you get "ro# a third'%arty vendor will %robably have its own e&ce%tions as well. The i#%ortant thing to understand is the conce%t and what you should do with the e&ce%tions. RFSURF STIJLT+(6PTE5M@TIHMU The basic idea is that the na#e o" the e&ce%tion re%resents the %roble# that occurred, and the e&ce%tion na#e is intended to be relatively sel"' e&%lanatory. The e&ce%tions are not all de"ined in 8ava!lang; so#e are created to su%%ort other libraries such as *til, net, and io, which you can

58=

Thinking in Java

,,,'0ruceEckel'com

see "ro# their "ull class na#es or what they are inherited "ro#. Eor e&a#%le, all IF) e&ce%tions are inherited "ro# 8ava!io!I.&4ception. RF SURFSTIJLT+(6PTE5M@TIHKU

#he s.ecial case of 5untimeE-ce tion


The "irst e&a#%le in this cha%ter was

if-t ?? null. thro: ne: &ullPointerE6ce"tion-.<


It can be a bit horri"ying to think that you #ust check "or n*ll on every re"erence that is %assed into a #ethod *since you can t know i" the caller has %assed you a valid re"erence,. Eortunately, you don t9this is %art o" the standard run'ti#e checking that Java %er"or#s "or you, and i" any call is #ade to a n*ll re"erence, Java will auto#atically throw a /*ll#ointer&4ception. So the above bit o" code is always su%er"luous. RFSURFSTIJLT+(6PTE5M@TIHLU There s a whole grou% o" e&ce%tion ty%es that are in this category. They re always thrown auto#atically by Java and you don t need to include the# in your e&ce%tion s%eci"ications. +onveniently enough, they re all grou%ed together by %utting the# under a single base class called $*ntime&4ception, which is a %er"ect e&a#%le o" inheritance= it establishes a "a#ily o" ty%es that have so#e characteristics and behaviors in co##on. 6lso, you never need to write an e&ce%tion s%eci"ication saying that a #ethod #ight throw a $*ntime&4ception, since that s 0ust assu#ed. Because they indicate bugs, you virtually never catch a $*ntime&4ception9it s dealt with auto#atically. I" you were "orced to check "or $*ntime&4ceptions your code could get #essy. Even though you don t ty%ically catch $*ntime&4ceptions, in your own %ackages you #ight choose to throw so#e o" the $*ntime&4ceptions. RFSURF STIJLT+(6PTE5M@TIH?U :hat ha%%ens when you don t catch such e&ce%tionsO Since the co#%iler doesn t en"orce e&ce%tion s%eci"ications "or these, it s Auite %lausible that a $*ntime&4ception could %ercolate all the way out to your mainA B

581

#ethod without being caught. To see what ha%%ens in this case, try the "ollowing e&a#%le=

//3 c('3&everCaught.Hava // $gnoring 5unti#eE6ce"tions. "ublic class &everCaught @ static voi! f-. @ thro: ne: 5unti#eE6ce"tion-8Lro# f-.8.< A static voi! g-. @ f-.< A "ublic static voi! #ain-%tringNO args. @ g-.< A A ///3>
/ou can already see that a $*ntime&4ception *or anything inherited "ro# it, is a s%ecial case, since the co#%iler doesn t reAuire an e&ce%tion s%eci"ication "or these ty%es. RFSURFSTIJLT+(6PTE5M@TIHHU The out%ut is=

E6ce"tion in threa! 8#ain8 Hava.lang.5unti#eE6ce"tion3 Lro# f-. at &everCaught.f-&everCaught.Hava3C. at &everCaught.g-&everCaught.Hava3( . at &everCaught.#ain-&everCaught.Hava3(,.


So the answer is= I" a $*ntime&4ception gets all the way out to main A B without being caught, print)tackTraceA B is called "or that e&ce%tion as the %rogra# e&its. RFSURFSTIJLT+(6PTE5M@TIH3U >ee% in #ind that you can only ignore $*ntime&4ceptions in your coding, since all other handling is care"ully en"orced by the co#%iler. The reasoning is that a $*ntime&4ception re%resents a %rogra##ing error=

6()

6n error you cannot catch *receiving a n*ll re"erence handed to your #ethod by a client %rogra##er, "or e&a#%le, . RFSURF STIJLT+(6PTE5M@TIHGU

582

Thinking in Java

,,,'0ruceEckel'com

6!)

6n error that you, as a %rogra##er, should have checked "or in your code *such as ArrayIn'e4.*t.f2o*n's&4ception where you should have %aid attention to the si1e o" the array,. RFSURF STIJLT+(6PTE5M@TIHIU

/ou can see what a tre#endous bene"it it is to have e&ce%tions in this case, since they hel% in the debugging %rocess. RFSURF STIJLT+(6PTE5M@TIH2U It s interesting to notice that you cannot classi"y Java e&ce%tion handling as a single'%ur%ose tool. /es, it is designed to handle those %esky run' ti#e errors that will occur because o" "orces outside your code s control, but it s also essential "or certain ty%es o" %rogra##ing bugs that the co#%iler cannot detect. RFSURFSTIJLT+(6PTE5M@TI3@U

erforming cleanu. with finall:


There s o"ten so#e %iece o" code that you want to e&ecute whether or not an e&ce%tion is thrown within a try block. This usually %ertains to so#e o%eration other than #e#ory recovery *since that s taken care o" by the garbage collector,. To achieve this e""ect, you use a finally clause@ at the end o" all the e&ce%tion handlers. The "ull %icture o" an e&ce%tion handling section is thus=

try @ // The guar!e! region3 Dangerous activities // that #ight thro: 0, B, or C A catch-0 a(. @ // Man!ler for situation 0 A catch-B b(. @ // Man!ler for situation B A catch-C c(. @ // Man!ler for situation C A finally @ // 0ctivities that ha""en every ti#e
@ +<< e&ce%tion handling does not have the finally clause because it relies on destructors to acco#%lish this sort o" cleanu%.

583

A
To de#onstrate that the finally clause always runs, try this %rogra#= RF SURFSTIJLT+(6PTE5M@TI3MU

//3 c('3Linally\orks.Hava // The finally clause is al:ays e6ecute!. class ThreeE6ce"tion e6ten!s E6ce"tion @A "ublic class Linally\orks @ static int count ? '< "ublic static voi! #ain-%tringNO args. @ :hile-true. @ try @ // Post-incre#ent is Uero first ti#e3 if-countKK ?? '. thro: ne: ThreeE6ce"tion-.< %yste#.out."rintln-8&o e6ce"tion8.< A catch-ThreeE6ce"tion e. @ %yste#.err."rintln-8ThreeE6ce"tion8.< A finally @ %yste#.err."rintln-8$n finally clause8.< if-count ?? . break< // out of 8:hile8 A A A A ///3>
This %rogra# also gives a hint "or how you can deal with the "act that e&ce%tions in Java *like e&ce%tions in +<<, do not allow you to resu#e back to where the e&ce%tion was thrown, as discussed earlier. I" you %lace your try block in a loo%, you can establish a condition that #ust be #et be"ore you continue the %rogra#. /ou can also add a static counter or so#e other device to allow the loo% to try several di""erent a%%roaches be"ore giving u%. This way you can build a greater level o" robustness into your %rogra#s. RFSURFSTIJLT+(6PTE5M@TI3KU The out%ut is=

ThreeE6ce"tion $n finally clause

584

Thinking in Java

,,,'0ruceEckel'com

&o e6ce"tion $n finally clause


:hether an e&ce%tion is thrown or not, the finally clause is always e&ecuted. RFSURFSTIJLT+(6PTE5M@TI3LU

Whats !inally forA


In a language without garbage collection and without auto#atic destructor calls @, finally is i#%ortant because it allows the %rogra##er to guarantee the release o" #e#ory regardless o" what ha%%ens in the try block. But Java has garbage collection, so releasing #e#ory is virtually never a %roble#. 6lso, it has no destructors to call. So when do you need to use finally in JavaO RFSURFSTIJLT+(6PTE5M@TI3?U

finally is necessary when you need to set so#ething other than #e#ory back to its original state. This is so#e kind o" cleanu% like an o%en "ile or network connection, so#ething you ve drawn on the screen, or even a switch in the outside world, as #odeled in the "ollowing e&a#%le= //3 c('3GnGff%:itch.Hava // \hy use finally[ class %:itch @ boolean state ? false< boolean rea!-. @ return state< A voi! on-. @ state ? true< A voi! off-. @ state ? false< A A class GnGffE6ce"tion( e6ten!s E6ce"tion @A class GnGffE6ce"tion e6ten!s E6ce"tion @A "ublic class GnGff%:itch @ static %:itch s: ? ne: %:itch-.< static voi! f-. thro:s GnGffE6ce"tion(, GnGffE6ce"tion @A "ublic static voi! #ain-%tringNO args. @
@ 6 destructor is a "unction that s always called when an ob0ect beco#es unused. /ou

always know e&actly where and when the destructor gets called. +<< has auto#atic destructor calls, but 7el%hi s )b0ect Pascal versions M and K do not *which changes the #eaning and use o" the conce%t o" a destructor "or that language,.

585

try @ s:.on-.< // Co!e that can thro: e6ce"tions... f-.< s:.off-.< A catch-GnGffE6ce"tion( e. @ %yste#.err."rintln-8GnGffE6ce"tion(8.< s:.off-.< A catch-GnGffE6ce"tion e. @ %yste#.err."rintln-8GnGffE6ce"tion 8.< s:.off-.< A A A ///3>
The goal here is to #ake sure that the switch is o"" when mainA B is co#%leted, so s(!offA B is %laced at the end o" the try block and at the end o" each e&ce%tion handler. But it s %ossible that an e&ce%tion could be thrown that isn t caught here, so s(!offA B would be #issed. (owever, with finally you can %lace the cleanu% code "ro# a try block in 0ust one %lace= RFSURFSTIJLT+(6PTE5M@TI3HU

//3 c('3\ithLinally.Hava // Linally auarantees cleanu". "ublic class \ithLinally @ static %:itch s: ? ne: %:itch-.< "ublic static voi! #ain-%tringNO args. @ try @ s:.on-.< // Co!e that can thro: e6ce"tions... GnGff%:itch.f-.< A catch-GnGffE6ce"tion( e. @ %yste#.err."rintln-8GnGffE6ce"tion(8.< A catch-GnGffE6ce"tion e. @ %yste#.err."rintln-8GnGffE6ce"tion 8.< A finally @ s:.off-.< A A A ///3>

587

Thinking in Java

,,,'0ruceEckel'com

(ere the s(!offA B has been #oved to 0ust one %lace, where it s guaranteed to run no #atter what ha%%ens. RFSURF STIJLT+(6PTE5M@TI33U Even in cases in which the e&ce%tion is not caught in the current set o" catch clauses, finally will be e&ecuted be"ore the e&ce%tion handling #echanis# continues its search "or a handler at the ne&t higher level=

//3 c('30l:aysLinally.Hava // Linally is al:ays e6ecute!. class LourE6ce"tion e6ten!s E6ce"tion @A "ublic class 0l:aysLinally @ "ublic static voi! #ain-%tringNO args. @ %yste#.out."rintln8Entering first try block8.< try @ %yste#.out."rintln8Entering secon! try block8.< try @ thro: ne: LourE6ce"tion-.< A finally @ %yste#.out."rintln8finally in n! try block8.< A A catch-LourE6ce"tion e. @ %yste#.err."rintln8Caught LourE6ce"tion in (st try block8.< A finally @ %yste#.err."rintln8finally in (st try block8.< A A A ///3>
The out%ut "or this %rogra# shows you what ha%%ens= RFSURF STIJLT+(6PTE5M@TI3GU

Entering first try block Entering secon! try block finally in n! try block

588

Caught LourE6ce"tion in (st try block finally in (st try block


The finally state#ent will also be e&ecuted in situations in which break and contin*e state#ents are involved. Cote that, along with the labeled break and labeled contin*e, finally eli#inates the need "or a goto state#ent in Java. RFSURFSTIJLT+(6PTE5M@TI3IU

itfall: the lost e0ce.tion


In general, Java s e&ce%tion i#%le#entation is Auite outstanding, but un"ortunately there s a "law. 6lthough e&ce%tions are an indication o" a crisis in your %rogra# and should never be ignored, it s %ossible "or an e&ce%tion to si#%ly be lost. This ha%%ens with a %articular con"iguration using a finally clause=

//3 c('3LostJessage.Hava // Mo: an e6ce"tion can be lost. class Wery$#"ortantE6ce"tion e6ten!s E6ce"tion @ "ublic %tring to%tring-. @ return 80 very i#"ortant e6ce"tion48< A A class MoMu#E6ce"tion e6ten!s E6ce"tion @ "ublic %tring to%tring-. @ return 80 trivial e6ce"tion8< A A "ublic class LostJessage @ voi! f-. thro:s Wery$#"ortantE6ce"tion @ thro: ne: Wery$#"ortantE6ce"tion-.< A voi! !is"ose-. thro:s MoMu#E6ce"tion @ thro: ne: MoMu#E6ce"tion-.< A "ublic static voi! #ain-%tringNO args. thro:s E6ce"tion @ LostJessage l# ? ne: LostJessage-.<

58:

Thinking in Java

,,,'0ruceEckel'com

try @ l#.f-.< A finally @ l#.!is"ose-.< A A A ///3>


The out%ut is=

E6ce"tion in threa! 8#ain8 0 trivial e6ce"tion at LostJessage.!is"ose-LostJessage.Hava3 (. at LostJessage.#ain-LostJessage.Hava3 C.


/ou can see that there s no evidence o" the VeryImportant&4ception, which is si#%ly re%laced by the HoH*m&4ception in the finally clause. This is a rather serious %it"all, since it #eans that an e&ce%tion can be co#%letely lost, and in a "ar #ore subtle and di""icult'to'detect "ashion than the e&a#%le above. In contrast, +<< treats the situation in which a second e&ce%tion is thrown be"ore the "irst one is handled as a dire %rogra##ing error. Perha%s a "uture version o" Java will re%air this %roble# *on the other hand, you will ty%ically wra% any #ethod that throws an e&ce%tion, such as 'isposeA B, inside a try6catch clause,. RF SURFSTIJLT+(6PTE5M@TI32U

/0ce.tion restrictions
:hen you override a #ethod, you can throw only the e&ce%tions that have been s%eci"ied in the base'class version o" the #ethod. This is a use"ul restriction, since it #eans that code that works with the base class will auto#atically work with any ob0ect derived "ro# the base class *a "unda#ental ))P conce%t, o" course,, including e&ce%tions. RFSURF STIJLT+(6PTE5M@TIG@U This e&a#%le de#onstrates the kinds o" restrictions i#%osed *at co#%ile' ti#e, "or e&ce%tions=

//3 c('3%tor#y$nning.Hava // Gverri!!en #etho!s #ay thro: only the // e6ce"tions s"ecifie! in their base-class

58;

// versions, or e6ce"tions !erive! fro# the // base-class e6ce"tions. class BaseballE6ce"tion e6ten!s E6ce"tion @A class Loul e6ten!s BaseballE6ce"tion @A class %trike e6ten!s BaseballE6ce"tion @A abstract class $nning @ $nning-. thro:s BaseballE6ce"tion @A voi! event -. thro:s BaseballE6ce"tion @ // Doesn2t actually have to thro: anything A abstract voi! atBat-. thro:s %trike, Loul< voi! :alk-. @A // Thro:s nothing A class %tor#E6ce"tion e6ten!s E6ce"tion @A class 5aine!Gut e6ten!s %tor#E6ce"tion @A class Po"Loul e6ten!s Loul @A interface %tor# @ voi! event-. thro:s 5aine!Gut< voi! rainMar!-. thro:s 5aine!Gut< A "ublic class %tor#y$nning e6ten!s $nning i#"le#ents %tor# @ // G` to a!! ne: e6ce"tions for // constructors, but you #ust !eal // :ith the base constructor e6ce"tions3 %tor#y$nning-. thro:s 5aine!Gut, BaseballE6ce"tion @A %tor#y$nning-%tring s. thro:s Loul, BaseballE6ce"tion @A // 5egular #etho!s #ust confor# to base class3 //4 voi! :alk-. thro:s Po"Loul @A //Co#"ile error // $nterface C0&&GT a!! e6ce"tions to e6isting // #etho!s fro# the base class3 //4 "ublic voi! event-. thro:s 5aine!Gut @A // $f the #etho! !oesn2t alrea!y e6ist in the // base class, the e6ce"tion is G`3

5:=

Thinking in Java

,,,'0ruceEckel'com

"ublic voi! rainMar!-. thro:s 5aine!Gut @A // ;ou can choose to not thro: any e6ce"tions, // even if base version !oes3 "ublic voi! event-. @A // Gverri!!en #etho!s can thro: // inherite! e6ce"tions3 voi! atBat-. thro:s Po"Loul @A "ublic static voi! #ain-%tringNO args. @ try @ %tor#y$nning si ? ne: %tor#y$nning-.< si.atBat-.< A catch-Po"Loul e. @ %yste#.err."rintln-8Po" foul8.< A catch-5aine!Gut e. @ %yste#.err."rintln-85aine! out8.< A catch-BaseballE6ce"tion e. @ %yste#.err."rintln-8aeneric error8.< A // %trike not thro:n in !erive! version. try @ // \hat ha""ens if you u"cast[ $nning i ? ne: %tor#y$nning-.< i.atBat-.< // ;ou #ust catch the e6ce"tions fro# the // base-class version of the #etho!3 A catch-%trike e. @ %yste#.err."rintln-8%trike8.< A catch-Loul e. @ %yste#.err."rintln-8Loul8.< A catch-5aine!Gut e. @ %yste#.err."rintln-85aine! out8.< A catch-BaseballE6ce"tion e. @ %yste#.err."rintln8aeneric baseball e6ce"tion8.< A A A ///3>
In Inning, you can see that both the constructor and the eventA B #ethod say they will throw an e&ce%tion, but they never do. This is legal because it allows you to "orce the user to catch any e&ce%tions that #ight

5:1

be added in overridden versions o" eventA B. The sa#e idea holds "or abstract #ethods, as seen in at2atA B. RFSURF STIJLT+(6PTE5M@TIGMU The interface )torm is interesting because it contains one #ethod * eventA B, that is de"ined in Inning, and one #ethod that isn t. Both #ethods throw a new ty%e o" e&ce%tion, $aine'.*t. :hen )tormyInning e4ten's Inning and implements )torm, you ll see that the eventA B #ethod in )torm cannot change the e&ce%tion inter"ace o" eventA B in Inning. 6gain, this #akes sense because otherwise you d never know i" you were catching the correct thing when working with the base class. )" course, i" a #ethod described in an interface is not in the base class, such as rainHar'A B, then there s no %roble# i" it throws e&ce%tions. RFSURFSTIJLT+(6PTE5M@TIGKU The restriction on e&ce%tions does not a%%ly to constructors. /ou can see in )tormyInning that a constructor can throw anything it wants, regardless o" what the base'class constructor throws. (owever, since a base'class constructor #ust always be called one way or another *here, the de"ault constructor is called auto#atically,, the derived'class constructor #ust declare any base'class constructor e&ce%tions in its e&ce%tion s%eci"ication. Cote that a derived'class constructor cannot catch e&ce%tions thrown by its base'class constructor. RFSURF STIJLT+(6PTE5M@TIGLU The reason )tormyInning!(alkA B will not co#%ile is that it throws an e&ce%tion, while Inning!(alkA B does not. I" this was allowed, then you could write code that called Inning!(alkA B and that didn t have to handle any e&ce%tions, but then when you substituted an ob0ect o" a class derived "ro# Inning, e&ce%tions would be thrown so your code would break. By "orcing the derived'class #ethods to con"or# to the e&ce%tion s%eci"ications o" the base'class #ethods, substitutability o" ob0ects is #aintained. RFSURFSTIJLT+(6PTE5M@TIG?U The overridden eventA B #ethod shows that a derived'class version o" a #ethod #ay choose not to throw any e&ce%tions, even i" the base'class version does. 6gain, this is "ine since it doesn t break any code that is written9assu#ing the base'class version throws e&ce%tions. Si#ilar logic a%%lies to at2atA B, which throws #opFo*l, an e&ce%tion that is derived

5:2

Thinking in Java

,,,'0ruceEckel'com

"ro# Fo*l thrown by the base'class version o" at2atA B. This way, i" so#eone writes code that works with Inning and calls at2atA B, they #ust catch the Fo*l e&ce%tion. Since #opFo*l is derived "ro# Fo*l, the e&ce%tion handler will also catch #opFo*l. RFSURF STIJLT+(6PTE5M@TIGHU The last %oint o" interest is in mainA B. (ere you can see that i" you re dealing with e&actly a )tormyInning ob0ect, the co#%iler "orces you to catch only the e&ce%tions that are s%eci"ic to that class, but i" you u%cast to the base ty%e then the co#%iler *correctly, "orces you to catch the e&ce%tions "or the base ty%e. 6ll these constraints %roduce #uch #ore robust e&ce%tion'handling code @. RFSURFSTIJLT+(6PTE5M@TIG3U It s use"ul to reali1e that although e&ce%tion s%eci"ications are en"orced by the co#%iler during inheritance, the e&ce%tion s%eci"ications are not %art o" the ty%e o" a #ethod, which is co#%rised o" only the #ethod na#e and argu#ent ty%es. There"ore, you cannot overload #ethods based on e&ce%tion s%eci"ications. In addition, 0ust because an e&ce%tion s%eci"ication e&ists in a base'class version o" a #ethod doesn t #ean that it #ust e&ist in the derived'class version o" the #ethod. This is Auite di""erent "ro# inheritance rules, where a #ethod in the base class #ust also e&ist in the derived class. Put another way, the !e&ce%tion s%eci"ication inter"ace$ "or a %articular #ethod #ay narrow during inheritance and overriding, but it #ay not widen9this is %recisely the o%%osite o" the rule "or the class inter"ace during inheritance. RFSURF STIJLT+(6PTE5M@TIGGU

Constructors
:hen writing code with e&ce%tions, it s %articularly i#%ortant that you always ask, !I" an e&ce%tion occurs, will this be %ro%erly cleaned u%O$ Most o" the ti#e you re "airly sa"e, but in constructors there s a %roble#. The constructor %uts the ob0ect into a sa"e starting state, but it #ight %er"or# so#e o%eration9such as o%ening a "ile9that doesn t get cleaned u% until the user is "inished with the ob0ect and calls a s%ecial cleanu%
@ IS) +<< added si#ilar constraints that reAuire derived'#ethod e&ce%tions to be the sa#e as, or derived "ro#, the e&ce%tions thrown by the base'class #ethod. This is one case in which +<< is actually able to check e&ce%tion s%eci"ications at co#%ile'ti#e.

5:3

#ethod. I" you throw an e&ce%tion "ro# inside a constructor, these cleanu% behaviors #ight not occur %ro%erly. This #eans that you #ust be es%ecially diligent while you write your constructor. RFSURF STIJLT+(6PTE5M@TIGIU Since you ve 0ust learned about finally, you #ight think that it is the correct solution. But it s not Auite that si#%le, because finally %er"or#s the cleanu% code ever) timeD even in the situations in which you don t want the cleanu% code e&ecuted until the cleanu% #ethod runs. Thus, i" you do %er"or# cleanu% in finally, you #ust set so#e kind o" "lag when the constructor "inishes nor#ally so that you don t do anything in the finally block i" the "lag is set. Because this isn t %articularly elegant *you are cou%ling your code "ro# one %lace to another,, it s best i" you try to avoid %er"or#ing this kind o" cleanu% in finally unless you are "orced to. RFSURFSTIJLT+(6PTE5M@TIG2U In the "ollowing e&a#%le, a class called Inp*tFile is created that o%ens a "ile and allows you to read it one line *converted into a )tring, at a ti#e. It uses the classes File$ea'er and 2*ffere'$ea'er "ro# the Java standard IF) library that will be discussed in +ha%ter MM, but which are si#%le enough that you %robably won t have any trouble understanding their basic use=

//3 c('3Cleanu".Hava // Paying attention to e6ce"tions // in constructors. i#"ort Hava.io.B< class $n"utLile @ "rivate Buffere!5ea!er in< $n"utLile-%tring fna#e. thro:s E6ce"tion @ try @ in ? ne: Buffere!5ea!erne: Lile5ea!er-fna#e..< // Gther co!e that #ight thro: e6ce"tions A catch-Lile&otLoun!E6ce"tion e. @ %yste#.err."rintln8Coul! not o"en 8 K fna#e.< // \asn2t o"en, so !on2t close it

5:4

Thinking in Java

,,,'0ruceEckel'com

thro: e< A catch-E6ce"tion e. @ // 0ll other e6ce"tions #ust close it try @ in.close-.< A catch-$GE6ce"tion e . @ %yste#.err."rintln8in.close-. unsuccessful8.< A thro: e< // 5ethro: A finally @ // Don2t close it here444 A A %tring getLine-. @ %tring s< try @ s ? in.rea!Line-.< A catch-$GE6ce"tion e. @ %yste#.err."rintln8rea!Line-. unsuccessful8.< s ? 8faile!8< A return s< A voi! cleanu"-. @ try @ in.close-.< A catch-$GE6ce"tion e . @ %yste#.err."rintln8in.close-. unsuccessful8.< A A A "ublic class Cleanu" @ "ublic static voi! #ain-%tringNO args. @ try @ $n"utLile in ? ne: $n"utLile-8Cleanu".Hava8.< %tring s<

5:5

int i ? (< :hile--s ? in.getLine-.. 4? null. %yste#.out."rintln-88K iKK K 83 8 K s.< in.cleanu"-.< A catch-E6ce"tion e. @ %yste#.err."rintln8Caught in #ain, e."rint%tackTrace-.8.< e."rint%tackTrace-%yste#.err.< A A A ///3>
The constructor "or Inp*tFile takes a )tring argu#ent, which is the na#e o" the "ile you want to o%en. Inside a try block, it creates a File$ea'er using the "ile na#e. 6 File$ea'er isn t %articularly use"ul until you turn around and use it to create a 2*ffere'$ea'er that you can actually talk to9notice that one o" the bene"its o" Inp*tFile is that it co#bines these two actions. RFSURFSTIJLT+(6PTE5M@TII@U I" the File$ea'er constructor is unsuccess"ul, it throws a File/otFo*n'&4ception, which #ust be caught se%arately because that s the one case in which you don t want to close the "ile since it wasn t success"ully o%ened. 6ny other catch clauses #ust close the "ile because it ,as o%ened by the ti#e those catch clauses are entered. *)" course, this is trickier i" #ore than one #ethod can throw a File/otFo*n'&4ception. In that case, you #ight want to break things into several try blocks., The closeA B #ethod #ight throw an e&ce%tion so it is tried and caught even though it s within the block o" another catch clause9it s 0ust another %air o" curly braces to the Java co#%iler. 6"ter %er"or#ing local o%erations, the e&ce%tion is rethrown, which is a%%ro%riate because this constructor "ailed, and you wouldn t want the calling #ethod to assu#e that the ob0ect had been %ro%erly created and was valid. RFSURF STIJLT+(6PTE5M@TIIMU In this e&a#%le, which doesn t use the a"ore#entioned "lagging techniAue, the finally clause is de"initely not the %lace to closeA B the "ile, since that would close it every ti#e the constructor co#%leted. Since we want the "ile to be o%en "or the use"ul li"eti#e o" the Inp*tFile ob0ect this would not be a%%ro%riate. RFSURFSTIJLT+(6PTE5M@TIIKU

5:7

Thinking in Java

,,,'0ruceEckel'com

The get+ineA B #ethod returns a )tring containing the ne&t line in the "ile. It calls rea'+ineA B, which can throw an e&ce%tion, but that e&ce%tion is caught so get+ineA B doesn t throw any e&ce%tions. )ne o" the design issues with e&ce%tions is whether to handle an e&ce%tion co#%letely at this level, to handle it %artially and %ass the sa#e e&ce%tion *or a di""erent one, on, or whether to si#%ly %ass it on. Passing it on, when a%%ro%riate, can certainly si#%li"y coding. The get+ineA B #ethod beco#es=

%tring getLine-. thro:s $GE6ce"tion @ return in.rea!Line-.< A


But o" course, the caller is now res%onsible "or handling any I.&4ception that #ight arise. RFSURFSTIJLT+(6PTE5M@TIILU The clean*pA B #ethod #ust be called by the user when "inished using the Inp*tFile ob0ect. This will release the syste# resources *such as "ile handles, that are used by the 2*ffere'$ea'er andFor File$ea'er ob0ects @. /ou don t want to do this until you re "inished with the Inp*tFile ob0ect, at the %oint you re going to let it go. /ou #ight think o" %utting such "unctionality into a finali7eA B #ethod, but as #entioned in +ha%ter ? you can t always be sure that finali7eA B will be called *even i" you can be sure that it will be called, you don t know ,hen,. This is one o" the downsides to Java= all cleanu%9other than #e#ory cleanu%9doesn t ha%%en auto#atically, so you #ust in"or# the client %rogra##er that they are res%onsible, and %ossibly guarantee that cleanu% occurs using finali7eA B. RFSURFSTIJLT+(6PTE5M@TII?U In -lean*p!8ava an Inp*tFile is created to o%en the sa#e source "ile that creates the %rogra#, the "ile is read in a line at a ti#e, and line nu#bers are added. 6ll e&ce%tions are caught generically in mainA B, although you could choose greater granularity. RFSURF STIJLT+(6PTE5M@TIIHU )ne o" the bene"its o" this e&a#%le is to show you why e&ce%tions are introduced at this %oint in the book9you can t do basic IF) without using e&ce%tions. E&ce%tions are so integral to %rogra##ing in Java, es%ecially because the co#%iler en"orces the#, that you can acco#%lish only so
@ In +<<, a destructor would handle this "or you.

5:8

#uch without knowing how to work with the#. RFSURF STIJLT+(6PTE5M@TII3U

/0ce.tion matching
:hen an e&ce%tion is thrown, the e&ce%tion handling syste# looks through the !nearest$ handlers in the order they are written. :hen it "inds a #atch, the e&ce%tion is considered handled, and no "urther searching occurs. RFSURFSTIJLT+(6PTE5M@TIIGU Matching an e&ce%tion doesn t reAuire a %er"ect #atch between the e&ce%tion and its handler. 6 derived'class ob0ect will #atch a handler "or the base class, as shown in this e&a#%le=

//3 c('3Mu#an.Hava // Catching e6ce"tion hierarchies. class 0nnoyance e6ten!s E6ce"tion @A class %neeUe e6ten!s 0nnoyance @A "ublic class Mu#an @ "ublic static voi! #ain-%tringNO args. @ try @ thro: ne: %neeUe-.< A catch-%neeUe s. @ %yste#.err."rintln-8Caught %neeUe8.< A catch-0nnoyance a. @ %yste#.err."rintln-8Caught 0nnoyance8.< A A A ///3>
The )nee7e e&ce%tion will be caught by the "irst catch clause that it #atches9which is the "irst one, o" course. (owever, i" you re#ove the "irst catch clause, leaving only= RFSURFSTIJLT+(6PTE5M@TIIIU

try @ thro: ne: %neeUe-.< A catch-0nnoyance a. @ %yste#.err."rintln-8Caught 0nnoyance8.<

5::

Thinking in Java

,,,'0ruceEckel'com

A
The code will still work because it s catching the base class o" )nee7e. Put another way, catchAAnnoyance eB will catch an Annoyance or an) class derived $rom it. This is use"ul because i" you decide to add #ore derived e&ce%tions to a #ethod, then the client %rogra##er s code will not need changing as long as the client catches the base class e&ce%tions. RFSURFSTIJLT+(6PTE5M@TII2U I" you try to !#ask$ the derived'class e&ce%tions by %utting the base'class catch clause "irst, like this=

try @ thro: ne: %neeUe-.< A catch-0nnoyance a. @ %yste#.err."rintln-8Caught 0nnoyance8.< A catch-%neeUe s. @ %yste#.err."rintln-8Caught %neeUe8.< A
the co#%iler will give you an error #essage, since it sees that the )nee7e catch'clause can never be reached. RFSURFSTIJLT+(6PTE5M@TI2@U

/0ce.tion guidelines
4se e&ce%tions to=

6*) 6+) 6,) 6-) 64) 65)

Ei& the %roble# and call the #ethod that caused the e&ce%tion again. Patch things u% and continue without retrying the #ethod. +alculate so#e alternative result instead o" what the #ethod was su%%osed to %roduce. 7o whatever you can in the current conte&t and rethrow the same e&ce%tion to a higher conte&t. 7o whatever you can in the current conte&t and throw a di$$erent e&ce%tion to a higher conte&t. Ter#inate the %rogra#.

5:;

66)

Si#%li"y. *I" your e&ce%tion sche#e #akes things #ore co#%licated, then it is %ain"ul and annoying to use.,

(77) Make your library and %rogra# sa"er. *This is a short'ter#


invest#ent "or debugging, and a long'ter# invest#ent *"or a%%lication robustness., RFSURFSTIJLT+(6PTE5M@TI2MU

1ummar:
I#%roved error recovery is one o" the #ost %ower"ul ways that you can increase the robustness o" your code. Error recovery is a "unda#ental concern "or every %rogra# you write, but it s es%ecially i#%ortant in Java, where one o" the %ri#ary goals is to create %rogra# co#%onents "or others to use. To create a robust s)stemD each com onent must be robust' RFSURFSTIJLT+(6PTE5M@TI2KU The goals "or e&ce%tion handling in Java are to si#%li"y the creation o" large, reliable %rogra#s using less code than currently %ossible, and with #ore con"idence that your a%%lication doesn t have an unhandled error. RFSURFSTIJLT+(6PTE5M@TI2LU

E&ce%tions are not terribly di""icult to learn, and are one o" those "eatures that %rovide i##ediate and signi"icant bene"its to your %ro0ect. Eortunately, Java en"orces all as%ects o" e&ce%tions so it s guaranteed that they will be used consistently by both library designers and client %rogra##ers. RFSURFSTIJLT+(6PTE5M@TI2?U

/0ercises
Solutions to selected e&ercises can be "ound in the electronic docu#entThe Thinking in Java "nnotated Solution @uide, available "or a s#all "ee "ro# ,,,'0ruceEckel'com.

(47) +reate a class with a mainA B that throws an ob0ect o" class
&4ception inside a try block. 8ive the constructor "or &4ception a )tring argu#ent. +atch the e&ce%tion inside a catch clause and %rint the )tring argu#ent. 6dd a finally clause
and %rint a #essage to %rove you were there. RFSURF STIJLT+(6PTE5M@TI2HU

5;=

Thinking in Java

,,,'0ruceEckel'com

(4() +reate your own e&ce%tion class using the e4ten's keyword.
:rite a constructor "or this class that takes a )tring argu#ent and stores it inside the ob0ect with a )tring re"erence. :rite a #ethod that %rints out the stored )tring. +reate a try6catch clause to e&ercise your new e&ce%tion. RFSURF STIJLT+(6PTE5M@TI23U

(4!) :rite a class with a #ethod that throws an e&ce%tion o" the
ty%e created in E&ercise K. Try co#%iling it without an e&ce%tion s%eci"ication to see what the co#%iler says. 6dd the a%%ro%riate e&ce%tion s%eci"ication. Try out your class and its e&ce%tion inside a try'catch clause. RFSURFSTIJLT+(6PTE5M@TI2GU

(4*) 7e"ine an ob0ect re"erence and initiali1e it to n*ll. Try to call a


#ethod through this re"erence. Cow wra% the code in a try6catch clause to catch the e&ce%tion. RFSURFSTIJLT+(6PTE5M@TI2IU

(4+) +reate a class with two #ethods, fA B and gA B. In gA B, throw an


e&ce%tion o" a new ty%e that you de"ine. In fA B, call gA B, catch its e&ce%tion and, in the catch clause, throw a di""erent e&ce%tion *o" a second ty%e that you de"ine,. Test your code in mainA B. RFSURF STIJLT+(6PTE5M@TI22U

(4,) +reate three new ty%es o" e&ce%tions. :rite a class with a
#ethod that throws all three. In mainA B, call the #ethod but only use a single catch clause that will catch all three ty%es o" e&ce%tions. RFSURFSTIJLT+(6PTE5M@TIM@@U

(4-) :rite code to generate and catch an


ArrayIn'e4.*t.f2o*n's&4ception. RFSURF
STIJLT+(6PTE5M@TIM@MU

(44) +reate your own resu#%tion'like behavior using a (hile loo%


that re%eats until an e&ce%tion is no longer thrown. RFSURF STIJLT+(6PTE5M@TIM@KU

(45) +reate a three'level hierarchy o" e&ce%tions. Cow create a base'


class A with a #ethod that throws an e&ce%tion at the base o" your hierarchy. Inherit 2 "ro# A and override the #ethod so it throws an e&ce%tion at level two o" your hierarchy. 5e%eat by inheriting

5;1

class - "ro# 2. In mainA B, create a - and u%cast it to A, then call the #ethod. RFSURFSTIJLT+(6PTE5M@TIM@LU

(46) 7e#onstrate that a derived'class constructor cannot catch


e&ce%tions thrown by its base'class constructor. RFSURF STIJLT+(6PTE5M@TIM@?U

(57) Show that .n.ff)(itch!8ava can "ail by throwing a


$*ntime&4ception inside the try block. RFSURF
STIJLT+(6PTE5M@TIM@HU

(5() Show that 0ithFinally!8ava doesn t "ail by throwing a


$*ntime&4ception inside the try block. RFSURF
STIJLT+(6PTE5M@TIM@3U

(5!) Modi"y E&ercise 3 by adding a finally clause. Veri"y your


finally clause is e&ecuted, even i" a /*ll#ointer&4ception is
thrown. RFSURFSTIJLT+(6PTE5M@TIM@GU

(5*) +reate an e&a#%le where you use a "lag to control whether


cleanu% code is called, as described in the second %aragra%h a"ter the heading !+onstructors.$ RFSURFSTIJLT+(6PTE5M@TIM@IU

(5+) Modi"y )tormyInning!8ava by adding an


UmpireArg*ment e&ce%tion ty%e, and #ethods that throw this
e&ce%tion. Test the #odi"ied hierarchy. RFSURF STIJLT+(6PTE5M@TIM@2U

(5,) 5e#ove the "irst catch clause in H*man!8ava and veri"y that
the code still co#%iles and runs %ro%erly. RFSURF STIJLT+(6PTE5M@TIMM@U

(5-) 6dd a second level o" e&ce%tion loss to +ost1essage!8ava so


that the HoH*m&4ception is itsel" re%laced by a third e&ce%tion. RFSURFSTIJLT+(6PTE5M@TIMMMU

(54) In +ha%ter H, "ind the two %rogra#s called Assert!8ava and


#odi"y these to throw their own ty%e o" e&ce%tion instead o" %rinting to )ystem!err. This e&ce%tion should be an inner class that e&tends $*ntime&4ception. RFSURF STIJLT+(6PTE5M@TIMMKU

5;2

Thinking in Java

,,,'0ruceEckel'com

(55) 6dd an a%%ro%riate set o" e&ce%tions to cDY<


"reenho*se-ontrols!8ava. RFSU

5;3

((: #he "ava IDO 1:stem


RFSTIJLT+(6PTE5MMTI@U+reating a good in%utFout%ut *IF), syste# is one o" the #ore di""icult tasks "or the language designer.
This is evidenced by the nu#ber o" di""erent a%%roaches. The challenge see#s to be in covering all eventualities. Cot only are there di""erent sources and sinks o" IF) that you want to co##unicate with *"iles, the console, network connections,, but you need to talk to the# in a wide variety o" ways *seAuential, rando#'access, bu""ered, binary, character, by lines, by words, etc.,. RFSURFSTIJLT+(6PTE5MMTIMU The Java library designers attacked this %roble# by creating lots o" classes. In "act, there are so #any classes "or Java s IF) syste# that it can be inti#idating at "irst *ironically, the Java IF) design actually %revents an e&%losion o" classes,. There was also a signi"icant change in the IF) library a"ter Java M.@, when the original byte'oriented library was su%%le#ented with char'oriented, 4nicode'based IF) classes. 6s a result there are a "air nu#ber o" classes to learn be"ore you understand enough o" Java s IF) %icture that you can use it %ro%erly. In addition, it s rather i#%ortant to understand the evolution history o" the IF) library, even i" your "irst reaction is !don t bother #e with history, 0ust show #e how to use it.$ The %roble# is that without the historical %ers%ective you will ra%idly beco#e con"used with so#e o" the classes and when you should and shouldn t use the#. RFSURFSTIJLT+(6PTE5MMTIKU This cha%ter will give you an introduction to the variety o" IF) classes in the standard Java library and how to use the#. RFSURF STIJLT+(6PTE5MMTILU

5;4

#he 6ile class


Be"ore getting into the classes that actually read and write data to strea#s, we ll look a utility %rovided with the library to assist you in handling "ile directory issues. RFSURFSTIJLT+(6PTE5MMTI?U The File class has a deceiving na#e9you #ight think it re"ers to a "ile, but it doesn t. It can re%resent either the name o" a %articular "ile or the names o" a set o" "iles in a directory. I" it s a set o" "iles, you can ask "or the set with the listA B #ethod, and this returns an array o" )tring. It #akes sense to return an array rather than one o" the "le&ible container classes because the nu#ber o" ele#ents is "i&ed, and i" you want a di""erent directory listing you 0ust create a di""erent File ob0ect. In "act, !EilePath$ would have been a better na#e "or the class. This section shows an e&a#%le o" the use o" this class, including the associated FilenameFilter interface. RFSURFSTIJLT+(6PTE5MMTIHU

A director: lister
Su%%ose you d like to see a directory listing. The File ob0ect can be listed in two ways. I" you call listA B with no argu#ents, you ll get the "ull list that the File ob0ect contains. (owever, i" you want a restricted list9"or e&a#%le, i" you want all o" the "iles with an e&tension o" !8ava9then you use a !directory "ilter,$ which is a class that tells how to select the File ob0ects "or dis%lay. RFSURFSTIJLT+(6PTE5MMTI3U (ere s the code "or the e&a#%le. Cote that the result has been e""ortlessly sorted *al%habetically, using the 8ava!*tils!Array!sortA B #ethod and the Alphabetic-omparator de"ined in +ha%ter 2=

//3 c((3DirList.Hava // Dis"lays !irectory listing. i#"ort Hava.io.B< i#"ort Hava.util.B< i#"ort co#.bruceeckel.util.B< "ublic class DirList @ "ublic static voi! #ain-%tringNO args. @ Lile "ath ? ne: Lile-8.8.<

Cha ter 11! The Java I/O S)stem

5;5

%tringNO list< if-args.length ?? '. list ? "ath.list-.< else list ? "ath.list-ne: DirLilter-argsN'O..< 0rrays.sort-list, ne: 0l"habeticCo#"arator-..< for-int i ? '< i P list.length< iKK. %yste#.out."rintln-listNiO.< A A class DirLilter i#"le#ents Lilena#eLilter @ %tring afn< DirLilter-%tring afn. @ this.afn ? afn< A "ublic boolean acce"t-Lile !ir, %tring na#e. @ // %tri" "ath infor#ation3 %tring f ? ne: Lile-na#e..get&a#e-.< return f.in!e6Gf-afn. 4? -(< A A ///3>
The irFilter class !i#%le#ents$ the interface FilenameFilter. It s use"ul to see how si#%le the FilenameFilter interface is= RFSURF STIJLT+(6PTE5MMTIGU

"ublic interface Lilena#eLilter @ boolean acce"t-Lile !ir, %tring na#e.< A


It says all that this ty%e o" ob0ect does is %rovide a #ethod called accept A B. The whole reason behind the creation o" this class is to %rovide the acceptA B #ethod to the listA B #ethod so that listA B can !call back$ acceptA B to deter#ine which "ile na#es should be included in the list. Thus, this techniAue is o"ten re"erred to as a callback or so#eti#es a $unctor *that is, irFilter is a "unctor because its only 0ob is to hold a #ethod, or the Command Pattern. Because listA B takes a FilenameFilter ob0ect as its argu#ent, it #eans that you can %ass an ob0ect o" any class that i#%le#ents FilenameFilter to choose *even at run'ti#e, how the listA B #ethod will behave. The %ur%ose o" a callback is

5;7

to %rovide "le&ibility in the behavior o" code. RFSURF STIJLT+(6PTE5MMTIIU

irFilter shows that 0ust because an interface contains only a set o" #ethods, you re not restricted to writing only those #ethods. */ou #ust at least %rovide de"initions "or all the #ethods in an inter"ace, however., In this case, the irFilter constructor is also created. RFSURF STIJLT+(6PTE5MMTI2U
The acceptA B #ethod #ust acce%t a File ob0ect re%resenting the directory that a %articular "ile is "ound in, and a )tring containing the na#e o" that "ile. /ou #ight choose to use or ignore either o" these argu#ents, but you will %robably at least use the "ile na#e. 5e#e#ber that the listA B #ethod is calling acceptA B "or each o" the "ile na#es in the directory ob0ect to see which one should be included9this is indicated by the boolean result returned by acceptA B. RFSURF STIJLT+(6PTE5MMTIM@U To #ake sure the ele#ent you re working with is only the "ile na#e and contains no %ath in"or#ation, all you have to do is take the )tring ob0ect and create a File ob0ect out o" it, then call get/ameA B, which stri%s away all the %ath in"or#ation *in a %lat"or#'inde%endent way,. Then acceptA B uses the )tring class in'e4.fA B #ethod to see i" the search string afn a%%ears anywhere in the na#e o" the "ile. I" afn is "ound within the string, the return value is the starting inde& o" afn, but i" it s not "ound the return value is 'M. >ee% in #ind that this is a si#%le string search and does not have !glob$ e&%ression wildcard #atching9such as !"oO.bOrB$9which is #uch #ore di""icult to i#%le#ent. RFSURF STIJLT+(6PTE5MMTIMMU The listA B #ethod returns an array. /ou can Auery this array "or its length and then #ove through it selecting the array ele#ents. This ability to easily %ass an array in and out o" a #ethod is a tre#endous i#%rove#ent over the behavior o" + and +<<. RFSURF STIJLT+(6PTE5MMTIMKU

Cha ter 11! The Java I/O S)stem

5;8

Anon:mous inner classes


This e&a#%le is ideal "or rewriting using an anony#ous inner class *described in +ha%ter I,. 6s a "irst cut, a #ethod filterA B is created that returns a re"erence to a FilenameFilter=

//3 c((3DirList .Hava // Yses anony#ous inner classes. i#"ort Hava.io.B< i#"ort Hava.util.B< i#"ort co#.bruceeckel.util.B< "ublic class DirList @ "ublic static Lilena#eLilter filter-final %tring afn. @ // Creation of anony#ous inner class3 return ne: Lilena#eLilter-. @ %tring fn ? afn< "ublic boolean acce"t-Lile !ir, %tring n. @ // %tri" "ath infor#ation3 %tring f ? ne: Lile-n..get&a#e-.< return f.in!e6Gf-fn. 4? -(< A A< // En! of anony#ous inner class A "ublic static voi! #ain-%tringNO args. @ Lile "ath ? ne: Lile-8.8.< %tringNO list< if-args.length ?? '. list ? "ath.list-.< else list ? "ath.list-filter-argsN'O..< 0rrays.sort-list, ne: 0l"habeticCo#"arator-..< for-int i ? '< i P list.length< iKK. %yste#.out."rintln-listNiO.< A A ///3>

5;:

Cote that the argu#ent to filterA B #ust be final. This is reAuired by the anony#ous inner class so that it can use an ob0ect "ro# outside its sco%e. RFSURFSTIJLT+(6PTE5MMTIMLU This design is an i#%rove#ent because the FilenameFilter class is now tightly bound to ir+istI. (owever, you can take this a%%roach one ste% "urther and de"ine the anony#ous inner class as an argu#ent to listA B, in which case it s even s#aller=

//3 c((3DirList).Hava // Buil!ing the anony#ous inner class 8in-"lace.8 i#"ort Hava.io.B< i#"ort Hava.util.B< i#"ort co#.bruceeckel.util.B< "ublic class DirList) @ "ublic static voi! #ain-final %tringNO args. @ Lile "ath ? ne: Lile-8.8.< %tringNO list< if-args.length ?? '. list ? "ath.list-.< else list ? "ath.list-ne: Lilena#eLilter-. @ "ublic boolean acce"t-Lile !ir, %tring n. @ %tring f ? ne: Lile-n..get&a#e-.< return f.in!e6Gf-argsN'O. 4? -(< A A.< 0rrays.sort-list, ne: 0l"habeticCo#"arator-..< for-int i ? '< i P list.length< iKK. %yste#.out."rintln-listNiO.< A A ///3>
The argu#ent to mainA B is now final, since the anony#ous inner class uses args]D^ directly. RFSURFSTIJLT+(6PTE5MMTIM?U This shows you how anony#ous inner classes allow the creation o" Auick' and'dirty classes to solve %roble#s. Since everything in Java revolves

Cha ter 11! The Java I/O S)stem

5;;

around classes, this can be a use"ul coding techniAue. )ne bene"it is that it kee%s the code that solves a %articular %roble# isolated together in one s%ot. )n the other hand, it is not always as easy to read, so you #ust use it 0udiciously. RFSURFSTIJLT+(6PTE5MMTIMHU

Checking for and creating directories


The File class is #ore than 0ust a re%resentation "or an e&isting "ile or directory. /ou can also use a File ob0ect to create a new directory or an entire directory %ath i" it doesn t e&ist. /ou can also look at the characteristics o" "iles *si1e, last #odi"ication date, readFwrite,, see whether a File ob0ect re%resents a "ile or a directory, and delete a "ile. This %rogra# shows so#e o" the other #ethods available with the File class *see the (TMD docu#entation "ro# >ava'sun'com "or the "ull set,=

//3 c((3JakeDirectories.Hava // De#onstrates the use of the Lile class to // create !irectories an! #ani"ulate files. i#"ort Hava.io.B< "ublic class JakeDirectories @ "rivate final static %tring usage ? 8Ysage3JakeDirectories "ath( ..._n8 K 8Creates each "ath_n8 K 8Ysage3JakeDirectories -! "ath( ..._n8 K 8Deletes each "ath_n8 K 8Ysage3JakeDirectories -r "ath( "ath _n8 K 85ena#es fro# "ath( to "ath _n8< "rivate static voi! usage-. @ %yste#.err."rintln-usage.< %yste#.e6it-(.< A "rivate static voi! fileData-Lile f. @ %yste#.out."rintln80bsolute "ath3 8 K f.get0bsolutePath-. K 8_n Can rea!3 8 K f.can5ea!-. K 8_n Can :rite3 8 K f.can\rite-. K 8_n get&a#e3 8 K f.get&a#e-. K

7==

8_n getParent3 8 K f.getParent-. K 8_n getPath3 8 K f.getPath-. K 8_n length3 8 K f.length-. K 8_n lastJo!ifie!3 8 K f.lastJo!ifie!-..< if-f.isLile-.. %yste#.out."rintln-8it2s a file8.< else if-f.isDirectory-.. %yste#.out."rintln-8it2s a !irectory8.< A "ublic static voi! #ain-%tringNO args. @ if-args.length P (. usage-.< if-argsN'O.e=uals-8-r8.. @ if-args.length 4? ). usage-.< Lile ol! ? ne: Lile-argsN(O., rna#e ? ne: Lile-argsN O.< ol!.rena#eTo-rna#e.< fileData-ol!.< fileData-rna#e.< return< // E6it #ain A int count ? '< boolean !el ? false< if-argsN'O.e=uals-8-!8.. @ countKK< !el ? true< A for- < count P args.length< countKK. @ Lile f ? ne: Lile-argsNcountO.< if-f.e6ists-.. @ %yste#.out."rintln-f K 8 e6ists8.< if-!el. @ %yste#.out."rintln-8!eleting...8 K f.< f.!elete-.< A A else @ // Doesn2t e6ist if-4!el. @ f.#k!irs-.< %yste#.out."rintln-8create! 8 K f.< A

Cha ter 11! The Java I/O S)stem

7=1

A fileData-f.< A A A ///3>
In file ataA B you can see various "ile investigation #ethods used to dis%lay in"or#ation about the "ile or directory %ath. RFSURF STIJLT+(6PTE5MMTIM3U The "irst #ethod that s e&ercised by mainA B is renameToA B, which allows you to rena#e *or #ove, a "ile to an entirely new %ath re%resented by the argu#ent, which is another File ob0ect. This also works with directories o" any length. RFSURFSTIJLT+(6PTE5MMTIMGU I" you e&%eri#ent with the above %rogra#, you ll "ind that you can #ake a directory %ath o" any co#%le&ity because mk'irsA B will do all the work "or you. RFSURFSTIJLT+(6PTE5MMTIMIU

In.ut and out.ut


IF) libraries o"ten use the abstraction o" a stream, which re%resents any data source or sink as an ob0ect ca%able o" %roducing or receiving %ieces o" data. The strea# hides the details o" what ha%%ens to the data inside the actual IF) device. RFSURFSTIJLT+(6PTE5MMTIM2U The Java library classes "or IF) are divided by in%ut and out%ut, as you can see by looking at the online Java class hierarchy with your :eb browser. By inheritance, everything derived "ro# the Inp*t)tream or $ea'er classes have basic #ethods called rea'A B "or reading a single byte or array o" bytes. Dikewise, everything derived "ro# .*tp*t)tream or 0riter classes have basic #ethods called (riteA B "or writing a single byte or array o" bytes. (owever, you won t generally use these #ethods; they e&ist so that other classes can use the#9these other classes %rovide a #ore use"ul inter"ace. Thus, you ll rarely create your strea# ob0ect by using a single class, but instead will layer #ulti%le ob0ects together to %rovide your desired "unctionality. The "act that you create #ore than one ob0ect to create a single resulting strea# is the %ri#ary reason that Java s strea# library is con"using. RFSURFSTIJLT+(6PTE5MMTIK@U

7=2

It s hel%"ul to categori1e the classes by their "unctionality. In Java M.@, the library designers started by deciding that all classes that had anything to do with in%ut would be inherited "ro# Inp*t)tream and all classes that were associated with out%ut would be inherited "ro# .*tp*t)tream. RFSURFSTIJLT+(6PTE5MMTIKMU

#:.es of 7n utStream
Inp*t)tream s 0ob is to re%resent classes that %roduce in%ut "ro# di""erent sources. These sources can be= (7() 6n array o" bytes. (7!) 6 )tring ob0ect. (7*) 6 "ile. (7+) 6 !%i%e,$ which works like a %hysical %i%e= you %ut things in one
end and they co#e out the other.

(7,) 6 seAuence o" other strea#s, so you can collect the# together into
a single strea#.

(7-) )ther sources, such as an Internet connection. *This will be


discussed in a later cha%ter., RFSURFSTIJLT+(6PTE5MMTIKKU Each o" these has an associated subclass o" Inp*t)tream. In addition, the FilterInp*t)tream is also a ty%e o" Inp*t)tream, to %rovide a base class "or cdecoratorc classes that attach attributes or use"ul inter"aces to in%ut strea#s. This is discussed later. RFSURF STIJLT+(6PTE5MMTIKLU

Table >>6>! Types of Inp*t)tream

Cha ter 11! The Java I/O S)stem

7=3

-lass

F*nction

-onstr*ctor Arg*ments Ho( to *se it


The bu""er "ro# which to e&tract the bytes. 6s a source o" data. +onnect it to a

2yteArray6 Inp*t)trea m

6llows a bu""er in #e#ory to be used as an

Inp*t)tream

FilterInp*t)tream )tring2*ffer 6 Inp*t)trea m


ob0ect to %rovide a use"ul inter"ace. 6 )tring. The underlying i#%le#entation actually uses a )tring2*ffer. 6s a source o" data. +onnect it to a

+onverts a

)tring into an Inp*t)tream

FilterInp*t)tream File6 Inp*t)trea m


ob0ect to %rovide a use"ul inter"ace. 6 )tring re%resenting the "ile na#e, or a File or File escriptor ob0ect. 6s a source o" data. +onnect it to a

Eor reading in"or#ation "ro# a "ile

FilterInp*t)tream
ob0ect to %rovide a use"ul inter"ace.

#ipe'6 Inp*t)trea m

Produces the data that s being written to the associated #ipe'.*tp*t' )tream. I#%le#ents the !%i%ing$ conce%t.

#ipe'.*tp*t)tream

6s a source o" data in #ultithreading. +onnect it to a

FilterInp*t)tream
ob0ect to %rovide a use"ul inter"ace.

7=4

-lass

F*nction

)eC*ence6 Inp*t)trea m

+onverts two or #ore

-onstr*ctor Arg*ments Ho( to *se it Two Inp*t)tream


ob0ects or an

Inp*t)tream
ob0ects into a single

&n*meration "or a
container o"

Inp*t)tream ob0ects.
6s a source o" data. +onnect it to a

Inp*t)tream.

FilterInp*t)tream Filter6 Inp*t)trea m


ob0ect to %rovide a use"ul inter"ace. See Table MM'L.

6bstract class which is an inter"ace "or decorators that %rovide use"ul "unctionality to the other

See Table MM'L.

Inp*t)tream
classes. See Table MM'L.

#:.es of Out utStream


This category includes the classes that decide where your out%ut will go= an array o" bytes *no )tring, however; %resu#ably you can create one using the array o" bytes,, a "ile, or a !%i%e.$ RFSURF STIJLT+(6PTE5MMTIK?U In addition, the Filter.*tp*t)tream %rovides a base class "or cdecoratorc classes that attach attributes or use"ul inter"aces to out%ut strea#s. This is discussed later. RFSURFSTIJLT+(6PTE5MMTIKHU

Table >>6I! Types of .*tp*t)tream

Cha ter 11! The Java I/O S)stem

7=5

-lass

F*nction

-onstr*ctor Arg*ments Ho( to *se it


)%tional initial si1e o" the bu""er. To designate the destination o" your data. +onnect it to a

2yteArray6 .*tp*t)trea m

+reates a bu""er in #e#ory. 6ll the data that you send to the strea# is %laced in this bu""er.

Filter.*tp*t)tream File6 .*tp*t)trea m


ob0ect to %rovide a use"ul inter"ace. 6 String re%resenting the "ile na#e, or a File or File escriptor ob0ect. To designate the destination o" your data. +onnect it to a

Eor sending in"or#ation to a "ile.

Filter.*tp*t)tream
ob0ect to %rovide a use"ul inter"ace.

#ipe'6 .*tp*t)trea m

6ny in"or#ation you write to this auto#atically ends u% as in%ut "or the associated

#ipe'Inp*t)tream

#ipe'Inp*t6 )tream.
I#%le#ents the !%i%ing$ conce%t.

To designate the destination o" your data "or #ultithreading. +onnect it to a

Filter.*tp*t)tream
ob0ect to %rovide a use"ul inter"ace.

7=7

-lass

F*nction

-onstr*ctor Arg*ments Ho( to *se it


See Table MM'?. See Table MM'?.

Filter6 .*tp*t)trea m

6bstract class which is an inter"ace "or decorators that %rovide use"ul "unctionality to the other

.*tp*t)tream
classes. See Table MM'?.

Adding attributes and useful interfaces


The use o" layered ob0ects to dyna#ically and trans%arently add res%onsibilities to individual ob0ects is re"erred to as the %ecorator %attern. *Patterns @ are the sub0ect o" Thinking in Patterns ,ith Java, downloadable at ,,,'0ruceEckel'com., The decorator %attern s%eci"ies that all ob0ects that wra% around your initial ob0ect have the sa#e inter"ace. This #akes the basic use o" the decorators trans%arent9you send the sa#e #essage to an ob0ect whether it s been decorated or not. This is the reason "or the e&istence o" the !"ilter$ classes in the Java IF) library= the abstract !"ilter$ class is the base class "or all the decorators. *6 decorator #ust have the sa#e inter"ace as the ob0ect it decorates, but the decorator can also e&tend the inter"ace, which occurs in several o" the !"ilter$ classes,. RFSURFSTIJLT+(6PTE5MMTIK3U 7ecorators are o"ten used when si#%le subclassing results in a large nu#ber o" subclasses in order to satis"y every %ossible co#bination that is needed9so #any subclasses that it beco#es i#%ractical. The Java IF) library reAuires #any di""erent co#binations o" "eatures, which is why the decorator %attern is used. There is a drawback to the decorator %attern, however. 7ecorators give you #uch #ore "le&ibility while you re
@ %esign Patterns, Erich 8a##a et al', 6ddison':esley M22H.

Cha ter 11! The Java I/O S)stem

7=8

writing a %rogra# *since you can easily #i& and #atch attributes,, but they add co#%le&ity to your code. The reason that the Java IF) library is awkward to use is that you #ust create #any classes9the !core$ IF) ty%e %lus all the decorators9in order to get the single IF) ob0ect that you want. RFSURFSTIJLT+(6PTE5MMTIKGU The classes that %rovide the decorator inter"ace to control a %articular Inp*t)tream or .*tp*t)tream are the FilterInp*t)tream and Filter.*tp*t)tream9which don t have very intuitive na#es. FilterInp*t)tream and Filter.*tp*t)tream are abstract classes that are derived "ro# the base classes o" the IF) library, Inp*t)tream and .*tp*t)tream, which is the key reAuire#ent o" the decorator *so that it %rovides the co##on inter"ace to all the ob0ects that are being decorated,. RFSURFSTIJLT+(6PTE5MMTIKIU

$eading from an 7n utStream with 6ilter7n utStream


The FilterInp*t)tream classes acco#%lish two signi"icantly di""erent things. ataInp*t)tream allows you to read di""erent ty%es o" %ri#itive data as well as )tring ob0ects. *6ll the #ethods start with !read,$ such as rea'2yteA B, rea'FloatA B, etc., This, along with its co#%anion ata.*tp*t)tream, allows you to #ove %ri#itive data "ro# one %lace to another via a strea#. These !%laces$ are deter#ined by the classes in Table MM'M. RFSURFSTIJLT+(6PTE5MMTIK2U The re#aining classes #odi"y the way an Inp*t)tream behaves internally= whether it s bu""ered or unbu""ered, i" it kee%s track o" the lines it s reading *allowing you to ask "or line nu#bers or set the line nu#ber,, and whether you can %ush back a single character. The last two classes look a lot like su%%ort "or building a co#%iler *that is, they were added to su%%ort the construction o" the Java co#%iler,, so you %robably won t use the# in general %rogra##ing. RFSURF STIJLT+(6PTE5MMTIL@U /ou ll %robably need to bu""er your in%ut al#ost every ti#e, regardless o" the IF) device you re connecting to, so it would have #ade #ore sense "or the IF) library to #ake a s%ecial case *or si#%ly a #ethod call, "or

7=:

unbu""ered in%ut rather than bu""ered in%ut. RFSURF STIJLT+(6PTE5MMTILMU

Table >>6J! Types of FilterInp*t)tream -lass F*nction -onstr*ctor Arg*ments Ho( to *se it Inp*t)tream

ata6 Inp*t)trea m

4sed in concert with

ata.*tp*t)tream
, so you can read %ri#itives * int, char, long, etc., "ro# a strea# in a %ortable "ashion. 4se this to %revent a %hysical read every ti#e you want #ore data. /ou re saying !4se a bu""er.$ +ontains a "ull inter"ace to allow you to read %ri#itive ty%es. Inp*t)tream, with o%tional bu""er si1e. This doesn t %rovide an inter"ace er se, 0ust a reAuire#ent that a bu""er be used. 6ttach an inter"ace ob0ect.

2*ffere'6 Inp*t)tream

+ine/*mber 6 Inp*t)tream

>ee%s track o" line nu#bers in the in%ut strea#; you can call

Inp*t)tream

get+ine/*mberA B
and

set+ine/*mberA intB.

This 0ust adds line nu#bering, so you ll %robably attach an inter"ace ob0ect.

Cha ter 11! The Java I/O S)stem

7=;

#*shback6 Inp*t)tream

(as a one byte %ush' back bu""er so that you can %ush back the last character read.

Inp*t)tream

8enerally used in the scanner "or a co#%iler and %robably included because the Java co#%iler needed it. /ou %robably won t use this.

Writing to an Out utStream with 6ilterOut utStream


The co#%le#ent to ataInp*t)tream is ata.*tp*t)tream, which "or#ats each o" the %ri#itive ty%es and )tring ob0ects onto a strea# in such a way that any ataInp*t)tream, on any #achine, can read the#. 6ll the #ethods start with !write,$ such as (rite2yteA B, (riteFloatA B, etc. RFSURFSTIJLT+(6PTE5MMTILKU The original intent o" #rint)tream was to %rint all o" the %ri#itive data ty%es and )tring ob0ects in a viewable "or#at. This is di""erent "ro# ata.*tp*t)tream, whose goal is to %ut data ele#ents on a strea# in a way that ataInp*t)tream can %ortably reconstruct the#. RFSURF STIJLT+(6PTE5MMTILLU The two i#%ortant #ethods in #rint)tream are printA B and println A B, which are overloaded to %rint all the various ty%es. The di""erence between printA B and printlnA B is that the latter adds a newline when it s done. RFSURFSTIJLT+(6PTE5MMTIL?U

#rint)tream can be %roble#atic because it tra%s all I.&4ceptions */ou #ust e&%licitly test the error status with check&rrorA B, which returns tr*e i" an error has occurred,. 6lso, #rint)tream doesn t internationali1e %ro%erly and doesn t handle line breaks in a %lat"or# inde%endent way *these %roble#s are solved with #rint0riter,. RFSURF STIJLT+(6PTE5MMTILHU

71=

2*ffere'.*tp*t)tream is a #odi"ier and tells the strea# to use bu""ering so you don t get a %hysical write every ti#e you write to the strea#. /ou ll %robably always want to use this with "iles, and %ossibly console IF). RFSURFSTIJLT+(6PTE5MMTIL3U Table >>6Q! Types of Filter.*tp*t)tream -lass F*nction -onstr*ctor Arg*ments Ho( to *se it .*tp*t)tream

ata6 .*tp*t)trea m

4sed in concert with

ataInp*t)tream
so you can write %ri#itives *int, char, long, etc., to a strea# in a %ortable "ashion. Eor %roducing "or#atted out%ut. :hile +ontains "ull inter"ace to allow you to write %ri#itive ty%es. .*tp*t)tream, with o%tional

#rint)tream

boolean
indicating that the bu""er is "lushed with every newline. Should be the !"inal$ wra%%ing "or your

ata.*tp*t)trea m handles the storage o" data, #rint)tream handles dis la).

.*tp*t)tream
ob0ect. /ou ll %robably use this a lot. .*tp*t)tream, with o%tional bu""er si1e. This doesn t %rovide an inter"ace er se, 0ust a reAuire#ent that a bu""er is used. 6ttach an inter"ace ob0ect.

2*ffere'6 .*tp*t)trea m

4se this to %revent a %hysical write every ti#e you send a %iece o" data. /ou re saying !4se a bu""er.$ /ou can call fl*shA B to "lush the bu""er.

Cha ter 11! The Java I/O S)stem

711

5eaders L 4riters
Java M.M #ade so#e signi"icant #odi"ications to the "unda#ental IF) strea# library *Java K, however, did not #ake "unda#ental #odi"ications,. :hen you see the $ea'er and 0riter classes your "irst thought *like #ine, #ight be that these were #eant to re%lace the Inp*t)tream and .*tp*t)tream classes. But that s not the case. 6lthough so#e as%ects o" the original strea#s library are de%recated *i" you use the# you will receive a warning "ro# the co#%iler,, the Inp*t)tream and .*tp*t)tream classes still %rovide valuable "unctionality in the "or# o" byte'oriented IF), while the $ea'er and 0riter classes %rovide 4nicode'co#%liant, character'based IF). In addition= RFSURFSTIJLT+(6PTE5MMTILGU

(74) Java M.M added new classes into the Inp*t)tream and .*tp*t)tream hierarchy, so it s obvious those classes weren t
being re%laced. RFSURFSTIJLT+(6PTE5MMTILIU

(75) There are ti#es when you #ust use classes "ro# the !byte$ hierarchy in combination with classes in the !character$ hierarchy.
To acco#%lish this there are !bridge$ classes= Inp*t)tream$ea'er converts an Inp*t)tream to a $ea'er and .*tp*t)tream0riter converts an .*tp*t)tream to a 0riter. RFSURFSTIJLT+(6PTE5MMTIL2U The #ost i#%ortant reason "or the $ea'er and 0riter hierarchies is "or internationali1ation. The old IF) strea# hierarchy su%%orts only I'bit byte strea#s and doesn t handle the M3'bit 4nicode characters well. Since 4nicode is used "or internationali1ation *and Java s native char is M3'bit 4nicode,, the $ea'er and 0riter hierarchies were added to su%%ort 4nicode in all IF) o%erations. In addition, the new libraries are designed "or "aster o%erations than the old. RFSURFSTIJLT+(6PTE5MMTI?@U 6s is the %ractice in this book, I will atte#%t to %rovide an overview o" the classes, but assu#e that you will use online docu#entation to deter#ine all the details, such as the e&haustive list o" #ethods. RFSURF STIJLT+(6PTE5MMTI?MU

712

1ources and sinks of data


6l#ost all o" the original Java IF) strea# classes have corres%onding $ea'er and 0riter classes to %rovide native 4nicode #ani%ulation. (owever, there are so#e %laces where the byte'oriented Inp*t)treams and .*tp*t)treams are the correct solution; in %articular, the 8ava! *til!7ip libraries are byte'oriented rather than char'oriented. So the #ost sensible a%%roach to take is to tr) to use the $ea'er and 0riter classes whenever you can, and you ll discover the situations when you have to use the byte'oriented libraries because your code won t co#%ile. RFSURFSTIJLT+(6PTE5MMTI?KU (ere is a table that shows the corres%ondence between the sources and sinks o" in"or#ation *that is, where the data %hysically co#es "ro# or goes to, in the two hierarchies.

)o*rces , )inks< Java >!D class Inp*t)tream .*tp*t)tream FileInp*t)tream File.*tp*t)tream )tring2*fferInp*t)trea m
*no corres%onding class,

-orrespon'ing Java >!> class $ea'er


converter=

Inp*t)tream$ea'er 0riter
converter=

.*tp*t)tream0riter File$ea'er File0riter )tring$ea'er )tring0riter -harArray$ea'er -harArray0riter #ipe'$ea'er #ipe'0riter

2yteArrayInp*t)tream 2yteArray.*tp*t)trea m #ipe'Inp*t)tream #ipe'.*tp*t)tream

In general, you ll "ind that the inter"aces "or the two di""erent hierarchies are si#ilar i" not identical.

Cha ter 11! The Java I/O S)stem

713

Modif:ing stream behavior


Eor Inp*t)treams and .*tp*t)treams, strea#s were ada%ted "or %articular needs using !decorator$ subclasses o" FilterInp*t)tream and Filter.*tp*t)tream! The $ea'er and 0riter class hierarchies continue the use o" this idea9but not e&actly. RFSURF STIJLT+(6PTE5MMTI?LU In the "ollowing table, the corres%ondence is a rougher a%%ro&i#ation than in the %revious table. The di""erence is because o" the class organi1ation= while 2*ffere'.*tp*t)tream is a subclass o" Filter.*tp*t)tream, 2*ffere'0riter is not a subclass o" Filter0riter *which, even though it is abstract, has no subclasses and so a%%ears to have been %ut in either as a %laceholder or si#%ly so you wouldn t wonder where it was,. (owever, the inter"aces to the classes are Auite a close #atch.

Filters< Java >!D class FilterInp*t)tream Filter.*tp*t)tream 2*ffere'Inp*t)tream 2*ffere'.*tp*t)tream ataInp*t)tream

-orrespon'ing Java >!> class Filter$ea'er Filter0riter *abstract class


with no subclasses,

2*ffere'$ea'er *also has rea'+ineA B, 2*ffere'0riter 4se ataInp*t)tream


*E&ce%t when you need to use rea'+ineA B, when you should use a 2*ffere'$ea'er,

#rint)tream +ine/*mberInp*t)trea m )treamTokeni7er #*sh2ackInp*t)tream

#rint0riter +ine/*mber$ea'er )treamTokeni7er


*use constructor that takes a $ea'er instead,

#*sh2ack$ea'er

There s one direction that s Auite clear= :henever you want to use rea'+ineA B, you shouldn t do it with a ataInp*t)tream any #ore

714

*this is #et with a de%recation #essage at co#%ile'ti#e,, but instead use a 2*ffere'$ea'er. )ther than this, ataInp*t)tream is still a !%re"erred$ #e#ber o" the IF) library. To #ake the transition to using a #rint0riter easier, it has constructors that take any .*tp*t)tream ob0ect, as well as 0riter ob0ects. (owever, #rint0riter has no #ore su%%ort "or "or#atting than #rint)tream does; the inter"aces are virtually the sa#e. RFSURF STIJLT+(6PTE5MMTI??U The #rint0riter constructor also has an o%tion to %er"or# auto#atic "lushing, which ha%%ens a"ter every printlnA B i" the constructor "lag is set. RFSURFSTIJLT+(6PTE5MMTI?HU

Cnchanged Classes
So#e classes were le"t unchanged between Java M.@ and Java M.M= Java M.@ classes without corres%onding Java M.M classes

ata.*tp*t)tream File $an'omAccessFile )eC*enceInp*t)tream ata.*tp*t)tream, in %articular, is used without change, so "or
storing and retrieving data in a trans%ortable "or#at you use the Inp*t)tream and .*tp*t)tream hierarchies.

Off b: itself: $andomAccess<ile


$an'omAccessFile is used "or "iles containing records o" known si1e so that you can #ove "ro# one record to another using seekA B, then read or
change the records. The records don t have to be the sa#e si1e; you 0ust

Cha ter 11! The Java I/O S)stem

715

have to be able to deter#ine how big they are and where they are %laced in the "ile. RFSURFSTIJLT+(6PTE5MMTI?3U 6t "irst it s a little bit hard to believe that $an'omAccessFile is not %art o" the Inp*t)tream or .*tp*t)tream hierarchy. (owever, it has no association with those hierarchies other than that it ha%%ens to i#%le#ent the ataInp*t and ata.*tp*t inter"aces *which are also i#%le#ented by ataInp*t)tream and ata.*tp*t)tream,. It doesn t even use any o" the "unctionality o" the e&isting Inp*t)tream or .*tp*t)tream classes9it s a co#%letely se%arate class, written "ro# scratch, with all o" its own *#ostly native, #ethods. The reason "or this #ay be that $an'omAccessFile has essentially di""erent behavior than the other IF) ty%es, since you can #ove "orward and backward within a "ile. In any event, it stands alone, as a direct descendant o" .b8ect. RF SURFSTIJLT+(6PTE5MMTI?GU Essentially, a $an'omAccessFile works like a ataInp*t)tream %asted together with a ata.*tp*t)tream, along with the #ethods getFile#ointerA B to "ind out where you are in the "ile, seekA B to #ove to a new %oint in the "ile, and lengthA B to deter#ine the #a&i#u# si1e o" the "ile. In addition, the constructors reAuire a second argu#ent *identical to fopenA B in +, indicating whether you are 0ust rando#ly reading * arb, or reading and writing * ar(b,. There s no su%%ort "or write'only "iles, which could suggest that $an'omAccessFile #ight have worked well i" it were inherited "ro# ataInp*t)tream. RFSURF STIJLT+(6PTE5MMTI?IU The seeking #ethods are available only in $an'omAccessFile, which works "or "iles only. 2*ffere'Inp*t)tream does allow you to markA B a %osition *whose value is held in a single internal variable, and resetA B to that %osition, but this is li#ited and not very use"ul. RFSURF STIJLT+(6PTE5MMTI?2U

717

#:.ical uses of IDO streams


6lthough you can co#bine the IF) strea# classes in #any di""erent ways, you ll %robably 0ust use a "ew co#binations. The "ollowing e&a#%le can be used as a basic re"erence; it shows the creation and use o" ty%ical IF) con"igurations. Cote that each con"iguration begins with a co##ented nu#ber and title that corres%onds to the heading "or the a%%ro%riate e&%lanation that "ollows in the te&t.

//3 c((3$G%trea#De#o.Hava // Ty"ical $/G strea# configurations. i#"ort Hava.io.B< "ublic class $G%trea#De#o @ // Thro: e6ce"tions to console3 "ublic static voi! #ain-%tringNO args. thro:s $GE6ce"tion @ // (. 5ea!ing in"ut by lines3 Buffere!5ea!er in ? ne: Buffere!5ea!erne: Lile5ea!er-8$G%trea#De#o.Hava8..< %tring s, s ? ne: %tring-.< :hile--s ? in.rea!Line-..4? null. s K? s K 8_n8< in.close-.< // (b. 5ea!ing stan!ar! in"ut3 Buffere!5ea!er st!in ? ne: Buffere!5ea!erne: $n"ut%trea#5ea!er-%yste#.in..< %yste#.out."rint-8Enter a line38.< %yste#.out."rintln-st!in.rea!Line-..< // . $n"ut fro# #e#ory %tring5ea!er in ? ne: %tring5ea!er-s .< int c< :hile--c ? in .rea!-.. 4? -(.

Cha ter 11! The Java I/O S)stem

718

%yste#.out."rint--char.c.< // ). Lor#atte! #e#ory in"ut try @ Data$n"ut%trea# in) ? ne: Data$n"ut%trea#ne: Byte0rray$n"ut%trea#-s .getBytes-...< :hile-true. %yste#.out."rint--char.in).rea!Byte-..< A catch-EGLE6ce"tion e. @ %yste#.err."rintln-8En! of strea#8.< A // I. Lile out"ut try @ Buffere!5ea!er inI ? ne: Buffere!5ea!erne: %tring5ea!er-s ..< Print\riter out( ? ne: Print\riterne: Buffere!\riterne: Lile\riter-8$GDe#o.out8...< int lineCount ? (< :hile--s ? inI.rea!Line-.. 4? null . out(."rintln-lineCountKK K 83 8 K s.< out(.close-.< A catch-EGLE6ce"tion e. @ %yste#.err."rintln-8En! of strea#8.< A // ,. %toring D recovering !ata try @ DataGut"ut%trea# out ? ne: DataGut"ut%trea#ne: Buffere!Gut"ut%trea#ne: LileGut"ut%trea#-8Data.t6t8...< out .:riteDouble-).(I(,C.< out .:riteChars:riteYTL-8That :as "i_n8.< out .:riteBytes-8That :as "i_n8.< out .:riteDouble-(.I(I().<

71:

out .:riteYTL-8%=uare root of 8.< out .close-.< Data$n"ut%trea# in, ? ne: Data$n"ut%trea#ne: Buffere!$n"ut%trea#ne: Lile$n"ut%trea#-8Data.t6t8...< Buffere!5ea!er in,br ? ne: Buffere!5ea!erne: $n"ut%trea#5ea!er-in,..< // Just use Data$n"ut%trea# for !ata3 %yste#.out."rintln-in,.rea!Double-..< // Gnly rea!YTL-. :ill recover the // Java-YTL %tring "ro"erly3 // Can no: use the 8"ro"er8 rea!Line-.3 %yste#.out."rintln-in,br.rea!Linerea!YTL-..< // But the line co#es out funny. // The one create! :ith :riteBytes is G`3 %yste#.out."rintln-in,br.rea!Line-..< // 5ea! the follo:ing !ouble an! %tring3 %yste#.out."rintln-in,.rea!Double-..< %yste#.out."rintln-in,.rea!YTL-..< A catch-EGLE6ce"tion e. @ %yste#.err."rintln-8En! of strea#8.< A // +. 5ea!ing/:riting ran!o# access files 5an!o#0ccessLile rf ? ne: 5an!o#0ccessLile-8rtest.!at8, 8r:8.< for-int i ? '< i P ('< iKK. rf.:riteDouble-iB(.I(I.< rf.close-.< rf ? ne: 5an!o#0ccessLile-8rtest.!at8, 8r:8.< rf.seek-,B1.< rf.:riteDouble-I*.'''(.< rf.close-.< rf ? ne: 5an!o#0ccessLile-8rtest.!at8, 8r8.< for-int i ? '< i P ('< iKK.

Cha ter 11! The Java I/O S)stem

71;

%yste#.out."rintln8Walue 8 K i K 83 8 K rf.rea!Double-..< rf.close-.< A A ///3>


(ere are the descri%tions "or the nu#bered sections o" the %rogra#= RF SURFSTIJLT+(6PTE5MMTIH@U

In.ut streams
Parts M through ? de#onstrate the creation and use o" in%ut strea#s. Part ? also shows the si#%le use o" an out%ut strea#.

() ;uffered in.ut file


To o%en a "ile "or character in%ut, you use a FileInp*t$ea'er with a )tring or a File ob0ect as the "ile na#e. Eor s%eed, you ll want that "ile to be bu""ered so you give the resulting re"erence to the constructor "or a 2*ffere'$ea'er. Since 2*ffere'$ea'er also %rovides the rea'+ine A B #ethod, this is your "inal ob0ect and the inter"ace you read "ro#. :hen you reach the end o" the "ile, rea'+ineA B returns n*ll so that is used to break out o" the (hile loo%. RFSURFSTIJLT+(6PTE5MMTIHMU The )tring sI is used to accu#ulate the entire contents o" the "ile *including newlines that #ust be added since rea'+ineA B stri%s the# o"",. sI is then used in the later %ortions o" this %rogra#. Einally, close A B is called to close the "ile. Technically, closeA B will be called when finali7eA B runs, and this is su%%osed to ha%%en *whether or not garbage collection occurs, as the %rogra# e&its. (owever, this has been inconsistently i#%le#ented, so the only sa"e a%%roach is to e&%licitly call closeA B "or "iles. RFSURFSTIJLT+(6PTE5MMTIHKU Section Mb shows how you can wra% )ystem!in "or reading console in%ut. )ystem!in is a ataInp*t)tream and 2*ffere'$ea'er needs a $ea'er argu#ent, so Inp*t)tream$ea'er is brought in to %er"or# the translation. RFSURFSTIJLT+(6PTE5MMTIHLU

72=

!) In.ut from memor:


This section takes the )tring sI that now contains the entire contents o" the "ile and uses it to create a )tring$ea'er. Then rea'A B is used to read each character one at a ti#e and send it out to the console. Cote that rea'A B returns the ne&t byte as an int and thus it #ust be cast to a char to %rint %ro%erly. RFSURFSTIJLT+(6PTE5MMTIH?U

*) <ormatted memor: in.ut


To read !"or#atted$ data, you use a ataInp*t)tream, which is a byte' oriented IF) class *rather than char oriented,. Thus you #ust use all Inp*t)tream classes rather than $ea'er classes. )" course, you can read anything *such as a "ile, as bytes using Inp*t)tream classes, but here a )tring is used. To convert the )tring to an array o" bytes, which is what is a%%ro%riate "or a 2yteArrayInp*t)tream, )tring has a get2ytesA B #ethod to do the 0ob. 6t that %oint, you have an a%%ro%riate Inp*t)tream to hand to ataInp*t)tream. RFSURF STIJLT+(6PTE5MMTIHHU I" you read the characters "ro# a ataInp*t)tream one byte at a ti#e using rea'2yteA B, any byte value is a legiti#ate result so the return value cannot be used to detect the end o" in%ut. Instead, you can use the availableA B #ethod to "ind out how #any #ore characters are available. (ere s an e&a#%le that shows how to read a "ile one byte at a ti#e=

//3 c((3TestEGL.Hava // Testing for the en! of file // :hile rea!ing a byte at a ti#e. i#"ort Hava.io.B< "ublic class TestEGL @ // Thro: e6ce"tions to console3 "ublic static voi! #ain-%tringNO args. thro:s $GE6ce"tion @ Data$n"ut%trea# in ? ne: Data$n"ut%trea#ne: Buffere!$n"ut%trea#ne: Lile$n"ut%trea#-8TestEof.Hava8...< :hile-in.available-. 4? '. %yste#.out."rint--char.in.rea!Byte-..<

Cha ter 11! The Java I/O S)stem

721

A A ///3>
Cote that availableA B works di""erently de%ending on what sort o" #ediu# you re reading "ro#; it s literally !the nu#ber o" bytes that can be read ,ithout blocking.$ :ith a "ile this #eans the whole "ile, but with a di""erent kind o" strea# this #ight not be true, so use it thought"ully. RF SURFSTIJLT+(6PTE5MMTIH3U /ou could also detect the end o" in%ut in cases like these by catching an e&ce%tion. (owever, the use o" e&ce%tions "or control "low is considered a #isuse o" that "eature. RFSURFSTIJLT+(6PTE5MMTIHGU

+) <ile out.ut
This e&a#%le also shows how to write data to a "ile. Eirst, a File0riter is created to connect to the "ile. /ou ll virtually always want to bu""er the out%ut by wra%%ing it in a 2*ffere'0riter *try re#oving this wra%%ing to see the i#%act on the %er"or#ance9bu""ering tends to dra#atically increase %er"or#ance o" IF) o%erations,. Then "or the "or#atting it s turned into a #rint0riter. The data "ile created this way is readable as an ordinary te&t "ile. RFSURFSTIJLT+(6PTE5MMTIHIU 6s the lines are written to the "ile, line nu#bers are added. Cote that +ine/*mberInp*t)tream is not used, because it s a silly class and you don t need it. 6s shown here, it s trivial to kee% track o" your own line nu#bers. RFSURFSTIJLT+(6PTE5MMTIH2U :hen the in%ut strea# is e&hausted, rea'+ineA B returns n*ll. /ou ll see an e&%licit closeA B "or o*t>, because i" you don t call closeA B "or all your out%ut "iles, you #ight discover that the bu""ers don t get "lushed so they re inco#%lete. RFSURFSTIJLT+(6PTE5MMTI3@U

Out.ut streams
The two %ri#ary kinds o" out%ut strea#s are se%arated by the way they write data= one writes it "or hu#an consu#%tion, and the other writes it to be reacAuired by a ataInp*t)tream. The $an'omAccessFile stands alone, although its data "or#at is co#%atible with the

722

ataInp*t)tream and ata.*tp*t)tream. RFSURF STIJLT+(6PTE5MMTI3MU

,) 1toring and recovering data


6 #rint0riter "or#ats data so it s readable by a hu#an. (owever, to out%ut data so that it can be recovered by another strea#, you use a ata.*tp*t)tream to write the data and a ataInp*t)tream to recover the data. )" course, these strea#s could be anything, but here a "ile is used, bu""ered "or both reading and writing. ata.*tp*t)tream and ataInp*t)tream are byte'oriented and thus reAuire the Inp*t)treams and .*tp*t)treams. RFSURF STIJLT+(6PTE5MMTI3KU I" you use a ata.*tp*t)tream to write the data, then Java guarantees that you can accurately recover the data using a ataInp*t)tream9 regardless o" what di""erent %lat"or#s write and read the data. This is incredibly valuable, as anyone knows who has s%ent ti#e worrying about %lat"or#'s%eci"ic data issues. That %roble# vanishes i" you have Java on both %lat"or#s @. RFSURFSTIJLT+(6PTE5MMTI3LU

Cote that the character string is written using both (rite-harsA B and (rite2ytesA B. :hen you run the %rogra#, you ll discover that (rite-harsA B out%uts M3'bit 4nicode characters. :hen you read the line using rea'+ineA B, you ll see that there is a s%ace between each character, because o" the e&tra byte inserted by 4nicode. Since there is no co#%le#entary !read+hars$ #ethod in ataInp*t)tream, you re stuck %ulling these characters o"" one at a ti#e with rea'-harA B. So "or 6S+II, it s easier to write the characters as bytes "ollowed by a newline; then use rea'+ineA B to read back the bytes as a regular 6S+II line.:hen using a ata.*tp*t)tream, the only reliable way to write a )tring so that it can be recovered by a ataInp*t)tream is to use 4TE'I encoding, acco#%lished above using (riteUTFA B and rea'UTFA B. 4TE'I is a variation on 4nicode, which stores all characters in K bytes. I" you re working with 6S+II or #ostly 6S+II characters *which only occu%y G bits,, this is a tre#endous waste o" s%ace andFor bandwidth, so 4TE'I encodes 6S+II characters in a single byte, and non'6S+II characters in
@ ZMD is another way to solve the %roble# o" #oving data across di""erent co#%uting %lat"or#s, and does not de%end on having Java on all %lat"or#s. (owever, Java tools e&ist that su%%ort ZMD.

Cha ter 11! The Java I/O S)stem

723

two or three bytes. In addition, the length o" the string is stored in the "irst two bytes. (owever, (riteUTFA B and rea'UTFA B use a s%ecial variation o" 4TE'I "or Java *which is co#%letely described in the JavaSo"t (TMD docu#entation "or those #ethods, and so i" you read a string written with (riteUTFA B using a non'Java %rogra#, you #ust write s%ecial code in order to read the string %ro%erly. RFSURF
STIJLT+(6PTE5MMTI3?U

:ith (riteUTFA B and rea'UTFA B, you can inter#ingle )trings and other ty%es o" data using a ata.*tp*t)tream with the knowledge that the )trings will be %ro%erly stored as 4nicode, and will be easily recoverable with a ataInp*t)tream. RFSURF
STIJLT+(6PTE5MMTI3HU The (rite o*bleA B stores the 'o*ble nu#ber to the strea# and the co#%le#entary rea' o*bleA B recovers it *there are si#ilar #ethods "or reading and writing the other ty%es,. But "or any o" the reading #ethods to work correctly, you #ust know the e&act %lace#ent o" the data ite# in the strea#, since it would be eAually %ossible to read the stored 'o*ble as a si#%le seAuence o" bytes, or as a char, etc. So you #ust either have a "i&ed "or#at "or the data in the "ile or e&tra in"or#ation #ust be stored in the "ile that you %arse to deter#ine where the data is located. Cote that ob0ect seriali1ation *described later in this

cha%ter, #ay be an easier way to store and retrieve co#%le& data structures. RFSURFSTIJLT+(6PTE5MMTI33U

-) $eading and writing random access files


6s %reviously noted, the $an'omAccessFile is al#ost totally isolated "ro# the rest o" the IF) hierarchy, save "or the "act that it i#%le#ents the ataInp*t and ata.*tp*t inter"aces. So you cannot co#bine it with any o" the as%ects o" the Inp*t)tream and .*tp*t)tream subclasses. Even though it #ight #ake sense to treat a 2yteArrayInp*t)tream as a rando# access ele#ent, you can use $an'omAccessFile to only o%en a "ile. /ou #ust assu#e a $an'omAccessFile is %ro%erly bu""ered since you cannot add that. N5WON5WTIJJX-HA#T&$>>XI\ZO The one o%tion you have is in the second constructor argu#ent= you can o%en a $an'omAccessFile to read * arb, or read and write *ar(b,. RF SURFSTIJLT+(6PTE5MMTI3IU

724

4sing a $an'omAccessFile is like using a co#bined ataInp*t)tream and ata.*tp*t)tream *because it i#%le#ents the eAuivalent inter"aces,. In addition, you can see that seekA B is used to #ove about in the "ile and change one o" the values. RFSURF STIJLT+(6PTE5MMTI32U

A bugAA bugA
I" you look at section H, you ll see that the data is written be$ore the te&t. That s because a %roble# was introduced in Java M.M *and %ersists in Java K, that sure see#s like a bug to #e, but I re%orted it and the bug %eo%le at JavaSo"t said that this is the way it is su%%osed to work *however, the %roble# did not occur in Java M.@, which #akes #e sus%icious,. The %roble# is shown in the "ollowing code= //3 c((3$GProble#.Hava // Java (.( an! higher $/G Proble#. i#"ort Hava.io.B< "ublic class $GProble# @ // Thro: e6ce"tions to console3 "ublic static voi! #ain-%tringNO args. thro:s $GE6ce"tion @ DataGut"ut%trea# out ? ne: DataGut"ut%trea#ne: Buffere!Gut"ut%trea#ne: LileGut"ut%trea#-8Data.t6t8...< out.:riteDouble-).(I(,C.< out.:riteBytes-8That :as the value of "i_n8.< out.:riteBytes-8This is "i/ 3_n8.< out.:riteDouble-).(I(,C/ .< out.close-.< Data$n"ut%trea# in ? ne: Data$n"ut%trea#ne: Buffere!$n"ut%trea#ne: Lile$n"ut%trea#-8Data.t6t8...< Buffere!5ea!er inbr ? ne: Buffere!5ea!erne: $n"ut%trea#5ea!er-in..<

Cha ter 11! The Java I/O S)stem

725

// The !oubles :ritten BELG5E the line of te6t // rea! back correctly3 %yste#.out."rintln-in.rea!Double-..< // 5ea! the lines of te6t3 %yste#.out."rintln-inbr.rea!Line-..< %yste#.out."rintln-inbr.rea!Line-..< // Trying to rea! the !oubles after the line // "ro!uces an en!-of-file e6ce"tion3 %yste#.out."rintln-in.rea!Double-..< A A ///3>

_5e#oved "ro# te&t` *This was a bug in #y reasoning Y I did not understand the intention o" (riteUTFA B and rea'UTFA B. 6lso, creating two bu""ers "or the sa#e strea# turns out to be a big #istake Y the "irst bu""er that you read sucks u% e&tra bytes so the second bu""er gets indeter#inate out%ut,. RFSURFSTIJLT+(6PTE5MMTIG@U

i.ed streams
The #ipe'Inp*t)tream, #ipe'.*tp*t)tream, #ipe'$ea'er and #ipe'0riter have been #entioned only brie"ly in this cha%ter. This is not to suggest that they aren t use"ul, but their value is not a%%arent until you begin to understand #ultithreading, since the %i%ed strea#s are used to co##unicate between threads. This is covered along with an e&a#%le in +ha%ter M?. RFSURFSTIJLT+(6PTE5MMTIGMU

1tandard IDO
The ter# standard I/O re"ers to the 4ni& conce%t *which is re%roduced in so#e "or# in :indows and #any other o%erating syste#s, o" a single strea# o" in"or#ation that is used by a %rogra#. 6ll the %rogra# s in%ut can co#e "ro# standard in ut, all its out%ut can go to standard out ut, and all o" its error #essages can be sent to standard error. The value o" standard IF) is that %rogra#s can easily be chained together and one %rogra# s standard out%ut can beco#e the standard in%ut "or another %rogra#. This is a %ower"ul tool. RFSURFSTIJLT+(6PTE5MMTIGKU

727

$eading from standard in.ut


Eollowing the standard IF) #odel, Java has )ystem!in, )ystem!o*t, and )ystem!err. Throughout this book you ve seen how to write to standard out%ut using )ystem!o*t, which is already %rewra%%ed as a #rint)tream ob0ect. )ystem!err is likewise a #rint)tream, but )ystem!in is a raw Inp*t)tream, with no wra%%ing. This #eans that while you can use )ystem!o*t and )ystem!err right away, )ystem!in #ust be wra%%ed be"ore you can read "ro# it. RFSURF STIJLT+(6PTE5MMTIGLU Ty%ically, you ll want to read in%ut a line at a ti#e using rea'+ineA B, so you ll want to wra% )ystem!in in a 2*ffere'$ea'er. To do this, you #ust convert )ystem!in to a $ea'er using Inp*t)tream$ea'er. (ere s an e&a#%le that si#%ly echoes each line that you ty%e in=

//3 c((3Echo.Hava // Mo: to rea! fro# stan!ar! in"ut. i#"ort Hava.io.B< "ublic class Echo @ "ublic static voi! #ain-%tringNO args. thro:s $GE6ce"tion @ Buffere!5ea!er in ? ne: Buffere!5ea!erne: $n"ut%trea#5ea!er-%yste#.in..< %tring s< :hile--s ? in.rea!Line-...length-. 4? '. %yste#.out."rintln-s.< // 0n e#"ty line ter#inates the "rogra# A A ///3>
The reason "or the e&ce%tion s%eci"ication is that rea'+ineA B can throw an I.&4ception. Cote that )ystem!in should usually be bu""ered, as with #ost strea#s. RFSURFSTIJLT+(6PTE5MMTIG?U

Cha ter 11! The Java I/O S)stem

728

Changing System.out to a 'rint4riter


)ystem!o*t is a #rint)tream, which is an .*tp*t)tream. #rint0riter has a constructor that takes an .*tp*t)tream as an argu#ent. Thus, i" you want you can convert )ystem!o*t into a #rint0riter using that constructor= //3 c((3Change%yste#Gut.Hava // Turn %yste#.out into a Print\riter. i#"ort Hava.io.B< "ublic class Change%yste#Gut @ "ublic static voi! #ain-%tringNO args. @ Print\riter out ? ne: Print\riter-%yste#.out, true.< out."rintln-8Mello, :orl!8.< A A ///3>
It s i#%ortant to use the two'argu#ent version o" the #rint0riter constructor and to set the second argu#ent to tr*e in order to enable auto#atic "lushing, otherwise you #ay not see the out%ut. RFSURF STIJLT+(6PTE5MMTIGHU

$edirecting standard IDO


The Java )ystem class allows you to redirect the standard in%ut, out%ut, and error IF) strea#s using si#%le static #ethod calls=

setInAInp*t)treamB set.*tA#rint)treamB set&rrA#rint)treamB RFSURFSTIJLT+(6PTE5MMTIG3U


5edirecting out%ut is es%ecially use"ul i" you suddenly start creating a large a#ount o" out%ut on your screen and it s scrolling %ast "aster than you can read it. @ 5edirecting in%ut is valuable "or a co##and'line
@ +ha%ter ML shows an even #ore convenient solution "or this= a 84I %rogra# with a scrolling te&t area.

72:

%rogra# in which you want to test a %articular user'in%ut seAuence re%eatedly. (ere s a si#%le e&a#%le that shows the use o" these #ethods=

//3 c((35e!irecting.Hava // De#onstrates stan!ar! $/G re!irection. i#"ort Hava.io.B< "ublic class 5e!irecting @ // Thro: e6ce"tions to console3 "ublic static voi! #ain-%tringNO args. thro:s $GE6ce"tion @ Buffere!$n"ut%trea# in ? ne: Buffere!$n"ut%trea#ne: Lile$n"ut%trea#85e!irecting.Hava8..< Print%trea# out ? ne: Print%trea#ne: Buffere!Gut"ut%trea#ne: LileGut"ut%trea#-8test.out8...< %yste#.set$n-in.< %yste#.setGut-out.< %yste#.setErr-out.< Buffere!5ea!er br ? ne: Buffere!5ea!erne: $n"ut%trea#5ea!er-%yste#.in..< %tring s< :hile--s ? br.rea!Line-.. 4? null. %yste#.out."rintln-s.< out.close-.< // 5e#e#ber this4 A A ///3>
This %rogra# attaches standard in%ut to a "ile, and redirects standard out%ut and standard error to another "ile. RFSURF STIJLT+(6PTE5MMTIGGU IF) redirection #ani%ulates strea#s o" bytes, not strea#s o" characters, thus Inp*t)treams and .*tp*t)treams are used rather than $ea'ers and 0riters. RFSURFSTIJLT+(6PTE5MMTIGIU

Cha ter 11! The Java I/O S)stem

72;

Com.ression
The Java IF) library contains classes to su%%ort reading and writing strea#s in a co#%ressed "or#at. These are wra%%ed around e&isting IF) classes to %rovide co#%ression "unctionality. RFSURF STIJLT+(6PTE5MMTIG2U These classes are not derived "ro# the $ea'er and 0riter classes, but instead are %art o" the Inp*t)tream and .*tp*t)tream hierarchies. This is because the co#%ression library works with bytes, not characters. (owever, you #ight so#eti#es be "orced to #i& the two ty%es o" strea#s. *5e#e#ber that you can use Inp*t)tream$ea'er and .*tp*t)tream0riter to %rovide easy conversion between one ty%e and another.,

-ompression class -hecke'Inp*t)tream -hecke'.*tp*t)trea m eflater.*tp*t)trea m Zip.*tp*t)tream "ZI#.*tp*t)tream InflaterInp*t)tream ZipInp*t)tream "ZI#Inp*t)tream

F*nction "et-heck)*mA B %roduces checksu# "or any Inp*t)tream *not


0ust deco#%ression,. "et-heck)*mA B %roduces checksu# "or any .*tp*t)tream *not 0ust co#%ression,. Base class "or co#%ression classes. 6 eflater.*tp*t)tream that co#%resses data into the Qi% "ile "or#at. 6 eflater.*tp*t)tream that co#%resses data into the 8QIP "ile "or#at. Base class "or deco#%ression classes. 6n InflaterInp*t)tream that deco#%resses data that has been stored in the Qi% "ile "or#at. 6n InflaterInp*t)tream that deco#%resses data that has been stored in the 8QIP "ile "or#at.

73=

6lthough there are #any co#%ression algorith#s, Qi% and 8QIP are %ossibly the #ost co##only used. Thus you can easily #ani%ulate your co#%ressed data with the #any tools available "or reading and writing these "or#ats.

1im.le com.ression with 'QI


The 8QIP inter"ace is si#%le and thus is %robably #ore a%%ro%riate when you have a single strea# o" data that you want to co#%ress *rather than a container o" dissi#ilar %ieces o" data,. (ere s an e&a#%le that co#%resses a single "ile=

//3 c((3aT$Pco#"ress.Hava // Yses aT$P co#"ression to co#"ress a file // :hose na#e is "asse! on the co##an! line. i#"ort Hava.io.B< i#"ort Hava.util.Ui".B< "ublic class aT$Pco#"ress @ // Thro: e6ce"tions to console3 "ublic static voi! #ain-%tringNO args. thro:s $GE6ce"tion @ Buffere!5ea!er in ? ne: Buffere!5ea!erne: Lile5ea!er-argsN'O..< Buffere!Gut"ut%trea# out ? ne: Buffere!Gut"ut%trea#ne: aT$PGut"ut%trea#ne: LileGut"ut%trea#-8test.gU8...< %yste#.out."rintln-8\riting file8.< int c< :hile--c ? in.rea!-.. 4? -(. out.:rite-c.< in.close-.< out.close-.< %yste#.out."rintln-85ea!ing file8.< Buffere!5ea!er in ? ne: Buffere!5ea!erne: $n"ut%trea#5ea!erne: aT$P$n"ut%trea#-

Cha ter 11! The Java I/O S)stem

731

ne: Lile$n"ut%trea#-8test.gU8....< %tring s< :hile--s ? in .rea!Line-.. 4? null. %yste#.out."rintln-s.< A A ///3>


The use o" the co#%ression classes is straight"orward9you si#%ly wra% your out%ut strea# in a "ZI#.*tp*t)tream or Zip.*tp*t)tream and your in%ut strea# in a "ZI#Inp*t)tream or ZipInp*t)tream. 6ll else is ordinary IF) reading and writing. This is an e&a#%le o" #i&ing the char'oriented strea#s with the byte'oriented strea#s= in uses the $ea'er classes, whereas "ZI#.*tp*t)tream s constructor can acce%t only an .*tp*t)tream ob0ect, not a 0riter ob0ect. :hen the "ile is o%ened, the "ZI#Inp*t)tream is converted to a $ea'er. RFSURF STIJLT+(6PTE5MMTII@U

Multifile storage with Qi.


The library that su%%orts the Qi% "or#at is #uch #ore e&tensive. :ith it you can easily store #ulti%le "iles, and there s even a se%arate class to #ake the %rocess o" reading a Qi% "ile easy. The library uses the standard Qi% "or#at so that it works sea#lessly with all the tools currently downloadable on the Internet. The "ollowing e&a#%le has the sa#e "or# as the %revious e&a#%le, but it handles as #any co##and'line argu#ents as you want. In addition, it shows the use o" the -hecks*m classes to calculate and veri"y the checksu# "or the "ile. There are two -hecks*m ty%es= A'lerJI *which is "aster, and -$-JI *which is slower but slightly #ore accurate,. RFSURFSTIJLT+(6PTE5MMTIIMU

//3 c((3Ti"Co#"ress.Hava // Yses Ti" co#"ression to co#"ress any // nu#ber of files given on the co##an! line. i#"ort Hava.io.B< i#"ort Hava.util.B< i#"ort Hava.util.Ui".B< "ublic class Ti"Co#"ress @ // Thro: e6ce"tions to console3 "ublic static voi! #ain-%tringNO args.

732

thro:s $GE6ce"tion @ LileGut"ut%trea# f ? ne: LileGut"ut%trea#-8test.Ui"8.< Checke!Gut"ut%trea# csu# ? ne: Checke!Gut"ut%trea#f, ne: 0!ler) -..< Ti"Gut"ut%trea# out ? ne: Ti"Gut"ut%trea#ne: Buffere!Gut"ut%trea#-csu#..< out.setCo##ent-80 test of Java Ti""ing8.< // &o corres"on!ing getCo##ent-., though. for-int i ? '< i P args.length< iKK. @ %yste#.out."rintln8\riting file 8 K argsNiO.< Buffere!5ea!er in ? ne: Buffere!5ea!erne: Lile5ea!er-argsNiO..< out."ut&e6tEntry-ne: Ti"Entry-argsNiO..< int c< :hile--c ? in.rea!-.. 4? -(. out.:rite-c.< in.close-.< A out.close-.< // Checksu# vali! only after the file // has been close!4 %yste#.out."rintln-8Checksu#3 8 K csu#.getChecksu#-..getWalue-..< // &o: e6tract the files3 %yste#.out."rintln-85ea!ing file8.< Lile$n"ut%trea# fi ? ne: Lile$n"ut%trea#-8test.Ui"8.< Checke!$n"ut%trea# csu#i ? ne: Checke!$n"ut%trea#fi, ne: 0!ler) -..< Ti"$n"ut%trea# in ? ne: Ti"$n"ut%trea#ne: Buffere!$n"ut%trea#-csu#i..< Ti"Entry Ue< :hile--Ue ? in .get&e6tEntry-.. 4? null. @ %yste#.out."rintln-85ea!ing file 8 K Ue.<

Cha ter 11! The Java I/O S)stem

733

int 6< :hile--6 ? in .rea!-.. 4? -(. %yste#.out.:rite-6.< A %yste#.out."rintln-8Checksu#3 8 K csu#i.getChecksu#-..getWalue-..< in .close-.< // 0lternative :ay to o"en an! rea! // Ui" files3 Ti"Lile Uf ? ne: Ti"Lile-8test.Ui"8.< Enu#eration e ? Uf.entries-.< :hile-e.hasJoreEle#ents-.. @ Ti"Entry Ue ? -Ti"Entry.e.ne6tEle#ent-.< %yste#.out."rintln-8Lile3 8 K Ue .< // ... an! e6tract the !ata as before A A A ///3>
Eor each "ile to add to the archive, you #ust call p*t/e4t&ntryA B and %ass it a Zip&ntry ob0ect. The Zip&ntry ob0ect contains an e&tensive inter"ace that allows you to get and set all the data available on that %articular entry in your Qi% "ile= na#e, co#%ressed and unco#%ressed si1es, date, +5+ checksu#, e&tra "ield data, co##ent, co#%ression #ethod, and whether it s a directory entry. (owever, even though the Qi% "or#at has a way to set a %assword, this is not su%%orted in Java s Qi% library. 6nd although -hecke'Inp*t)tream and -hecke'.*tp*t)tream su%%ort both A'lerJI and -$-JI checksu#s, the Zip&ntry class su%%orts only an inter"ace "or +5+. This is a restriction o" the underlying Qi% "or#at, but it #ight li#it you "ro# using the "aster A'lerJI. RFSURFSTIJLT+(6PTE5MMTIIKU To e&tract "iles, ZipInp*t)tream has a get/e4t&ntryA B #ethod that returns the ne&t Zip&ntry i" there is one. 6s a #ore succinct alternative, you can read the "ile using a ZipFile ob0ect, which has a #ethod entries A B to return an &n*meration to the Zip&ntries. RFSURF STIJLT+(6PTE5MMTIILU In order to read the checksu# you #ust so#ehow have access to the associated -hecks*m ob0ect. (ere, a re"erence to the

734

-hecke'.*tp*t)tream and -hecke'Inp*t)tream ob0ects is retained, but you could also 0ust hold onto a re"erence to the -hecks*m
ob0ect. RFSURFSTIJLT+(6PTE5MMTII?U 6 ba""ling #ethod in Qi% strea#s is set-ommentA B. 6s shown above, you can set a co##ent when you re writing a "ile, but there s no way to recover the co##ent in the ZipInp*t)tream. +o##ents a%%ear to be su%%orted "ully on an entry'by'entry basis only via Zip&ntry. RFSURF STIJLT+(6PTE5MMTIIHU )" course, you are not li#ited to "iles when using the "ZI# or Zip libraries9you can co#%ress anything, including data to be sent through a network connection. RFSURFSTIJLT+(6PTE5MMTII3U

"ava A$chives 8"A$s9


The Qi% "or#at is also used in the J65 *Java 65chive, "ile "or#at, which is a way to collect a grou% o" "iles into a single co#%ressed "ile, 0ust like Qi%. (owever, like everything else in Java, J65 "iles are cross'%lat"or# so you don t need to worry about %lat"or# issues. /ou can also include audio and i#age "iles as well as class "iles. RFSURFSTIJLT+(6PTE5MMTIIGU J65 "iles are %articularly hel%"ul when you deal with the Internet. Be"ore J65 "iles, your :eb browser would have to #ake re%eated reAuests o" a :eb server in order to download all o" the "iles that #ake u% an a%%let. In addition, each o" these "iles was unco#%ressed. By co#bining all o" the "iles "or a %articular a%%let into a single J65 "ile, only one server reAuest is necessary and the trans"er is "aster because o" co#%ression. 6nd each entry in a J65 "ile can be digitally signed "or security *re"er to the Java docu#entation "or details,. RFSURFSTIJLT+(6PTE5MMTIIIU 6 J65 "ile consists o" a single "ile containing a collection o" 1i%%ed "iles along with a !#ani"est$ that describes the#. */ou can create your own #ani"est "ile; otherwise the 8ar %rogra# will do it "or you., /ou can "ind out #ore about J65 #ani"ests in the J7> (TMD docu#entation. RFSURF STIJLT+(6PTE5MMTII2U The 8ar utility that co#es with Sun s J7> auto#atically co#%resses the "iles o" your choice. /ou invoke it on the co##and line= RFSURF STIJLT+(6PTE5MMTI2@U

Cha ter 11! The Java I/O S)stem

735

Har No"tionsO !estination N#anifestO in"utfile-s.


The o%tions are si#%ly a collection o" letters *no hy%hen or any other indicator is necessary,. 4ni&FDinu& users will note the si#ilarity to the tar o%tions. These are=

c t 4 4 file f

+reates a new or e#%ty archive. Dists the table o" contents. E&tracts all "iles. E&tracts the na#ed "ile. Says= !I # going to give you the na#e o" the "ile.$ I" you don t use this, 0ar assu#es that its in%ut will co#e "ro# standard in%ut, or, i" it is creating a "ile, its out%ut will go to standard out%ut. Says that the "irst argu#ent will be the na#e o" the user'created #ani"est "ile. 8enerates verbose out%ut describing what 0ar is doing. )nly store the "iles; doesn t co#%ress the "iles *use to create a J65 "ile that you can %ut in your class%ath,. 7on t auto#atically create a #ani"est "ile.

m v D 1

I" a subdirectory is included in the "iles to be %ut into the J65 "ile, that subdirectory is auto#atically added, including all o" its subdirectories, etc. Path in"or#ation is also %reserved. (ere are so#e ty%ical ways to invoke 8ar=

Har cf #yJarLile.Har B.class


This creates a J65 "ile called myJarFile!8ar that contains all o" the class "iles in the current directory, along with an auto#atically generated #ani"est "ile. RFSURFSTIJLT+(6PTE5MMTI2MU

Har c#f #yJarLile.Har #yJanifestLile.#f B.class


Dike the %revious e&a#%le, but adding a user'created #ani"est "ile called

my1anifestFile!mf. RFSURFSTIJLT+(6PTE5MMTI2KU Har tf #yJarLile.Har

737

Produces a table o" contents o" the "iles in myJarFile!8ar. RFSURF STIJLT+(6PTE5MMTI2LU

Har tvf #yJarLile.Har


6dds the !verbose$ "lag to give #ore detailed in"or#ation about the "iles in myJarFile!8ar. RFSURFSTIJLT+(6PTE5MMTI2?U

Har cvf #y0"".Har au!io classes i#age


6ssu#ing a*'io, classes, and image are subdirectories, this co#bines all o" the subdirectories into the "ile myApp!8ar. The !verbose$ "lag is also included to give e&tra "eedback while the 8ar %rogra# is working. RF SURFSTIJLT+(6PTE5MMTI2HU I" you create a J65 "ile using the D o%tion, that "ile can be %laced in your +D6SSP6T(=

CL0%%P0TM?8lib(.Har<lib .Har<8
Then Java can search lib>!8ar and libI!8ar "or class "iles. RFSURF STIJLT+(6PTE5MMTI23U The 8ar tool isn t as use"ul as a 7ip utility. Eor e&a#%le, you can t add or u%date "iles to an e&isting J65 "ile; you can create J65 "iles only "ro# scratch. 6lso, you can t #ove "iles into a J65 "ile, erasing the# as they are #oved. (owever, a J65 "ile created on one %lat"or# will be trans%arently readable by the 8ar tool on any other %lat"or# *a %roble# that so#eti#es %lagues 7ip utilities,. RFSURFSTIJLT+(6PTE5MMTI2GU 6s you will see in +ha%ter ML, J65 "iles are also used to %ackage JavaBeans. RFSURFSTIJLT+(6PTE5MMTI2IU

Ob3ect seriali?ation
Java s ob>ect seriali?ation allows you to take any ob0ect that i#%le#ents the )eriali7able inter"ace and turn it into a seAuence o" bytes that can later be "ully restored to regenerate the original ob0ect. This is even true across a network, which #eans that the seriali1ation #echanis# auto#atically co#%ensates "or di""erences in o%erating syste#s. That is, you can create an ob0ect on a :indows #achine, seriali1e it, and send it

Cha ter 11! The Java I/O S)stem

738

across the network to a 4ni& #achine where it will be correctly reconstructed. /ou don t have to worry about the data re%resentations on the di""erent #achines, the byte ordering, or any other details. RFSURF STIJLT+(6PTE5MMTI22U By itsel", ob0ect seriali1ation is interesting because it allows you to i#%le#ent light,eight ersistence. 5e#e#ber that %ersistence #eans an ob0ect s li"eti#e is not deter#ined by whether a %rogra# is e&ecuting9 the ob0ect lives in bet,een invocations o" the %rogra#. By taking a seriali1able ob0ect and writing it to disk, then restoring that ob0ect when the %rogra# is reinvoked, you re able to %roduce the e""ect o" %ersistence. The reason it s called !lightweight$ is that you can t si#%ly de"ine an ob0ect using so#e kind o" !%ersistent$ keyword and let the syste# take care o" the details *although this #ight ha%%en in the "uture,. Instead, you #ust e&%licitly seriali1e and deseriali1e the ob0ects in your %rogra#. RFSURFSTIJLT+(6PTE5MMTIM@@U )b0ect seriali1ation was added to the language to su%%ort two #a0or "eatures. Java s remote method invocation *5MI, allows ob0ects that live on other #achines to behave as i" they live on your #achine. :hen sending #essages to re#ote ob0ects, ob0ect seriali1ation is necessary to trans%ort the argu#ents and return values. 5MI is discussed in +ha%ter MH. RFSURFSTIJLT+(6PTE5MMTIM@MU )b0ect seriali1ation is also necessary "or JavaBeans, described in +ha%ter ML. :hen a Bean is used, its state in"or#ation is generally con"igured at design'ti#e. This state in"or#ation #ust be stored and later recovered when the %rogra# is started; ob0ect seriali1ation %er"or#s this task. RF SURFSTIJLT+(6PTE5MMTIM@KU Seriali1ing an ob0ect is Auite si#%le, as long as the ob0ect i#%le#ents the

)eriali7able inter"ace *this inter"ace is 0ust a "lag and has no #ethods,.


:hen seriali1ation was added to the language, #any standard library classes were changed to #ake the# seriali1able, including all o" the wra%%ers "or the %ri#itive ty%es, all o" the container classes, and #any others. Even -lass ob0ects can be seriali1ed. *See +ha%ter MK "or the i#%lications o" this., RFSURFSTIJLT+(6PTE5MMTIM@LU To seriali1e an ob0ect, you create so#e sort o" .*tp*t)tream ob0ect and then wra% it inside an .b8ect.*tp*t)tream ob0ect. 6t this %oint you

73:

need only call (rite.b8ectA B and your ob0ect is seriali1ed and sent to the .*tp*t)tream. To reverse the %rocess, you wra% an Inp*t)tream inside an .b8ectInp*t)tream and call rea'.b8ectA B. :hat co#es back is, as usual, a re"erence to an u%cast .b8ect, so you #ust downcast to set things straight. RFSURFSTIJLT+(6PTE5MMTIM@?U 6 %articularly clever as%ect o" ob0ect seriali1ation is that it not only saves an i#age o" your ob0ect but it also "ollows all the re"erences contained in your ob0ect and saves those ob0ects, and "ollows all the re"erences in each o" those ob0ects, etc. This is so#eti#es re"erred to as the !web o" ob0ects$ that a single ob0ect can be connected to, and it includes arrays o" re"erences to ob0ects as well as #e#ber ob0ects. I" you had to #aintain your own ob0ect seriali1ation sche#e, #aintaining the code to "ollow all these links would be a bit #ind'boggling. (owever, Java ob0ect seriali1ation see#s to %ull it o"" "lawlessly, no doubt using an o%ti#i1ed algorith# that traverses the web o" ob0ects. The "ollowing e&a#%le tests the seriali1ation #echanis# by #aking a !wor#$ o" linked ob0ects, each o" which has a link to the ne&t seg#ent in the wor# as well as an array o" re"erences to ob0ects o" a di""erent class, ata=

//3 c((3\or#.Hava // De#onstrates obHect serialiUation. i#"ort Hava.io.B< class Data i#"le#ents %erialiUable @ "rivate int i< Data-int 6. @ i ? 6< A "ublic %tring to%tring-. @ return $nteger.to%tring-i.< A A "ublic class \or# i#"le#ents %erialiUable @ // aenerate a ran!o# int value3 "rivate static int r-. @ return -int.-Jath.ran!o#-. B ('.< A "rivate DataNO ! ? @ ne: Data-r-.., ne: Data-r-.., ne: Data-r-.. A<

Cha ter 11! The Java I/O S)stem

73;

"rivate \or# ne6t< "rivate char c< // Walue of i ?? nu#ber of seg#ents \or#-int i, char 6. @ %yste#.out."rintln-8 \or# constructor3 8 K i.< c ? 6< if---i Q '. ne6t ? ne: \or#-i, -char.-6 K (..< A \or#-. @ %yste#.out."rintln-8Default constructor8.< A "ublic %tring to%tring-. @ %tring s ? 838 K c K 8-8< for-int i ? '< i P !.length< iKK. s K? !NiO.to%tring-.< s K? 8.8< if-ne6t 4? null. s K? ne6t.to%tring-.< return s< A // Thro: e6ce"tions to console3 "ublic static voi! #ain-%tringNO args. thro:s Class&otLoun!E6ce"tion, $GE6ce"tion @ \or# : ? ne: \or#-+, 2a2.< %yste#.out."rintln-8: ? 8 K :.< GbHectGut"ut%trea# out ? ne: GbHectGut"ut%trea#ne: LileGut"ut%trea#-8:or#.out8..< out.:riteGbHect-8\or# storage8.< out.:riteGbHect-:.< out.close-.< // 0lso flushes out"ut GbHect$n"ut%trea# in ? ne: GbHect$n"ut%trea#ne: Lile$n"ut%trea#-8:or#.out8..< %tring s ? -%tring.in.rea!GbHect-.< \or# : ? -\or#.in.rea!GbHect-.< %yste#.out."rintln-s K 8, : ? 8 K : .< Byte0rrayGut"ut%trea# bout ? ne: Byte0rrayGut"ut%trea#-.< GbHectGut"ut%trea# out ?

74=

ne: GbHectGut"ut%trea#-bout.< out .:riteGbHect-8\or# storage8.< out .:riteGbHect-:.< out .flush-.< GbHect$n"ut%trea# in ? ne: GbHect$n"ut%trea#ne: Byte0rray$n"ut%trea#bout.toByte0rray-...< s ? -%tring.in .rea!GbHect-.< \or# :) ? -\or#.in .rea!GbHect-.< %yste#.out."rintln-s K 8, :) ? 8 K :).< A A ///3>
To #ake things interesting, the array o" ata ob0ects inside 0orm are initiali1ed with rando# nu#bers. *This way you don t sus%ect the co#%iler o" kee%ing so#e kind o" #eta'in"or#ation., Each 0orm seg#ent is labeled with a char that s auto#atically generated in the %rocess o" recursively generating the linked list o" 0orms. :hen you create a 0orm, you tell the constructor how long you want it to be. To #ake the ne4t re"erence it calls the 0orm constructor with a length o" one less, etc. The "inal ne4t re"erence is le"t as n*ll, indicating the end o" the 0orm. RFSURFSTIJLT+(6PTE5MMTIM@HU The %oint o" all this was to #ake so#ething reasonably co#%le& that couldn t easily be seriali1ed. The act o" seriali1ing, however, is Auite si#%le. )nce the .b8ect.*tp*t)tream is created "ro# so#e other strea#, (rite.b8ectA B seriali1es the ob0ect. Cotice the call to (rite.b8ectA B "or a )tring, as well. /ou can also write all the %ri#itive data ty%es using the sa#e #ethods as ata.*tp*t)tream *they share the sa#e inter"ace,. RFSURFSTIJLT+(6PTE5MMTIM@3U There are two se%arate code sections that look si#ilar. The "irst writes and reads a "ile and the second, "or variety, writes and reads a 2yteArray. /ou can read and write an ob0ect using seriali1ation to any ataInp*t)tream or ata.*tp*t)tream including, as you will see in the +ha%ter MH, a network. The out%ut "ro# one run was=

\or# constructor3 + \or# constructor3 , \or# constructor3 I

Cha ter 11! The Java I/O S)stem

741

\or# constructor3 ) \or# constructor3 \or# constructor3 ( : ? 3a- + .3b-(''.3c-)C+.3!-I1'.3e-)(+.3f-)C1. \or# storage, : ? 3a- + .3b-(''.3c-)C+.3!-I1'.3e -)(+.3f-)C1. \or# storage, :) ? 3a- + .3b-(''.3c-)C+.3!-I1'.3e -)(+.3f-)C1.
/ou can see that the deseriali1ed ob0ect really does contain all o" the links that were in the original ob0ect. RFSURFSTIJLT+(6PTE5MMTIM@GU Cote that no constructor, not even the de"ault constructor, is called in the %rocess o" deseriali1ing a )eriali7able ob0ect. The entire ob0ect is restored by recovering data "ro# the Inp*t)tream. RFSURF STIJLT+(6PTE5MMTIM@IU )b0ect seriali1ation is byte'oriented, and thus uses the Inp*t)tream and .*tp*t)tream hierarchies. RFSURFSTIJLT+(6PTE5MMTIM@2U

<inding the class


/ou #ight wonder what s necessary "or an ob0ect to be recovered "ro# its seriali1ed state. Eor e&a#%le, su%%ose you seriali1e an ob0ect and send it as a "ile or through a network to another #achine. +ould a %rogra# on the other #achine reconstruct the ob0ect using only the contents o" the "ileO RFSURFSTIJLT+(6PTE5MMTIMM@U The best way to answer this Auestion is *as usual, by %er"or#ing an e&%eri#ent. The "ollowing "ile goes in the subdirectory "or this cha%ter= RFSURFSTIJLT+(6PTE5MMTIMMMU

//3 c((30lien.Hava // 0 serialiUable class. i#"ort Hava.io.B< "ublic class 0lien i#"le#ents %erialiUable @ A ///3>
The "ile that creates and seriali1es an Alien ob0ect goes in the sa#e directory= RFSURFSTIJLT+(6PTE5MMTIMMKU

742

//3 c((3LreeUe0lien.Hava // Create a serialiUe! out"ut file. i#"ort Hava.io.B< "ublic class LreeUe0lien @ // Thro: e6ce"tions to console3 "ublic static voi! #ain-%tringNO args. thro:s $GE6ce"tion @ GbHectGut"ut out ? ne: GbHectGut"ut%trea#ne: LileGut"ut%trea#-89.file8..< 0lien Uorcon ? ne: 0lien-.< out.:riteGbHect-Uorcon.< A A ///3>
5ather than catching and handling e&ce%tions, this %rogra# takes the Auick and dirty a%%roach o" %assing the e&ce%tions out o" mainA B, so they ll be re%orted on the co##and line. RFSURF STIJLT+(6PTE5MMTIMMLU )nce the %rogra# is co#%iled and run, co%y the resulting X!file to a subdirectory called 4files, where the "ollowing code goes= RFSURF STIJLT+(6PTE5MMTIMM?U

//3 c((36files3Tha:0lien.Hava // Try to recover a serialiUe! file :ithout the // class of obHect that2s store! in that file. i#"ort Hava.io.B< "ublic class Tha:0lien @ "ublic static voi! #ain-%tringNO args. thro:s $GE6ce"tion, Class&otLoun!E6ce"tion @ GbHect$n"ut%trea# in ? ne: GbHect$n"ut%trea#ne: Lile$n"ut%trea#-89.file8..< GbHect #ystery ? in.rea!GbHect-.< %yste#.out."rintln-#ystery.getClass-..< A A ///3>

Cha ter 11! The Java I/O S)stem

743

This %rogra# o%ens the "ile and reads in the ob0ect mystery success"ully. (owever, as soon as you try to "ind out anything about the ob0ect9which reAuires the -lass ob0ect "or Alien9the Java Virtual Machine *JVM, cannot "ind Alien!class *unless it ha%%ens to be in the +lass%ath, which it shouldn t be in this e&a#%le,. /ou ll get a -lass/otFo*n'&4ception! *)nce again, all evidence o" alien li"e vanishes be"ore %roo" o" its e&istence can be veri"ied., RFSURF STIJLT+(6PTE5MMTIMMHU I" you e&%ect to do #uch a"ter you ve recovered an ob0ect that has been seriali1ed, you #ust #ake sure that the JVM can "ind the associated ! class "ile either in the local class %ath or so#ewhere on the Internet. RF SURFSTIJLT+(6PTE5MMTIMM3U

Controlling seriali?ation
6s you can see, the de"ault seriali1ation #echanis# is trivial to use. But what i" you have s%ecial needsO Perha%s you have s%ecial security issues and you don t want to seriali1e %ortions o" your ob0ect, or %erha%s it 0ust doesn t #ake sense "or one subob0ect to be seriali1ed i" that %art needs to be created anew when the ob0ect is recovered. RFSURF STIJLT+(6PTE5MMTIMMGU /ou can control the %rocess o" seriali1ation by i#%le#enting the

&4ternali7able inter"ace instead o" the )eriali7able inter"ace. The &4ternali7able inter"ace e&tends the )eriali7able inter"ace and adds two #ethods, (rite&4ternalA B and rea'&4ternalA B, that are
auto#atically called "or your ob0ect during seriali1ation and deseriali1ation so that you can %er"or# your s%ecial o%erations. RFSURF STIJLT+(6PTE5MMTIMMIU The "ollowing e&a#%le shows si#%le i#%le#entations o" the &4ternali7able inter"ace #ethods. Cote that 2lip> and 2lipI are nearly identical e&ce%t "or a subtle di""erence *see i" you can discover it by looking at the code,=

//3 c((3Bli"s.Hava // %i#"le use of E6ternaliUable D a "itfall. i#"ort Hava.io.B< i#"ort Hava.util.B<

744

class Bli"( i#"le#ents E6ternaliUable @ "ublic Bli"(-. @ %yste#.out."rintln-8Bli"( Constructor8.< A "ublic voi! :riteE6ternal-GbHectGut"ut out. thro:s $GE6ce"tion @ %yste#.out."rintln-8Bli"(.:riteE6ternal8.< A "ublic voi! rea!E6ternal-GbHect$n"ut in. thro:s $GE6ce"tion, Class&otLoun!E6ce"tion @ %yste#.out."rintln-8Bli"(.rea!E6ternal8.< A A class Bli" i#"le#ents E6ternaliUable @ Bli" -. @ %yste#.out."rintln-8Bli" Constructor8.< A "ublic voi! :riteE6ternal-GbHectGut"ut out. thro:s $GE6ce"tion @ %yste#.out."rintln-8Bli" .:riteE6ternal8.< A "ublic voi! rea!E6ternal-GbHect$n"ut in. thro:s $GE6ce"tion, Class&otLoun!E6ce"tion @ %yste#.out."rintln-8Bli" .rea!E6ternal8.< A A "ublic class Bli"s @ // Thro: e6ce"tions to console3 "ublic static voi! #ain-%tringNO args. thro:s $GE6ce"tion, Class&otLoun!E6ce"tion @ %yste#.out."rintln-8Constructing obHects38.< Bli"( b( ? ne: Bli"(-.< Bli" b ? ne: Bli" -.< GbHectGut"ut%trea# o ? ne: GbHectGut"ut%trea#ne: LileGut"ut%trea#-8Bli"s.out8..< %yste#.out."rintln-8%aving obHects38.< o.:riteGbHect-b(.<

Cha ter 11! The Java I/O S)stem

745

o.:riteGbHect-b .< o.close-.< // &o: get the# back3 GbHect$n"ut%trea# in ? ne: GbHect$n"ut%trea#ne: Lile$n"ut%trea#-8Bli"s.out8..< %yste#.out."rintln-85ecovering b(38.< b( ? -Bli"(.in.rea!GbHect-.< // GGP%4 Thro:s an e6ce"tion3 //4 %yste#.out."rintln-85ecovering b 38.< //4 b ? -Bli" .in.rea!GbHect-.< A A ///3>
The out%ut "or this %rogra# is= RFSURFSTIJLT+(6PTE5MMTIMM2U

Constructing obHects3 Bli"( Constructor Bli" Constructor %aving obHects3 Bli"(.:riteE6ternal Bli" .:riteE6ternal 5ecovering b(3 Bli"( Constructor Bli"(.rea!E6ternal
The reason that the 2lipI ob0ect is not recovered is that trying to do so causes an e&ce%tion. +an you see the di""erence between 2lip> and 2lipIO The constructor "or 2lip> is p*blic, while the constructor "or 2lipI is not, and that causes the e&ce%tion u%on recovery. Try #aking 2lipI s constructor p*blic and re#oving the 55= co##ents to see the correct results. RFSURFSTIJLT+(6PTE5MMTIMK@U

747

:hen b> is recovered, the 2lip> de"ault constructor is called. This is di""erent "ro# recovering a )eriali7able ob0ect, in which the ob0ect is constructed entirely "ro# its stored bits, with no constructor calls. :ith an &4ternali7able ob0ect, all the nor#al de"ault construction behavior occurs *including the initiali1ations at the %oint o" "ield de"inition,, and then rea'&4ternalA B is called. /ou need to be aware o" this9in %articular, the "act that all the de"ault construction always takes %lace9to %roduce the correct behavior in your &4ternali7able ob0ects. RFSURF STIJLT+(6PTE5MMTIMKMU (ere s an e&a#%le that shows what you #ust do to "ully store and retrieve an &4ternali7able ob0ect= RFSURFSTIJLT+(6PTE5MMTIMKKU

//3 c((3Bli").Hava // 5econstructing an e6ternaliUable obHect. i#"ort Hava.io.B< i#"ort Hava.util.B< "ublic class Bli") i#"le#ents E6ternaliUable @ int i< %tring s< // &o initialiUation "ublic Bli")-. @ %yste#.out."rintln-8Bli") Constructor8.< // s, i not initialiUe! A "ublic Bli")-%tring 6, int a. @ %yste#.out."rintln-8Bli")-%tring 6, int a.8.< s ? 6< i ? a< // s D i initialiUe! only in non!efault // constructor. A "ublic %tring to%tring-. @ return s K i< A "ublic voi! :riteE6ternal-GbHectGut"ut out. thro:s $GE6ce"tion @ %yste#.out."rintln-8Bli").:riteE6ternal8.< // ;ou #ust !o this3 out.:riteGbHect-s.< out.:rite$nt-i.< A "ublic voi! rea!E6ternal-GbHect$n"ut in.

Cha ter 11! The Java I/O S)stem

748

thro:s $GE6ce"tion, Class&otLoun!E6ce"tion @ %yste#.out."rintln-8Bli").rea!E6ternal8.< // ;ou #ust !o this3 s ? -%tring.in.rea!GbHect-.< i ?in.rea!$nt-.< A "ublic static voi! #ain-%tringNO args. thro:s $GE6ce"tion, Class&otLoun!E6ce"tion @ %yste#.out."rintln-8Constructing obHects38.< Bli") b) ? ne: Bli")-80 %tring 8, I*.< %yste#.out."rintln-b).< GbHectGut"ut%trea# o ? ne: GbHectGut"ut%trea#ne: LileGut"ut%trea#-8Bli").out8..< %yste#.out."rintln-8%aving obHect38.< o.:riteGbHect-b).< o.close-.< // &o: get it back3 GbHect$n"ut%trea# in ? ne: GbHect$n"ut%trea#ne: Lile$n"ut%trea#-8Bli").out8..< %yste#.out."rintln-85ecovering b)38.< b) ? -Bli").in.rea!GbHect-.< %yste#.out."rintln-b).< A A ///3>
The "ields s and i are initiali1ed only in the second constructor, but not in the de"ault constructor. This #eans that i" you don t initiali1e s and i in rea'&4ternalA B, it will be n*ll *since the storage "or the ob0ect gets wi%ed to 1ero in the "irst ste% o" ob0ect creation,. I" you co##ent out the two lines o" code "ollowing the %hrases !/ou #ust do this$ and run the %rogra#, you ll see that when the ob0ect is recovered, s is n*ll and i is 1ero. RFSURFSTIJLT+(6PTE5MMTIMKLU I" you are inheriting "ro# an &4ternali7able ob0ect, you ll ty%ically call the base'class versions o" (rite&4ternalA B and rea'&4ternalA B to %rovide %ro%er storage and retrieval o" the base'class co#%onents. RF SURFSTIJLT+(6PTE5MMTIMK?U

74:

So to #ake things work correctly you #ust not only write the i#%ortant data "ro# the ob0ect during the (rite&4ternalA B #ethod *there is no de"ault behavior that writes any o" the #e#ber ob0ects "or an &4ternali7able ob0ect,, but you #ust also recover that data in the rea'&4ternalA B #ethod. This can be a bit con"using at "irst because the de"ault construction behavior "or an &4ternali7able ob0ect can #ake it see# like so#e kind o" storage and retrieval takes %lace auto#atically. It does not. RFSURFSTIJLT+(6PTE5MMTIMKHU

#he transient ke:word


:hen you re controlling seriali1ation, there #ight be a %articular subob0ect that you don t want Java s seriali1ation #echanis# to auto#atically save and restore. This is co##only the case i" that subob0ect re%resents sensitive in"or#ation that you don t want to seriali1e, such as a %assword. Even i" that in"or#ation is private in the ob0ect, once it s seriali1ed it s %ossible "or so#eone to access it by reading a "ile or interce%ting a network trans#ission. RFSURF STIJLT+(6PTE5MMTIMK3U )ne way to %revent sensitive %arts o" your ob0ect "ro# being seriali1ed is to i#%le#ent your class as &4ternali7able, as shown %reviously. Then nothing is auto#atically seriali1ed and you can e&%licitly seriali1e only the necessary %arts inside (rite&4ternalA B. RFSURF STIJLT+(6PTE5MMTIMKGU I" you re working with a )eriali7able ob0ect, however, all seriali1ation ha%%ens auto#atically. To control this, you can turn o"" seriali1ation on a "ield'by'"ield basis using the transient keyword, which says !7on t bother saving or restoring this9I ll take care o" it.$ RFSURF STIJLT+(6PTE5MMTIMKIU Eor e&a#%le, consider a +ogin ob0ect that kee%s in"or#ation about a %articular login session. Su%%ose that, once you veri"y the login, you want to store the data, but without the %assword. The easiest way to do this is by i#%le#enting )eriali7able and #arking the pass(or' "ield as transient. (ere s what it looks like=

//3 c((3Logon.Hava // De#onstrates the 8transient8 key:or!.

Cha ter 11! The Java I/O S)stem

74;

i#"ort Hava.io.B< i#"ort Hava.util.B< "ublic class Logon i#"le#ents %erialiUable @ "rivate Date !ate ? ne: Date-.< "rivate %tring userna#e< "rivate transient %tring "ass:or!< Logon-%tring na#e, %tring ":!. @ userna#e ? na#e< "ass:or! ? ":!< A "ublic %tring to%tring-. @ %tring ":! ? -"ass:or! ?? null. [ 8-n/a.8 3 "ass:or!< return 8logon info3 _n 8 K 8userna#e3 8 K userna#e K 8_n !ate3 8 K !ate K 8_n "ass:or!3 8 K ":!< A "ublic static voi! #ain-%tringNO args. thro:s $GE6ce"tion, Class&otLoun!E6ce"tion @ Logon a ? ne: Logon-8Mulk8, 8#yLittlePony8.< %yste#.out."rintln- 8logon a ? 8 K a.< GbHectGut"ut%trea# o ? ne: GbHectGut"ut%trea#ne: LileGut"ut%trea#-8Logon.out8..< o.:riteGbHect-a.< o.close-.< // Delay3 int secon!s ? ,< long t ? %yste#.currentTi#eJillis-. K secon!s B ('''< :hile-%yste#.currentTi#eJillis-. P t. < // &o: get the# back3 GbHect$n"ut%trea# in ? ne: GbHect$n"ut%trea#ne: Lile$n"ut%trea#-8Logon.out8..< %yste#.out."rintln85ecovering obHect at 8 K ne: Date-..< a ? -Logon.in.rea!GbHect-.<

75=

%yste#.out."rintln- 8logon a ? 8 K a.< A A ///3>


/ou can see that the 'ate and *sername "ields are ordinary *not transient,, and thus are auto#atically seriali1ed. (owever, the pass(or' is transient, and so is not stored to disk; also the seriali1ation #echanis# #akes no atte#%t to recover it. The out%ut is= RF SURFSTIJLT+(6PTE5MMTIMK2U

logon a ? logon info3 userna#e3 Mulk !ate3 %un Jar ) (13 ,3,) P%T (CC* "ass:or!3 #yLittlePony 5ecovering obHect at %un Jar ) (13 ,3,C P%T (CC* logon a ? logon info3 userna#e3 Mulk !ate3 %un Jar ) (13 ,3,) P%T (CC* "ass:or!3 -n/a.
:hen the ob0ect is recovered, the pass(or' "ield is n*ll. Cote that to)tringA B #ust check "or a n*ll value o" pass(or' because i" you try to asse#ble a )tring ob0ect using the overloaded [L o%erator, and that o%erator encounters a n*ll re"erence, you ll get a /*ll#ointer&4ception! *Cewer versions o" Java #ight contain code to avoid this %roble#., RFSURFSTIJLT+(6PTE5MMTIML@U /ou can also see that the 'ate "ield is stored to and recovered "ro# disk and not generated anew. RFSURFSTIJLT+(6PTE5MMTIMLMU Since &4ternali7able ob0ects do not store any o" their "ields by de"ault, the transient keyword is "or use with )eriali7able ob0ects only. RF SURFSTIJLT+(6PTE5MMTIMLKU

An alternative to E-ternali0able
I" you re not keen on i#%le#enting the &4ternali7able inter"ace, there s another a%%roach. /ou can i#%le#ent the )eriali7able inter"ace and add *notice I say !add$ and not !override$ or !i#%le#ent$, #ethods called (rite.b8ectA B and rea'.b8ectA B that will auto#atically be called when the ob0ect is seriali1ed and deseriali1ed, res%ectively. That is,

Cha ter 11! The Java I/O S)stem

751

i" you %rovide these two #ethods they will be used instead o" the de"ault seriali1ation. RFSURFSTIJLT+(6PTE5MMTIMLLU The #ethods #ust have these e&act signatures=

"rivate voi! :riteGbHect-GbHectGut"ut%trea# strea#. thro:s $GE6ce"tion< "rivate voi! rea!GbHect-GbHect$n"ut%trea# strea#. thro:s $GE6ce"tion, Class&otLoun!E6ce"tion
Ero# a design stand%oint, things get really weird here. Eirst o" all, you #ight think that because these #ethods are not %art o" a base class or the )eriali7able inter"ace, they ought to be de"ined in their own inter"ace*s,. But notice that they are de"ined as private, which #eans they are to be called only by other #e#bers o" this class. (owever, you don t actually call the# "ro# other #e#bers o" this class, but instead the (rite.b8ect A B and rea'.b8ectA B #ethods o" the .b8ect.*tp*t)tream and .b8ectInp*t)tream ob0ects call your ob0ect s (rite.b8ectA B and rea'.b8ectA B #ethods. *Cotice #y tre#endous restraint in not launching into a long diatribe about using the sa#e #ethod na#es here. In a word= con"using., /ou #ight wonder how the .b8ect.*tp*t)tream and .b8ectInp*t)tream ob0ects have access to private #ethods o" your class. :e can only assu#e that this is %art o" the seriali1ation #agic. RFSURFSTIJLT+(6PTE5MMTIML?U In any event, anything de"ined in an interface is auto#atically p*blic so i" (rite.b8ectA B and rea'.b8ectA B #ust be private, then they can t be %art o" an interface. Since you #ust "ollow the signatures e&actly, the e""ect is the sa#e as i" you re i#%le#enting an interface. RFSURF STIJLT+(6PTE5MMTIMLHU It would a%%ear that when you call .b8ect.*tp*t)tream!(rite.b8ect A B, the )eriali7able ob0ect that you %ass it to is interrogated *using re"lection, no doubt, to see i" it i#%le#ents its own (rite.b8ectA B. I" so, the nor#al seriali1ation %rocess is ski%%ed and the (rite.b8ectA B is called. The sa#e sort o" situation e&ists "or rea'.b8ectA B. RFSURF STIJLT+(6PTE5MMTIML3U

752

There s one other twist. Inside your (rite.b8ectA B, you can choose to %er"or# the de"ault (rite.b8ectA B action by calling 'efa*lt0rite.b8ectA B. Dikewise, inside rea'.b8ectA B you can call 'efa*lt$ea'.b8ectA B. (ere is a si#%le e&a#%le that de#onstrates how you can control the storage and retrieval o" a )eriali7able ob0ect=

//3 c((3%erialCtl.Hava // Controlling serialiUation by a!!ing your o:n // :riteGbHect-. an! rea!GbHect-. #etho!s. i#"ort Hava.io.B< "ublic class %erialCtl i#"le#ents %erialiUable @ %tring a< transient %tring b< "ublic %erialCtl-%tring aa, %tring bb. @ a ? 8&ot Transient3 8 K aa< b ? 8Transient3 8 K bb< A "ublic %tring to%tring-. @ return a K 8_n8 K b< A "rivate voi! :riteGbHect-GbHectGut"ut%trea# strea#. thro:s $GE6ce"tion @ strea#.!efault\riteGbHect-.< strea#.:riteGbHect-b.< A "rivate voi! rea!GbHect-GbHect$n"ut%trea# strea#. thro:s $GE6ce"tion, Class&otLoun!E6ce"tion @ strea#.!efault5ea!GbHect-.< b ? -%tring.strea#.rea!GbHect-.< A "ublic static voi! #ain-%tringNO args. thro:s $GE6ce"tion, Class&otLoun!E6ce"tion @ %erialCtl sc ? ne: %erialCtl-8Test(8, 8Test 8.< %yste#.out."rintln-8Before3_n8 K sc.< Byte0rrayGut"ut%trea# buf ? ne: Byte0rrayGut"ut%trea#-.< GbHectGut"ut%trea# o ?

Cha ter 11! The Java I/O S)stem

753

ne: GbHectGut"ut%trea#-buf.< o.:riteGbHect-sc.< // &o: get it back3 GbHect$n"ut%trea# in ? ne: GbHect$n"ut%trea#ne: Byte0rray$n"ut%trea#buf.toByte0rray-...< %erialCtl sc ? -%erialCtl.in.rea!GbHect-.< %yste#.out."rintln-80fter3_n8 K sc .< A A ///3>
In this e&a#%le, one )tring "ield is ordinary and the other is transient, to %rove that the non' transient "ield is saved by the 'efa*lt0rite.b8ectA B #ethod and the transient "ield is saved and restored e&%licitly. The "ields are initiali1ed inside the constructor rather than at the %oint o" de"inition to %rove that they are not being initiali1ed by so#e auto#atic #echanis# during deseriali1ation. RFSURF STIJLT+(6PTE5MMTIMLGU I" you are going to use the de"ault #echanis# to write the non' transient %arts o" your ob0ect, you #ust call 'efa*lt0rite.b8ectA B as the "irst o%eration in (rite.b8ectA B and 'efa*lt$ea'.b8ectA B as the "irst o%eration in rea'.b8ectA B. These are strange #ethod calls. It would a%%ear, "or e&a#%le, that you are calling 'efa*lt0rite.b8ectA B "or an .b8ect.*tp*t)tream and %assing it no argu#ents, and yet it so#ehow turns around and knows the re"erence to your ob0ect and how to write all the non' transient %arts. S%ooky. RFSURFSTIJLT+(6PTE5MMTIMLIU The storage and retrieval o" the transient ob0ects uses #ore "a#iliar code. 6nd yet, think about what ha%%ens here. In mainA B, a )erial-tl ob0ect is created, and then it s seriali1ed to an .b8ect.*tp*t)tream! *Cotice in this case that a bu""er is used instead o" a "ile9it s all the sa#e to the .b8ect.*tp*t)tream., The seriali1ation occurs in the line=

o.:riteGbHect-sc.<
The (rite.b8ectA B #ethod #ust be e&a#ining sc to see i" it has its own (rite.b8ectA B #ethod. *Cot by checking the inter"ace9there isn t one9 or the class ty%e, but by actually hunting "or the #ethod using re"lection., I" it does, it uses that. 6 si#ilar a%%roach holds true "or rea'.b8ectA B.

754

Perha%s this was the only %ractical way that they could solve the %roble#, but it s certainly strange. RFSURFSTIJLT+(6PTE5MMTIML2U

=ersioning
It s %ossible that you #ight want to change the version o" a seriali1able class *ob0ects o" the original class #ight be stored in a database, "or e&a#%le,. This is su%%orted but you ll %robably do it only in s%ecial cases, and it reAuires an e&tra de%th o" understanding that we will not atte#%t to achieve here. The J7> (TMD docu#ents downloadable "ro# >ava' sun'com cover this to%ic Auite thoroughly. RFSURF STIJLT+(6PTE5MMTIM?@U /ou will also notice in the J7> (TMD docu#entation #any co##ents that begin with=

,arning. Seriali?ed ob>ects o$ this class ,ill not be com atible ,ith $uture S,ing releases' The current seriali?ation su ort is a ro riate $or short term storage or -MI bet,een a lications' M
This is because the versioning #echanis# is too si#%le to work reliably in all situations, es%ecially with JavaBeans. They re working on a correction "or the design, and that s what the warning is about. RFSURF STIJLT+(6PTE5MMTIM?MU

Csing .ersistence
It s Auite a%%ealing to use seriali1ation technology to store so#e o" the state o" your %rogra# so that you can easily restore the %rogra# to the current state later. But be"ore you can do this, so#e Auestions #ust be answered. :hat ha%%ens i" you seriali1e two ob0ects that both have a re"erence to a third ob0ectO :hen you restore those two ob0ects "ro# their seriali1ed state, do you get only one occurrence o" the third ob0ectO :hat i" you seriali1e your two ob0ects to se%arate "iles and deseriali1e the# in di""erent %arts o" your codeO RFSURFSTIJLT+(6PTE5MMTIM?KU (ere s an e&a#%le that shows the %roble#=

//3 c((3Jy\orl!.Hava i#"ort Hava.io.B< i#"ort Hava.util.B<

Cha ter 11! The Java I/O S)stem

755

class Mouse i#"le#ents %erialiUable @A class 0ni#al i#"le#ents %erialiUable @ %tring na#e< Mouse "referre!Mouse< 0ni#al-%tring n#, Mouse h. @ na#e ? n#< "referre!Mouse ? h< A "ublic %tring to%tring-. @ return na#e K 8N8 K su"er.to%tring-. K 8O, 8 K "referre!Mouse K 8_n8< A A "ublic class Jy\orl! @ "ublic static voi! #ain-%tringNO args. thro:s $GE6ce"tion, Class&otLoun!E6ce"tion @ Mouse house ? ne: Mouse-.< 0rrayList ani#als ? ne: 0rrayList-.< ani#als.a!!ne: 0ni#al-8Bosco the !og8, house..< ani#als.a!!ne: 0ni#al-85al"h the ha#ster8, house..< ani#als.a!!ne: 0ni#al-8Lronk the cat8, house..< %yste#.out."rintln-8ani#als3 8 K ani#als.< Byte0rrayGut"ut%trea# buf( ? ne: Byte0rrayGut"ut%trea#-.< GbHectGut"ut%trea# o( ? ne: GbHectGut"ut%trea#-buf(.< o(.:riteGbHect-ani#als.< o(.:riteGbHect-ani#als.< // \rite a // \rite to a !ifferent strea#3 Byte0rrayGut"ut%trea# buf ? ne: Byte0rrayGut"ut%trea#-.< GbHectGut"ut%trea# o ? ne: GbHectGut"ut%trea#-buf .< o .:riteGbHect-ani#als.<

n! set

757

// &o: get the# back3 GbHect$n"ut%trea# in( ? ne: GbHect$n"ut%trea#ne: Byte0rray$n"ut%trea#buf(.toByte0rray-...< GbHect$n"ut%trea# in ? ne: GbHect$n"ut%trea#ne: Byte0rray$n"ut%trea#buf .toByte0rray-...< 0rrayList ani#als( ? -0rrayList.in(.rea!GbHect-.< 0rrayList ani#als ? -0rrayList.in(.rea!GbHect-.< 0rrayList ani#als) ? -0rrayList.in .rea!GbHect-.< %yste#.out."rintln-8ani#als(3 8 K ani#als(.< %yste#.out."rintln-8ani#als 3 8 K ani#als .< %yste#.out."rintln-8ani#als)3 8 K ani#als).< A A ///3>
)ne thing that s interesting here is that it s %ossible to use ob0ect seriali1ation to and "ro# a byte array as a way o" doing a !dee% co%y$ o" any ob0ect that s )eriali7able! *6 dee% co%y #eans that you re du%licating the entire web o" ob0ects, rather than 0ust the basic ob0ect and its re"erences., +o%ying is covered in de%th in 6%%endi& 6. RFSURF STIJLT+(6PTE5MMTIM?LU

Animal ob0ects contain "ields o" ty%e Ho*se. In mainA B, an Array+ist o" these Animals is created and it is seriali1ed twice to one strea# and then again to a se%arate strea#. :hen these are deseriali1ed and %rinted, you see the "ollowing results "or one run *the ob0ects will be in di""erent #e#ory locations each run,= ani#als3 NBosco the !ogN0ni#alR(cc*+cO, MouseR(cc*+C , 5al"h the ha#sterN0ni#alR(cc*+!O, MouseR(cc*+C , Lronk the catN0ni#alR(cc*+eO, MouseR(cc*+C O ani#als(3 NBosco the !ogN0ni#alR(cca'cO, MouseR(cca(+ , 5al"h the ha#sterN0ni#alR(cca(*O, MouseR(cca(+ , Lronk the catN0ni#alR(cca(bO, MouseR(cca(+

Cha ter 11! The Java I/O S)stem

758

O ani#als 3 NBosco the !ogN0ni#alR(cca'cO, MouseR(cca(+ , 5al"h the ha#sterN0ni#alR(cca(*O, MouseR(cca(+ , Lronk the catN0ni#alR(cca(bO, MouseR(cca(+ O ani#als)3 NBosco the !ogN0ni#alR(cca, O, MouseR(cca,c , 5al"h the ha#sterN0ni#alR(cca,!O, MouseR(cca,c , Lronk the catN0ni#alR(cca+(O, MouseR(cca,c O
)" course you e&%ect that the deseriali1ed ob0ects have di""erent addresses "ro# their originals. But notice that in animals> and animalsI the sa#e addresses a%%ear, including the re"erences to the Ho*se ob0ect that both share. )n the other hand, when animalsJ is recovered the syste# has no way o" knowing that the ob0ects in this other strea# are aliases o" the ob0ects in the "irst strea#, so it #akes a co#%letely di""erent web o" ob0ects. RFSURFSTIJLT+(6PTE5MMTIM??U 6s long as you re seriali1ing everything to a single strea#, you ll be able to recover the sa#e web o" ob0ects that you wrote, with no accidental du%lication o" ob0ects. )" course, you can change the state o" your ob0ects in between the ti#e you write the "irst and the last, but that s your res%onsibility9the ob0ects will be written in whatever state they are in *and with whatever connections they have to other ob0ects, at the ti#e you seriali1e the#. RFSURFSTIJLT+(6PTE5MMTIM?HU The sa"est thing to do i" you want to save the state o" a syste# is to seriali1e as an !ato#ic$ o%eration. I" you seriali1e so#e things, do so#e other work, and seriali1e so#e #ore, etc., then you will not be storing the syste# sa"ely. Instead, %ut all the ob0ects that co#%rise the state o" your syste# in a single container and si#%ly write that container out in one o%eration. Then you can restore it with a single #ethod call as well. RF SURFSTIJLT+(6PTE5MMTIM?3U The "ollowing e&a#%le is an i#aginary co#%uter'aided design *+67, syste# that de#onstrates the a%%roach. In addition, it throws in the issue o" static "ields9i" you look at the docu#entation you ll see that -lass is )eriali7able, so it should be easy to store the static "ields by si#%ly seriali1ing the -lass ob0ect. That see#s like a sensible a%%roach, anyway.

//3 c((3C0D%tate.Hava

75:

// %aving an! restoring the state of a // "reten! C0D syste#. i#"ort Hava.io.B< i#"ort Hava.util.B< abstract class %ha"e i#"le#ents %erialiUable @ "ublic static final int 5ED ? (, BLYE ? , a5EE& ? )< "rivate int 6Pos, yPos, !i#ension< "rivate static 5an!o# r ? ne: 5an!o#-.< "rivate static int counter ? '< abstract "ublic voi! setColor-int ne:Color.< abstract "ublic int getColor-.< "ublic %ha"e-int 6Wal, int yWal, int !i#. @ 6Pos ? 6Wal< yPos ? yWal< !i#ension ? !i#< A "ublic %tring to%tring-. @ return getClass-. K 8 colorN8 K getColor-. K 8O 6PosN8 K 6Pos K 8O yPosN8 K yPos K 8O !i#N8 K !i#ension K 8O_n8< A "ublic static %ha"e ran!o#Lactory-. @ int 6Wal ? r.ne6t$nt-. V (''< int yWal ? r.ne6t$nt-. V (''< int !i# ? r.ne6t$nt-. V (''< s:itch-counterKK V ). @ !efault3 case '3 return ne: Circle-6Wal, yWal, !i#.< case (3 return ne: %=uare-6Wal, yWal, !i#.< case 3 return ne: Line-6Wal, yWal, !i#.< A A A class Circle e6ten!s %ha"e @ "rivate static int color ? 5ED< "ublic Circle-int 6Wal, int yWal, int !i#. @

Cha ter 11! The Java I/O S)stem

75;

su"er-6Wal, yWal, !i#.< A "ublic voi! setColor-int ne:Color. @ color ? ne:Color< A "ublic int getColor-. @ return color< A A class %=uare e6ten!s %ha"e @ "rivate static int color< "ublic %=uare-int 6Wal, int yWal, int !i#. @ su"er-6Wal, yWal, !i#.< color ? 5ED< A "ublic voi! setColor-int ne:Color. @ color ? ne:Color< A "ublic int getColor-. @ return color< A A class Line e6ten!s %ha"e @ "rivate static int color ? 5ED< "ublic static voi! serialiUe%tatic%tate-GbHectGut"ut%trea# os. thro:s $GE6ce"tion @ os.:rite$nt-color.< A "ublic static voi! !eserialiUe%tatic%tate-GbHect$n"ut%trea# os. thro:s $GE6ce"tion @ color ? os.rea!$nt-.< A "ublic Line-int 6Wal, int yWal, int !i#. @ su"er-6Wal, yWal, !i#.< A "ublic voi! setColor-int ne:Color. @ color ? ne:Color<

77=

A "ublic int getColor-. @ return color< A A "ublic class C0D%tate @ "ublic static voi! #ain-%tringNO args. thro:s E6ce"tion @ 0rrayList sha"eTy"es, sha"es< if-args.length ?? '. @ sha"eTy"es ? ne: 0rrayList-.< sha"es ? ne: 0rrayList-.< // 0!! references to the class obHects3 sha"eTy"es.a!!-Circle.class.< sha"eTy"es.a!!-%=uare.class.< sha"eTy"es.a!!-Line.class.< // Jake so#e sha"es3 for-int i ? '< i P ('< iKK. sha"es.a!!-%ha"e.ran!o#Lactory-..< // %et all the static colors to a5EE&3 for-int i ? '< i P ('< iKK. --%ha"e.sha"es.get-i.. .setColor-%ha"e.a5EE&.< // %ave the state vector3 GbHectGut"ut%trea# out ? ne: GbHectGut"ut%trea#ne: LileGut"ut%trea#-8C0D%tate.out8..< out.:riteGbHect-sha"eTy"es.< Line.serialiUe%tatic%tate-out.< out.:riteGbHect-sha"es.< A else @ // There2s a co##an!-line argu#ent GbHect$n"ut%trea# in ? ne: GbHect$n"ut%trea#ne: Lile$n"ut%trea#-argsN'O..< // 5ea! in the sa#e or!er they :ere :ritten3 sha"eTy"es ? -0rrayList.in.rea!GbHect-.< Line.!eserialiUe%tatic%tate-in.< sha"es ? -0rrayList.in.rea!GbHect-.< A // Dis"lay the sha"es3

Cha ter 11! The Java I/O S)stem

771

%yste#.out."rintln-sha"es.< A A ///3>
The )hape class implements )eriali7able, so anything that is inherited "ro# )hape is auto#atically )eriali7able as well. Each )hape contains data, and each derived )hape class contains a static "ield that deter#ines the color o" all o" those ty%es o" )hapes. *Placing a static "ield in the base class would result in only one "ield, since static "ields are not du%licated in derived classes., Methods in the base class can be overridden to set the color "or the various ty%es * static #ethods are not dyna#ically bound, so these are nor#al #ethods,. The ran'omFactoryA B #ethod creates a di""erent )hape each ti#e you call it, using rando# values "or the )hape data. RFSURF STIJLT+(6PTE5MMTIM?GU

-ircle and )C*are are straight"orward e&tensions o" )hape; the only di""erence is that -ircle initiali1es color at the %oint o" de"inition and )C*are initiali1es it in the constructor. :e ll leave the discussion o" +ine "or later. RFSURFSTIJLT+(6PTE5MMTIM?IU
In mainA B, one Array+ist is used to hold the -lass ob0ects and the other to hold the sha%es. I" you don t %rovide a co##and line argu#ent the shapeTypes Array+ist is created and the -lass ob0ects are added, and then the shapes Array+ist is created and )hape ob0ects are added. Ce&t, all the static color values are set to "$&&/, and everything is seriali1ed to the "ile -A )tate!o*t. RFSURFSTIJLT+(6PTE5MMTIM?2U I" you %rovide a co##and line argu#ent *%resu#ably -A )tate!o*t,, that "ile is o%ened and used to restore the state o" the %rogra#. In both situations, the resulting Array+ist o" )hapes is %rinted. The results "ro# one run are=

QHava C0D%tate Nclass Circle colorN)O 6PosN-,(O yPosN-CCO !i#N)1O , class %=uare colorN)O 6PosN O yPosN+(O !i#N-I+O , class Line colorN)O 6PosN,(O yPosN*)O !i#N+IO , class Circle colorN)O 6PosN-*'O yPosN(O !i#N(+O , class %=uare colorN)O 6PosN)O yPosNCIO !i#N-)+O , class Line colorN)O 6PosN-1IO yPosN- (O !i#N-),O , class Circle colorN)O 6PosN-*,O yPosN-I)O !i#N O

772

, class %=uare colorN)O 6PosN1(O yPosN)'O !i#N-I,O , class Line colorN)O 6PosN- CO yPosNC O !i#N(*O , class Circle colorN)O 6PosN(*O yPosNC'O !i#N-*+O O QHava C0D%tate C0D%tate.out Nclass Circle colorN(O 6PosN-,(O yPosN-CCO !i#N)1O , class %=uare colorN'O 6PosN O yPosN+(O !i#N-I+O , class Line colorN)O 6PosN,(O yPosN*)O !i#N+IO , class Circle colorN(O 6PosN-*'O yPosN(O !i#N(+O , class %=uare colorN'O 6PosN)O yPosNCIO !i#N-)+O , class Line colorN)O 6PosN-1IO yPosN- (O !i#N-),O , class Circle colorN(O 6PosN-*,O yPosN-I)O !i#N O , class %=uare colorN'O 6PosN1(O yPosN)'O !i#N-I,O , class Line colorN)O 6PosN- CO yPosNC O !i#N(*O , class Circle colorN(O 6PosN(*O yPosNC'O !i#N-*+O O
/ou can see that the values o" 4#os, y#os, and 'im were all stored and recovered success"ully, but there s so#ething wrong with the retrieval o" the static in"or#ation. It s all !L$ going in, but it doesn t co#e out that way. -ircles have a value o" M * $& , which is the de"inition,, and )C*ares have a value o" @ *re#e#ber, they are initiali1ed in the constructor,. It s as i" the statics didn t get seriali1ed at all. That s right9 even though class -lass is )eriali7able, it doesn t do what you e&%ect. So i" you want to seriali1e statics, you #ust do it yoursel". RFSURF STIJLT+(6PTE5MMTIMH@U This is what the seriali7e)tatic)tateA B and 'eseriali7e)tatic)tate A B static #ethods in +ine are "or. /ou can see that they are e&%licitly called as %art o" the storage and retrieval %rocess. *Cote that the order o" writing to the seriali1e "ile and reading back "ro# it #ust be #aintained., Thus to #ake -A )tate!8ava run correctly you #ust= RFSURF STIJLT+(6PTE5MMTIMHMU

(76) 6dd a seriali7e)tatic)tateA B and 'eseriali7e)tatic)tateA B to


the sha%es.

((7) 5e#ove the Array+ist shapeTypes and all code related to it.

Cha ter 11! The Java I/O S)stem

773

((() 6dd calls to the new seriali1e and deseriali1e static #ethods in the
sha%es. RFSURFSTIJLT+(6PTE5MMTIMHKU 6nother issue you #ight have to think about is security, since seriali1ation also saves private data. I" you have a security issue, those "ields should be #arked as transient. But then you have to design a secure way to store that in"or#ation so that when you do a restore you can reset those private variables. RFSURFSTIJLT+(6PTE5MMTIMHLU

#okeni?ing in.ut
Tokeni?ing is the %rocess o" breaking a seAuence o" characters into a seAuence o" !tokens,$ which are bits o" te&t deli#ited by whatever you choose. Eor e&a#%le, your tokens could be words, and then they would be deli#ited by white s%ace and %unctuation. There are two classes %rovided in the standard Java library that can be used "or tokeni1ation= )treamTokeni7er and )tringTokeni7er. RFSURF STIJLT+(6PTE5MMTIMH?U

Stream&okeni0er
6lthough )treamTokeni7er is not derived "ro# Inp*t)tream or .*tp*t)tream, it works only with Inp*t)tream ob0ects, so it right"ully belongs in the IF) %ortion o" the library. RFSURF STIJLT+(6PTE5MMTIMHHU +onsider a %rogra# to count the occurrence o" words in a te&t "ile=

//3 c((3\or!Count.Hava // Counts :or!s fro# a file, out"uts // results in sorte! for#. i#"ort Hava.io.B< i#"ort Hava.util.B< class Counter @ "rivate int i ? (< int rea!-. @ return i< A voi! incre#ent-. @ iKK< A A

774

"ublic class \or!Count @ "rivate Lile5ea!er file< "rivate %trea#TokeniUer st< // 0 TreeJa" kee"s keys in sorte! or!er3 "rivate TreeJa" counts ? ne: TreeJa"-.< \or!Count-%tring filena#e. thro:s Lile&otLoun!E6ce"tion @ try @ file ? ne: Lile5ea!er-filena#e.< st ? ne: %trea#TokeniUerne: Buffere!5ea!er-file..< st.or!inaryChar-2.2.< st.or!inaryChar-2-2.< A catch-Lile&otLoun!E6ce"tion e. @ %yste#.err."rintln8Coul! not o"en 8 K filena#e.< thro: e< A A voi! cleanu"-. @ try @ file.close-.< A catch-$GE6ce"tion e. @ %yste#.err."rintln8file.close-. unsuccessful8.< A A voi! count\or!s-. @ try @ :hile-st.ne6tToken-. 4? %trea#TokeniUer.TTbEGL. @ %tring s< s:itch-st.tty"e. @ case %trea#TokeniUer.TTbEGL3 s ? ne: %tring-8EGL8.< break< case %trea#TokeniUer.TTb&YJBE53 s ? Double.to%tring-st.nval.< break< case %trea#TokeniUer.TTb\G5D3

Cha ter 11! The Java I/O S)stem

775

s ? st.sval< // 0lrea!y a %tring break< !efault3 // single character in tty"e s ? %tring.valueGf--char.st.tty"e.< A if-counts.contains`ey-s.. --Counter.counts.get-s...incre#ent-.< else counts."ut-s, ne: Counter-..< A A catch-$GE6ce"tion e. @ %yste#.err."rintln8st.ne6tToken-. unsuccessful8.< A A Collection values-. @ return counts.values-.< A %et key%et-. @ return counts.key%et-.< A Counter getCounter-%tring s. @ return -Counter.counts.get-s.< A "ublic static voi! #ain-%tringNO args. thro:s Lile&otLoun!E6ce"tion @ \or!Count :c ? ne: \or!Count-argsN'O.< :c.count\or!s-.< $terator keys ? :c.key%et-..iterator-.< :hile-keys.has&e6t-.. @ %tring key ? -%tring.keys.ne6t-.< %yste#.out."rintln-key K 83 8 K :c.getCounter-key..rea!-..< A :c.cleanu"-.< A A ///3>
Presenting the words in sorted "or# is easy to do by storing the data in a Tree1ap, which auto#atically organi1es its keys in sorted order *see +ha%ter 2,. :hen you get a set o" keys using key)etA B, they will also be in sorted order. RFSURFSTIJLT+(6PTE5MMTIMH3U

777

To o%en the "ile, a File$ea'er is used, and to turn the "ile into words a )treamTokeni7er is created "ro# the File$ea'er wra%%ed in a 2*ffere'$ea'er. In )treamTokeni7er, there is a de"ault list o" se%arators, and you can add #ore with a set o" #ethods. (ere, or'inary-harA B is used to say !This character has no signi"icance that I # interested in,$ so the %arser doesn t include it as %art o" any o" the words that it creates. Eor e&a#%le, saying st!or'inary-harAc!cB #eans that %eriods will not be included as %arts o" the words that are %arsed. /ou can "ind #ore in"or#ation in the J7> (TMD docu#entation "ro# >ava'sun'com. RFSURFSTIJLT+(6PTE5MMTIMHGU In co*nt0or'sA B, the tokens are %ulled one at a ti#e "ro# the strea#, and the ttype in"or#ation is used to deter#ine what to do with each token, since a token can be an end'o"'line, a nu#ber, a string, or a single character. RFSURFSTIJLT+(6PTE5MMTIMHIU )nce a token is "ound, the Tree1ap co*nts is Aueried to see i" it already contains the token as a key. I" it does, the corres%onding -o*nter ob0ect is incre#ented to indicate that another instance o" this word has been "ound. I" not, a new -o*nter is created9since the -o*nter constructor initiali1es its value to one, this also acts to count the word. RFSURF STIJLT+(6PTE5MMTIMH2U

0or'-o*nt is not a ty%e o" Tree1ap, so it wasn t inherited. It %er"or#s a s%eci"ic ty%e o" "unctionality, so even though the keysA B and val*esA B #ethods #ust be ree&%osed, that still doesn t #ean that inheritance should be used since a nu#ber o" Tree1ap #ethods are ina%%ro%riate here. In addition, other #ethods like get-o*nterA B, which get the -o*nter "or a %articular )tring, and sorte'%eysA B, which %roduces an Iterator, "inish the change in the sha%e o" 0or'-o*nt s inter"ace. RFSURFSTIJLT+(6PTE5MMTIM3@U
In mainA B you can see the use o" a 0or'-o*nt to o%en and count the words in a "ile9it 0ust takes two lines o" code. Then an Iterator to a sorted list o" keys *words, is e&tracted, and this is used to %ull out each key and associated -o*nt. The call to clean*pA B is necessary to ensure that the "ile is closed. RFSURFSTIJLT+(6PTE5MMTIM3MU

Cha ter 11! The Java I/O S)stem

778

String&okeni0er
6lthough it isn t %art o" the IF) library, the )tringTokeni7er has su""iciently si#ilar "unctionality to )treamTokeni7er that it will be described here. RFSURFSTIJLT+(6PTE5MMTIM3KU The )tringTokeni7er returns the tokens within a string one at a ti#e. These tokens are consecutive characters deli#ited by tabs, s%aces, and newlines. Thus, the tokens o" the string !:here is #y catO$ are !:here$, !is$, !#y$, and !catO$ Dike the )treamTokeni7er, you can tell the )tringTokeni7er to break u% the in%ut in any way that you want, but with )tringTokeni7er you do this by %assing a second argu#ent to the constructor, which is a )tring o" the deli#iters you wish to use. In general, i" you need #ore so%histication, use a )treamTokeni7er. RF SURFSTIJLT+(6PTE5MMTIM3LU /ou ask a )tringTokeni7er ob0ect "or the ne&t token in the string using the ne4tTokenA B #ethod, which either returns the token or an e#%ty string to indicate that no tokens re#ain. RFSURF STIJLT+(6PTE5MMTIM3?U 6s an e&a#%le, the "ollowing %rogra# %er"or#s a li#ited analysis o" a sentence, looking "or key %hrase seAuences to indicate whether ha%%iness or sadness is i#%lied.

//3 c((30nalyUe%entence.Hava // Look for "articular se=uences in sentences. i#"ort Hava.util.B< "ublic class 0nalyUe%entence @ "ublic static voi! #ain-%tringNO args. @ analyUe-8$ a# ha""y about this8.< analyUe-8$ a# not ha""y about this8.< analyUe-8$ a# not4 $ a# ha""y8.< analyUe-8$ a# sa! about this8.< analyUe-8$ a# not sa! about this8.< analyUe-8$ a# not4 $ a# sa!8.< analyUe-80re you ha""y about this[8.< analyUe-80re you sa! about this[8.< analyUe-8$t2s you4 $ a# ha""y8.< analyUe-8$t2s you4 $ a# sa!8.<

77:

A static %tringTokeniUer st< static voi! analyUe-%tring s. @ "rt-8_nne: sentence QQ 8 K s.< boolean sa! ? false< st ? ne: %tringTokeniUer-s.< :hile -st.hasJoreTokens-.. @ %tring token ? ne6t-.< // Look until you fin! one of the // t:o starting tokens3 if-4token.e=uals-8$8. DD 4token.e=uals-80re8.. continue< // To" of :hile loo" if-token.e=uals-8$8.. @ %tring tk ? ne6t-.< if-4tk .e=uals-8a#8.. // Just be after $ break< // Gut of :hile loo" else @ %tring tk) ? ne6t-.< if-tk).e=uals-8sa!8.. @ sa! ? true< break< // Gut of :hile loo" A if -tk).e=uals-8not8.. @ %tring tkI ? ne6t-.< if-tkI.e=uals-8sa!8.. break< // Leave sa! false if-tkI.e=uals-8ha""y8.. @ sa! ? true< break< A A A A if-token.e=uals-80re8.. @ %tring tk ? ne6t-.< if-4tk .e=uals-8you8.. break< // Just be after 0re %tring tk) ? ne6t-.< if-tk).e=uals-8sa!8.. sa! ? true<

Cha ter 11! The Java I/O S)stem

77;

break< // Gut of :hile loo" A A if-sa!. "rt-8%a! !etecte!8.< A static %tring ne6t-. @ if-st.hasJoreTokens-.. @ %tring s ? st.ne6tToken-.< "rt-s.< return s< A else return 88< A static voi! "rt-%tring s. @ %yste#.out."rintln-s.< A A ///3>
Eor each string being analy1ed, a (hile loo% is entered and tokens are %ulled o"" the string. Cotice the "irst if state#ent, which says to contin*e *go back to the beginning o" the loo% and start again, i" the token is neither an !I$ nor an !6re.$ This #eans that it will get tokens until an !I$ or an !6re$ is "ound. /ou #ight think to use the PP instead o" the eC*als A B #ethod, but that won t work correctly, since PP co#%ares re"erence values while eC*alsA B co#%ares contents. RFSURF STIJLT+(6PTE5MMTIM3HU The logic o" the rest o" the analy7eA B #ethod is that the %attern that s being searched "or is !I a# sad,$ !I a# not ha%%y,$ or !6re you sadO$ :ithout the break state#ent, the code "or this would be even #essier than it is. /ou should be aware that a ty%ical %arser *this is a %ri#itive e&a#%le o" one, nor#ally has a table o" these tokens and a %iece o" code that #oves through the states in the table as new tokens are read. RFSURF STIJLT+(6PTE5MMTIM33U /ou should think o" the )tringTokeni7er only as shorthand "or a si#%le and s%eci"ic kind o" )treamTokeni7er. (owever, i" you have a )tring that you want to tokeni1e and )tringTokeni7er is too li#ited, all you have to do is turn it into a strea# with )tring2*fferInp*t)tream and

78=

then use that to create a #uch #ore %ower"ul )treamTokeni7er. RF SURFSTIJLT+(6PTE5MMTIM3GU

Checking ca.itali?ation st:le


In this section we ll look at a #ore co#%lete e&a#%le o" the use o" Java IF ), which also uses tokeni1ation. This %ro0ect is directly use"ul because it %er"or#s a style check to #ake sure that your ca%itali1ation con"or#s to the Java style as "ound at >ava'sun'com/docs/codeconv/inde*'html. It o%ens each !8ava "ile in the current directory and e&tracts all the class na#es and identi"iers, then shows you i" any o" the# don t #eet the Java style. RFSURFSTIJLT+(6PTE5MMTIM3IU Eor the %rogra# to o%erate correctly, you #ust "irst build a class na#e re%ository to hold all the class na#es in the standard Java library. /ou do this by #oving into all the source code subdirectories "or the standard Java library and running -lass)canner in each subdirectory. Provide as argu#ents the na#e o" the re%ository "ile *using the sa#e %ath and na#e each ti#e, and the 6a co##and'line o%tion to indicate that the class na#es should be added to the re%ository. RFSURF STIJLT+(6PTE5MMTIM32U To use the %rogra# to check your code, hand it the %ath and na#e o" the re%ository to use. It will check all the classes and identi"iers in the current directory and tell you which ones don t "ollow the ty%ical Java ca%itali1ation style. RFSURFSTIJLT+(6PTE5MMTIMG@U /ou should be aware that the %rogra# isn t %er"ect; there are a "ew ti#es when it will %oint out what it thinks is a %roble# but on looking at the code you ll see that nothing needs to be changed. This is a little annoying, but it s still #uch easier than trying to "ind all these cases by staring at your code.

//3 c((3Class%canner.Hava // %cans all files in !irectory for classes // an! i!entifiers, to check ca"italiUation. // 0ssu#es "ro"erly co#"iling co!e listings. // Doesn2t !o everything right, but is a // useful ai!. i#"ort Hava.io.B<

Cha ter 11! The Java I/O S)stem

781

i#"ort Hava.util.B< class Julti%tringJa" e6ten!s MashJa" @ "ublic voi! a!!-%tring key, %tring value. @ if-4contains`ey-key.. "ut-key, ne: 0rrayList-..< --0rrayList.get-key...a!!-value.< A "ublic 0rrayList get0rrayList-%tring key. @ if-4contains`ey-key.. @ %yste#.err."rintln8E55G53 can2t fin! key3 8 K key.< %yste#.e6it-(.< A return -0rrayList.get-key.< A "ublic voi! "rintWalues-Print%trea# ". @ $terator k ? key%et-..iterator-.< :hile-k.has&e6t-.. @ %tring one`ey ? -%tring.k.ne6t-.< 0rrayList val ? get0rrayList-one`ey.< for-int i ? '< i P val.siUe-.< iKK. "."rintln--%tring.val.get-i..< A A A "ublic class Class%canner @ "rivate Lile "ath< "rivate %tringNO fileList< "rivate Pro"erties classes ? ne: Pro"erties-.< "rivate Julti%tringJa" classJa" ? ne: Julti%tringJa"-., i!entJa" ? ne: Julti%tringJa"-.< "rivate %trea#TokeniUer in< "ublic Class%canner-. thro:s $GE6ce"tion @ "ath ? ne: Lile-8.8.< fileList ? "ath.list-ne: JavaLilter-..< for-int i ? '< i P fileList.length< iKK. @ %yste#.out."rintln-fileListNiO.< try @

782

scanListing-fileListNiO.< A catch-Lile&otLoun!E6ce"tion e. @ %yste#.err."rintln-8Coul! not o"en 8 K fileListNiO.< A A A voi! scanListing-%tring fna#e. thro:s $GE6ce"tion @ in ? ne: %trea#TokeniUerne: Buffere!5ea!erne: Lile5ea!er-fna#e...< // Doesn2t see# to :ork3 // in.slash%tarCo##ents-true.< // in.slash%lashCo##ents-true.< in.or!inaryChar-2/2.< in.or!inaryChar-2.2.< in.:or!Chars-2b2, 2b2.< in.eol$s%ignificant-true.< :hile-in.ne6tToken-. 4? %trea#TokeniUer.TTbEGL. @ if-in.tty"e ?? 2/2. eatCo##ents-.< else if-in.tty"e ?? %trea#TokeniUer.TTb\G5D. @ if-in.sval.e=uals-8class8. XX in.sval.e=uals-8interface8.. @ // aet class na#e3 :hile-in.ne6tToken-. 4? %trea#TokeniUer.TTbEGL DD in.tty"e 4? %trea#TokeniUer.TTb\G5D. < classes."ut-in.sval, in.sval.< classJa".a!!-fna#e, in.sval.< A if-in.sval.e=uals-8i#"ort8. XX in.sval.e=uals-8"ackage8.. !iscar!Line-.< else // $t2s an i!entifier or key:or! i!entJa".a!!-fna#e, in.sval.<

Cha ter 11! The Java I/O S)stem

783

A A A voi! !iscar!Line-. thro:s $GE6ce"tion @ :hile-in.ne6tToken-. 4? %trea#TokeniUer.TTbEGL DD in.tty"e 4? %trea#TokeniUer.TTbEGL. < // Thro: a:ay tokens to en! of line A // %trea#TokeniUer2s co##ent re#oval see#e! // to be broken. This e6tracts the#3 voi! eatCo##ents-. thro:s $GE6ce"tion @ if-in.ne6tToken-. 4? %trea#TokeniUer.TTbEGL. @ if-in.tty"e ?? 2/2. !iscar!Line-.< else if-in.tty"e 4? 2B2. in."ushBack-.< else :hile-true. @ if-in.ne6tToken-. ?? %trea#TokeniUer.TTbEGL. break< if-in.tty"e ?? 2B2. if-in.ne6tToken-. 4? %trea#TokeniUer.TTbEGL DD in.tty"e ?? 2/2. break< A A A "ublic %tringNO class&a#es-. @ %tringNO result ? ne: %tringNclasses.siUe-.O< $terator e ? classes.key%et-..iterator-.< int i ? '< :hile-e.has&e6t-.. resultNiKKO ? -%tring.e.ne6t-.< return result< A "ublic voi! checkClass&a#es-. @

784

$terator files ? classJa".key%et-..iterator-.< :hile-files.has&e6t-.. @ %tring file ? -%tring.files.ne6t-.< 0rrayList cls ? classJa".get0rrayList-file.< for-int i ? '< i P cls.siUe-.< iKK. @ %tring class&a#e ? -%tring.cls.get-i.< if-Character.isLo:erCaseclass&a#e.char0t-'... %yste#.out."rintln8class ca"italiUation error, file3 8 K file K 8, class3 8 K class&a#e.< A A A "ublic voi! check$!ent&a#es-. @ $terator files ? i!entJa".key%et-..iterator-.< 0rrayList re"ort%et ? ne: 0rrayList-.< :hile-files.has&e6t-.. @ %tring file ? -%tring.files.ne6t-.< 0rrayList i!s ? i!entJa".get0rrayList-file.< for-int i ? '< i P i!s.siUe-.< iKK. @ %tring i! ? -%tring.i!s.get-i.< if-4classes.contains-i!.. @ // $gnore i!entifiers of length ) or // longer that are all u""ercase // -"robably static final values.3 if-i!.length-. Q? ) DD i!.e=ualsi!.toY""erCase-... continue< // Check to see if first char is u""er3 if-Character.isY""erCase-i!.char0t-'...@ if-re"ort%et.in!e6Gf-file K i!. ?? -(.@ // &ot re"orte! yet re"ort%et.a!!-file K i!.< %yste#.out."rintln8$!ent ca"italiUation error in38 K file K 8, i!ent3 8 K i!.< A A

Cha ter 11! The Java I/O S)stem

785

A A A A static final %tring usage ? 8Ysage3 _n8 K 8Class%canner classna#es -a_n8 K 8_t0!!s all the class na#es in this _n8 K 8_t!irectory to the re"ository file _n8 K 8_tcalle! 2classna#es2_n8 K 8Class%canner classna#es_n8 K 8_tChecks all the Hava files in this _n8 K 8_t!irectory for ca"italiUation errors, _n8 K 8_tusing the re"ository file 2classna#es28< "rivate static voi! usage-. @ %yste#.err."rintln-usage.< %yste#.e6it-(.< A "ublic static voi! #ain-%tringNO args. thro:s $GE6ce"tion @ if-args.length P ( XX args.length Q . usage-.< Class%canner c ? ne: Class%canner-.< Lile ol! ? ne: Lile-argsN'O.< if-ol!.e6ists-.. @ try @ // Try to o"en an e6isting // "ro"erties file3 $n"ut%trea# ol!list ? ne: Buffere!$n"ut%trea#ne: Lile$n"ut%trea#-ol!..< c.classes.loa!-ol!list.< ol!list.close-.< A catch-$GE6ce"tion e. @ %yste#.err."rintln-8Coul! not o"en 8 K ol! K 8 for rea!ing8.< %yste#.e6it-(.< A A if-args.length ?? (. @ c.checkClass&a#es-.<

787

c.check$!ent&a#es-.< A // \rite the class na#es to a re"ository3 if-args.length ?? . @ if-4argsN(O.e=uals-8-a8.. usage-.< try @ Buffere!Gut"ut%trea# out ? ne: Buffere!Gut"ut%trea#ne: LileGut"ut%trea#-argsN'O..< c.classes.store-out, 8Classes foun! by Class%canner.Hava8.< out.close-.< A catch-$GE6ce"tion e. @ %yste#.err."rintln8Coul! not :rite 8 K argsN'O.< %yste#.e6it-(.< A A A A class JavaLilter i#"le#ents Lilena#eLilter @ "ublic boolean acce"t-Lile !ir, %tring na#e. @ // %tri" "ath infor#ation3 %tring f ? ne: Lile-na#e..get&a#e-.< return f.tri#-..en!s\ith-8.Hava8.< A A ///3>
The class 1*lti)tring1ap is a tool that allows you to #a% a grou% o" strings onto each key entry. It uses a Hash1ap *this ti#e with inheritance, with the key as the single string that s #a%%ed onto the Array+ist value. The a''A B #ethod si#%ly checks to see i" there s a key already in the Hash1ap, and i" not it %uts one there. The getArray+ist A B #ethod %roduces an Array+ist "or a %articular key, and printVal*esA B, which is %ri#arily use"ul "or debugging, %rints out all the values Array+ist by Array+ist. RFSURFSTIJLT+(6PTE5MMTIMGMU To kee% li"e si#%le, the class na#es "ro# the standard Java libraries are all %ut into a #roperties ob0ect *"ro# the standard Java library,.

Cha ter 11! The Java I/O S)stem

788

5e#e#ber that a #roperties ob0ect is a Hash1ap that holds only )tring ob0ects "or both the key and value entries. (owever, it can be saved to disk and restored "ro# disk in one #ethod call, so it s ideal "or the re%ository o" na#es. 6ctually, we need only a list o" na#es, and a Hash1ap can t acce%t n*ll "or either its key or its value entry. So the sa#e ob0ect will be used "or both the key and the value. RFSURF STIJLT+(6PTE5MMTIMGKU Eor the classes and identi"iers that are discovered "or the "iles in a %articular directory, two 1*lti)tring1aps are used= class1ap and i'ent1ap. 6lso, when the %rogra# starts u% it loads the standard class na#e re%ository into the #roperties ob0ect called classes, and when a new class na#e is "ound in the local directory that is also added to classes as well as to class1ap. This way, class1ap can be used to ste% through all the classes in the local directory, and classes can be used to see i" the current token is a class na#e *which indicates a de"inition o" an ob0ect or #ethod is beginning, so grab the ne&t tokens9until a se#icolon 9and %ut the# into i'ent1ap,. RFSURFSTIJLT+(6PTE5MMTIMGLU The de"ault constructor "or -lass)canner creates a list o" "ile na#es, using the JavaFilter i#%le#entation o" FilenameFilter, shown at the end o" the "ile. Then it calls scan+istingA B "or each "ile na#e. RFSURF STIJLT+(6PTE5MMTIMG?U Inside scan+istingA B the source code "ile is o%ened and turned into a )treamTokeni7er. In the docu#entation, %assing tr*e to slash)tar-ommentsA B and slash)lash-ommentsA B is su%%osed to stri% those co##ents out, but this see#s to be a bit "lawed, as it doesn t Auite work. Instead, those lines are co##ented out and the co##ents are e&tracted by another #ethod. To do this, the ! 5$ #ust be ca%tured as an ordinary character rather than letting the )treamTokeni7er absorb it as %art o" a co##ent, and the or'inary-harA B #ethod tells the )treamTokeni7er to do this. This is also true "or dots *! !$,, since we want to have the #ethod calls %ulled a%art into individual identi"iers. (owever, the underscore, which is ordinarily treated by )treamTokeni7er as an individual character, should be le"t as %art o" identi"iers since it a%%ears in such static final values as TTX&.F, etc., used in this very %rogra#. The (or'-harsA B #ethod takes a range o" characters you want to add to those that are le"t inside a token that is

78:

being %arsed as a word. Einally, when %arsing "or one'line co##ents or discarding a line we need to know when an end'o"'line occurs, so by calling eolIs)ignificantAtr*eB the E)D will show u% rather than being absorbed by the )treamTokeni7er. RFSURFSTIJLT+(6PTE5MMTIMGHU The rest o" scan+istingA B reads and reacts to tokens until the end o" the "ile, signi"ied when ne4tTokenA B returns the final static value )treamTokeni7er!TTX&.F. RFSURFSTIJLT+(6PTE5MMTIMG3U I" the token is a !F$ it is %otentially a co##ent, so eat-ommentsA B is called to deal with it. The only other situation we re interested in here is i" it s a word, o" which there are so#e s%ecial cases. RFSURF STIJLT+(6PTE5MMTIMGGU I" the word is class or interface then the ne&t token re%resents a class or inter"ace na#e, and it is %ut into classes and class1ap. I" the word is import or package, then we don t want the rest o" the line. 6nything else #ust be an identi"ier *which we re interested in, or a keyword *which we re not, but they re all lowercase anyway so it won t s%oil things to %ut those in,. These are added to i'ent1ap. RFSURF STIJLT+(6PTE5MMTIMGIU The 'iscar'+ineA B #ethod is a si#%le tool that looks "or the end o" a line. Cote that any ti#e you get a new token, you #ust check "or the end o" the "ile. RFSURFSTIJLT+(6PTE5MMTIMG2U The eat-ommentsA B #ethod is called whenever a "orward slash is encountered in the #ain %arsing loo%. (owever, that doesn t necessarily #ean a co##ent has been "ound, so the ne&t token #ust be e&tracted to see i" it s another "orward slash *in which case the line is discarded, or an asterisk. But i" it s neither o" those, it #eans the token you ve 0ust %ulled out is needed back in the #ain %arsing loo%. Eortunately, the p*sh2ack A B #ethod allows you to !%ush back$ the current token onto the in%ut strea# so that when the #ain %arsing loo% calls ne4tTokenA B it will get the one you 0ust %ushed back. RFSURFSTIJLT+(6PTE5MMTIMI@U Eor convenience, the class/amesA B #ethod %roduces an array o" all the na#es in the classes container. This #ethod is not used in the %rogra# but is hel%"ul "or debugging. RFSURFSTIJLT+(6PTE5MMTIMIMU

Cha ter 11! The Java I/O S)stem

78;

The ne&t two #ethods are the ones in which the actual checking takes %lace. In check-lass/amesA B, the class na#es are e&tracted "ro# the class1ap *which, re#e#ber, contains only the na#es in this directory, organi1ed by "ile na#e so the "ile na#e can be %rinted along with the errant class na#e,. This is acco#%lished by %ulling each associated Array+ist and ste%%ing through that, looking to see i" the "irst character is lowercase. I" so, the a%%ro%riate error #essage is %rinted. RFSURF STIJLT+(6PTE5MMTIMIKU In checkI'ent/amesA B, a si#ilar a%%roach is taken= each identi"ier na#e is e&tracted "ro# i'ent1ap. I" the na#e is not in the classes list, it s assu#ed to be an identi"ier or keyword. 6 s%ecial case is checked= i" the identi"ier length is three or #ore and all the characters are u%%ercase, this identi"ier is ignored because it s %robably a static final value such as TTX&.F. )" course, this is not a %er"ect algorith#, but it assu#es that you ll eventually notice any all'u%%ercase identi"iers that are out o" %lace. RFSURFSTIJLT+(6PTE5MMTIMILU Instead o" re%orting every identi"ier that starts with an u%%ercase character, this #ethod kee%s track o" which ones have already been re%orted in an Array+ist called report)etA B. This treats the Array+ist as a !set$ that tells you whether an ite# is already in the set. The ite# is %roduced by concatenating the "ile na#e and identi"ier. I" the ele#ent isn t in the set, it s added and then the re%ort is #ade. RFSURF STIJLT+(6PTE5MMTIMI?U The rest o" the listing is co#%rised o" mainA B, which busies itsel" by handling the co##and line argu#ents and "iguring out whether you re building a re%ository o" class na#es "ro# the standard Java library or checking the validity o" code you ve written. In both cases it #akes a -lass)canner ob0ect. RFSURFSTIJLT+(6PTE5MMTIMIHU :hether you re building a re%ository or using one, you #ust try to o%en the e&isting re%ository. By #aking a File ob0ect and testing "or e&istence, you can decide whether to o%en the "ile and loa'A B the #roperties list classes inside -lass)canner. *The classes "ro# the re%ository add to, rather than overwrite, the classes "ound by the -lass)canner constructor., I" you %rovide only one co##and'line argu#ent it #eans that you want to %er"or# a check o" the class na#es and identi"ier na#es,

7:=

but i" you %rovide two argu#ents *the second being ! 6a$, you re building a class na#e re%ository. In this case, an out%ut "ile is o%ened and the #ethod #roperties!saveA B is used to write the list into a "ile, along with a string that %rovides header "ile in"or#ation. RFSURF STIJLT+(6PTE5MMTIMI3U

1ummar:
The Java IF) strea# library does satis"y the basic reAuire#ents= you can %er"or# reading and writing with the console, a "ile, a block o" #e#ory, or even across the Internet *as you will see in +ha%ter MH,. :ith inheritance, you can create new ty%es o" in%ut and out%ut ob0ects. 6nd you can even add a si#%le e&tensibility to the kinds o" ob0ects a strea# will acce%t by rede"ining the to)tringA B #ethod that s auto#atically called when you %ass an ob0ect to a #ethod that s e&%ecting a )tring *Java s li#ited !auto#atic ty%e conversion$,. RFSURF STIJLT+(6PTE5MMTIMIGU There are Auestions le"t unanswered by the docu#entation and design o" the IF) strea# library. Eor e&a#%le, it would have been nice i" you could say that you want an e&ce%tion thrown i" you try to overwrite a "ile when o%ening it "or out%ut9so#e %rogra##ing syste#s allow you to s%eci"y that you want to o%en an out%ut "ile, but only i" it doesn t already e&ist. In Java, it a%%ears that you are su%%osed to use a File ob0ect to deter#ine whether a "ile e&ists, because i" you o%en it as a File.*tp*t)tream or File0riter it will always get overwritten. RFSURF STIJLT+(6PTE5MMTIMIIU The IF) strea# library brings u% #i&ed "eelings; it does #uch o" the 0ob and it s %ortable. But i" you don t already understand the decorator %attern, the design is nonintuitive, so there s e&tra overhead in learning and teaching it. It s also inco#%lete= there s no su%%ort "or the kind o" out%ut "or#atting that al#ost every other language s IF) %ackage su%%orts. RFSURFSTIJLT+(6PTE5MMTIMI2U

Cha ter 11! The Java I/O S)stem

7:1

(owever, once you do understand the decorator %attern and begin using the library in situations that reAuire its "le&ibility, you can begin to bene"it "ro# this design, at which %oint its cost in e&tra lines o" code #ay not bother you as #uch. RFSURFSTIJLT+(6PTE5MMTIM2@U I" you do not "ind what you re looking "or in this cha%ter *which has only been an introduction, and is not #eant to be co#%rehensive,, you can "ind in'de%th coverage in Java I/O, by Elliotte 5usty (arold *) 5eilly, M222,. RFSURFSTIJLT+(6PTE5MMTIM2MU

/0ercises
Solutions to selected e&ercises can be "ound in the electronic docu#entThe Thinking in Java "nnotated Solution @uide, available "or a s#all "ee "ro# ,,,'0ruceEckel'com.

(56) )%en a te&t "ile so that you can read the "ile one line at a ti#e.
5ead each line as a )tring and %lace that )tring ob0ect into a +inke'+ist. Print all o" the lines in the +inke'+ist in reverse order. RFSURFSTIJLT+(6PTE5MMTIM2KU

(67) Modi"y E&ercise M so that the na#e o" the "ile you read is
%rovided as a co##and'line argu#ent. RFSURF STIJLT+(6PTE5MMTIM2LU

(6() Modi"y E&ercise K to also o%en a te&t "ile so you can write te&t
into it. :rite the lines in the Array+ist, along with line nu#bers *do not atte#%t to use the !DineCu#ber$ classes,, out to the "ile. RFSURFSTIJLT+(6PTE5MMTIM2?U

(6!) Modi"y E&ercise K to "orce all the lines in the Array+ist to


u%%er case and send the results to )ystem!o*t. RFSURF STIJLT+(6PTE5MMTIM2HU

(6*) Modi"y E&ercise K to take additional co##and'line argu#ents


o" words to "ind in the "ile. Print any all lines in which any o" the words #atch. RFSURFSTIJLT+(6PTE5MMTIM23U

(6+) Modi"y

ir+ist!8ava so that the FilenameFilter actually

o%ens each "ile and acce%ts the "ile based on whether any o" the

7:2

trailing argu#ents on the co##and line e&ist in that "ile. RFSURF STIJLT+(6PTE5MMTIM2GU

(6,) +reate a class called )orte' ir+ist with a constructor that


takes "ile %ath in"or#ation and builds a sorted directory list "ro# the "iles at that %ath. +reate two overloaded listA B #ethods that will either %roduce the whole list or a subset o" the list based on an argu#ent. 6dd a si7eA B #ethod that takes a "ile na#e and %roduces the si1e o" that "ile. RFSURFSTIJLT+(6PTE5MMTIM2IU

(6-) Modi"y 0or'-o*nt!8ava so that it %roduces an al%habetic


sort instead, using the tool "ro# +ha%ter 2. RFSURF STIJLT+(6PTE5MMTIM22U

(64) Modi"y 0or'-o*nt!8ava so that it uses a class containing a


)tring and a count value to store each di""erent word, and a )et
o" these ob0ects to #aintain the list o" words. RFSURF STIJLT+(6PTE5MMTIK@@U

(65) Modi"y I.)tream emo!8ava so that it uses


+ine/*mberInp*t)tream +ine/*mber$ea'er to kee%
track o" the line count. Cote that it s #uch easier to 0ust kee% track %rogra##atically. RFSURFSTIJLT+(6PTE5MMTIK@MU

(66) Starting with section ? o" I.)tream emo!8ava, write a


%rogra# that co#%ares the %er"or#ance o" writing to a "ile when using bu""ered and unbu""ered IF). RFSURF STIJLT+(6PTE5MMTIK@KU

!77) Modi"y section H o" I.)tream emo!8ava to eli#inate the


s%aces in the line %roduced by the "irst call to in@!rea'UTFAB in@br!rea'+ineA B. 7o this using a (hile loo% and rea'-har A B. RFSURFSTIJLT+(6PTE5MMTIK@LU

!7() 5e%air the %rogra# -A )tate!8ava as described in the te&t.


RFSURFSTIJLT+(6PTE5MMTIK@?U

!7!) In 2lips!8ava, co%y the "ile and rena#e it to 2lip-heck!8ava


and rena#e the class 2lipI to 2lip-heck *#aking it p*blic and re#oving the %ublic sco%e "ro# the class 2lips in the %rocess,. 5e#ove the 55= #arks in the "ile and e&ecute the %rogra#

Cha ter 11! The Java I/O S)stem

7:3

including the o""ending lines. Ce&t, co##ent out the de"ault constructor "or 2lip-heck. 5un it and e&%lain why it works. Cote that a"ter co#%iling, you #ust e&ecute the %rogra# with ! 8ava 2lips$ because the mainA B #ethod is still in class 2lips. RFSURF STIJLT+(6PTE5MMTIK@HU

!7*) In 2lipJ!8ava, co##ent out the two lines a"ter the %hrases
!/ou #ust do this=$ and run the %rogra#. E&%lain the result and why it di""ers "ro# when the two lines are in the %rogra#. RFSURF STIJLT+(6PTE5MMTIK@3U

!7+) *Inter#ediate, In +ha%ter I, locate the


"reenho*se-ontrols!8ava e&a#%le, which consists o" three "iles. In "reenho*se-ontrols!8ava, the $estartA B inner class
has a hard'coded set o" events. +hange the %rogra# so that it reads the events and their relative ti#es "ro# a te&t "ile. *+hallenging= 4se a design %atterns $actor) method to build the events9see Thinking in Patterns ,ith Java, downloadable at ,,,'0ruceEckel'com', RFSU

7:4

(!: $un@time #:.e Identification


RFSTIJLT+(6PTE5MKTI@UThe idea o" run'ti#e ty%e identi"ication *5TTI, see#s "airly si#%le at "irst= it lets you "ind the e&act ty%e o" an ob0ect when you only have a re"erence to the base ty%e.
(owever, the need "or 5TTI uncovers a whole %lethora o" interesting *and o"ten %er%le&ing, )) design issues, and raises "unda#ental Auestions o" how you should structure your %rogra#s. RFSURF STIJLT+(6PTE5MKTIMU This cha%ter looks at the ways that Java allows you to discover in"or#ation about ob0ects and classes at run'ti#e. This takes two "or#s= !traditional$ 5TTI, which assu#es that you have all the ty%es available at co#%ile'ti#e and run'ti#e, and the !re"lection$ #echanis#, which allows you to discover class in"or#ation solely at run'ti#e. The !traditional$ 5TTI will be covered "irst, "ollowed by a discussion o" re"lection. RFSURF STIJLT+(6PTE5MKTIKU

#he need for $##I


+onsider the now "a#iliar e&a#%le o" a class hierarchy that uses %oly#or%his#. The generic ty%e is the base class )hape, and the s%eci"ic derived ty%es are -ircle, )C*are, and Triangle=

7:5

Sha e draw89

$ircle

S%uare

&riangle

This is a ty%ical class hierarchy diagra#, with the base class at the to% and the derived classes growing downward. The nor#al goal in ob0ect' oriented %rogra##ing is "or the bulk o" your code to #ani%ulate re"erences to the base ty%e * )hape, in this case,, so i" you decide to e&tend the %rogra# by adding a new class * $homboi', derived "ro# )hape, "or e&a#%le,, the bulk o" the code is not a""ected. In this e&a#%le, the dyna#ically bound #ethod in the )hape inter"ace is 'ra(A B, so the intent is "or the client %rogra##er to call 'ra(A B through a generic )hape re"erence. 'ra(A B is overridden in all o" the derived classes, and because it is a dyna#ically bound #ethod, the %ro%er behavior will occur even though it is called through a generic )hape re"erence. That s %oly#or%his#. RFSURFSTIJLT+(6PTE5MKTILU Thus, you generally create a s%eci"ic ob0ect * -ircle, )C*are, or Triangle,, u%cast it to a )hape *"orgetting the s%eci"ic ty%e o" the ob0ect,, and use that anony#ous )hape re"erence in the rest o" the %rogra#. RFSURFSTIJLT+(6PTE5MKTI?U 6s a brie" review o" %oly#or%his# and u%casting, you #ight code the above e&a#%le as "ollows=

//3 c( 3%ha"es.Hava i#"ort Hava.util.B< class %ha"e @ voi! !ra:-. @ %yste#.out."rintln-this K 8.!ra:-.8.< A A class Circle e6ten!s %ha"e @

7:7

Thinking in Java

,,,'0ruceEckel'com

"ublic %tring to%tring-. @ return 8Circle8< A A class %=uare e6ten!s %ha"e @ "ublic %tring to%tring-. @ return 8%=uare8< A A class Triangle e6ten!s %ha"e @ "ublic %tring to%tring-. @ return 8Triangle8< A A "ublic class %ha"es @ "ublic static voi! #ain-%tringNO args. @ 0rrayList s ? ne: 0rrayList-.< s.a!!-ne: Circle-..< s.a!!-ne: %=uare-..< s.a!!-ne: Triangle-..< $terator e ? s.iterator-.< :hile-e.has&e6t-.. --%ha"e.e.ne6t-...!ra:-.< A A ///3>
The base class contains a 'ra(A B #ethod that indirectly uses to)tring A B to %rint an identi"ier "or the class by %assing this to )ystem!o*t! printlnA B. I" that "unction sees an ob0ect, it auto#atically calls the to)tringA B #ethod to %roduce a )tring re%resentation. RFSURF STIJLT+(6PTE5MKTIHU Each o" the derived classes overrides the to)tringA B #ethod *"ro# .b8ect, so that 'ra(A B ends u% %rinting so#ething di""erent in each case. In mainA B, s%eci"ic ty%es o" )hape are created and then added to a n Array+ist. This is the %oint at which the u%cast occurs because the Array+ist holds only .b8ects. Since everything in Java *with the e&ce%tion o" %ri#itives, is an .b8ect, a n Array+ist can also hold )hape ob0ects. But during an u%cast to .b8ect, it also loses any s%eci"ic in"or#ation, including the "act that the ob0ects are )hapes. To the Array+ist, they are 0ust .b8ects. RFSURFSTIJLT+(6PTE5MKTI3U 6t the %oint you "etch an ele#ent out o" the Array+ist with ne4tA B, things get a little busy. Since the Array+ist holds only .b8ects, ne4tA B

7:8

naturally %roduces an .b8ect reference. But we know it s really a )hape re"erence, and we want to send )hape #essages to that ob0ect. So a cast to )hape is necessary using the traditional ! A)hapeB$ cast. This is the #ost basic "or# o" 5TTI, since in Java all casts are checked at run' ti#e "or correctness. That s e&actly what 5TTI #eans= at run'ti#e, the ty%e o" an ob0ect is identi"ied. RFSURFSTIJLT+(6PTE5MKTIGU In this case, the 5TTI cast is only %artial= the .b8ect is cast to a )hape, and not all the way to a -ircle, )C*are, or Triangle. That s because the only thing we kno, at this %oint is that the Array+ist is "ull o" )hapes. 6t co#%ile'ti#e, this is en"orced only by your own sel"'i#%osed rules, but at run'ti#e the cast ensures it. RFSURFSTIJLT+(6PTE5MKTIIU Cow %oly#or%his# takes over and the e&act #ethod that s called "or the

)hape is deter#ined by whether the re"erence is "or a -ircle, )C*are, or Triangle. 6nd in general, this is how it should be; you want the bulk o" your code to know as little as %ossible about s eci$ic ty%es o" ob0ects,
and to 0ust deal with the general re%resentation o" a "a#ily o" ob0ects *in this case, )hape,. 6s a result, your code will be easier to write, read, and #aintain, and your designs will be easier to i#%le#ent, understand, and change. So %oly#or%his# is the general goal in ob0ect'oriented %rogra##ing. RFSURFSTIJLT+(6PTE5MKTI2U But what i" you have a s%ecial %rogra##ing %roble# that s easiest to solve i" you know the e&act ty%e o" a generic re"erenceO Eor e&a#%le, su%%ose you want to allow your users to highlight all the sha%es o" any %articular ty%e by turning the# %ur%le. This way, they can "ind all the triangles on the screen by highlighting the#. )r %erha%s your #ethod

needs to !rotate$ a list o" sha%es, but it #akes no sense to rotate a circle so you d like to ski% only the circle ob0ects. This is what 5TTI acco#%lishes= you can ask a )hape re"erence the e&act ty%e that it s re"erring to. RFSURFSTIJLT+(6PTE5MKTIM@U :ith 5TTI you can select and isolate s%ecial cases.

#he $lass ob3ect


To understand how 5TTI works in Java, you #ust "irst know how ty%e in"or#ation is re%resented at run'ti#e. This is acco#%lished through a s%ecial kind o" ob0ect called the Class ob>ectD which contains in"or#ation

7::

Thinking in Java

,,,'0ruceEckel'com

about the class. *This is so#eti#es called a meta/class', In "act, the -lass ob0ect is used to create all o" the !regular$ ob0ects o" your class. RFSURF STIJLT+(6PTE5MKTIMMU There s a -lass ob0ect "or each class that is %art o" your %rogra#. That is, each ti#e you write and co#%ile a new class, a single -lass ob0ect is also created *and stored, a%%ro%riately enough, in an identically na#ed !class "ile,. 6t run'ti#e, when you want to #ake an ob0ect o" that class, the Java Virtual Machine *JVM, that s e&ecuting your %rogra# "irst checks to see i" the -lass ob0ect "or that ty%e is loaded. I" not, the JVM loads it by "inding the !class "ile with that na#e. Thus, a Java %rogra# isn t co#%letely loaded be"ore it begins, which is di""erent "ro# #any traditional languages. RFSURFSTIJLT+(6PTE5MKTIMKU )nce the -lass ob0ect "or that ty%e is in #e#ory, it is used to create all ob0ects o" that ty%e. RFSURFSTIJLT+(6PTE5MKTIMLU I" this see#s shadowy or i" you don t really believe it, here s a de#onstration %rogra# to %rove it=

//3 c( 3%:eet%ho".Hava // E6a#ination of the :ay the class loa!er :orks. class Can!y @ static @ %yste#.out."rintln-8Loa!ing Can!y8.< A A class au# @ static @ %yste#.out."rintln-8Loa!ing au#8.< A A class Cookie @ static @ %yste#.out."rintln-8Loa!ing Cookie8.< A A

7:;

"ublic class %:eet%ho" @ "ublic static voi! #ain-%tringNO args. @ %yste#.out."rintln-8insi!e #ain8.< ne: Can!y-.< %yste#.out."rintln-80fter creating Can!y8.< try @ Class.for&a#e-8au#8.< A catch-Class&otLoun!E6ce"tion e. @ e."rint%tackTrace-%yste#.err.< A %yste#.out."rintln80fter Class.for&a#e-_8au#_8.8.< ne: Cookie-.< %yste#.out."rintln-80fter creating Cookie8.< A A ///3>
Each o" the classes -an'y, "*m, and -ookie have a static clause that is e&ecuted as the class is loaded "or the "irst ti#e. In"or#ation will be %rinted to tell you when loading occurs "or that class. In mainA B, the ob0ect creations are s%read out between %rint state#ents to hel% detect the ti#e o" loading. RFSURFSTIJLT+(6PTE5MKTIM?U 6 %articularly interesting line is=

Class.for&a#e-8au#8.<
This #ethod is a static #e#ber o" -lass *to which all -lass ob0ects belong,. 6 -lass ob0ect is like any other ob0ect and so you can get and #ani%ulate a re"erence to it. *That s what the loader does., )ne o" the ways to get a re"erence to the -lass ob0ect is for/ameA B, which takes a )tring containing the te&tual na#e *watch the s%elling and ca%itali1ation., o" the %articular class you want a re"erence "or. It returns a -lass re"erence. RFSURFSTIJLT+(6PTE5MKTIMHU The out%ut o" this %rogra# "or one JVM is=

insi!e #ain Loa!ing Can!y 0fter creating Can!y Loa!ing au# 0fter Class.for&a#e-8au#8.

7;=

Thinking in Java

,,,'0ruceEckel'com

Loa!ing Cookie 0fter creating Cookie


/ou can see that each -lass ob0ect is loaded only when it s needed, and the static initiali1ation is %er"or#ed u%on class loading. RFSURF STIJLT+(6PTE5MKTIM3U

Class literals
Java %rovides a second way to %roduce the re"erence to the -lass ob0ect, using a class literal. In the above %rogra# this would look like=

au#.class<
which is not only si#%ler, but also sa"er since it s checked at co#%ile' ti#e. Because it eli#inates the #ethod call, it s also #ore e""icient. RF SURFSTIJLT+(6PTE5MKTIMGU +lass literals work with regular classes as well as inter"aces, arrays, and %ri#itive ty%es. In addition, there s a standard "ield called T:#& that e&ists "or each o" the %ri#itive wra%%er classes. The T:#& "ield %roduces a re"erence to the -lass ob0ect "or the associated %ri#itive ty%e, such that=

d is eC*ivalent to d boolean!class 2oolean!T:#& char!class -haracter!T:#& byte!class 2yte!T:#& short!class )hort!T:#& int!class Integer!T:#& long!class +ong!T:#& float!class Float!T:#& 'o*ble!class o*ble!T:#& voi'!class Voi'!T:#&
My %re"erence is to use the ! !class$ versions i" you can, since they re #ore consistent with regular classes. RFSURFSTIJLT+(6PTE5MKTIMIU

Checking before a cast


So "ar, you ve seen 5TTI "or#s including=

7;1

((!) The classic cast; e.g., ! A)hapeB,$ which uses 5TTI to #ake sure the cast is correct and throws a -lass-ast&4ception i" you ve
%er"or#ed a bad cast.

((*) The -lass ob0ect re%resenting the ty%e o" your ob0ect. The -lass
ob0ect can be Aueried "or use"ul run'ti#e in"or#ation. RFSURF STIJLT+(6PTE5MKTIM2U In +<<, the classic cast ! A)hapeB$ does not %er"or# 5TTI. It si#%ly tells the co#%iler to treat the ob0ect as the new ty%e. In Java, which does %er"or# the ty%e check, this cast is o"ten called a !ty%e sa"e downcast.$ The reason "or the ter# !downcast$ is the historical arrange#ent o" the class hierarchy diagra#. I" casting a -ircle to a )hape is an u%cast, then casting a )hape to a -ircle is a downcast. (owever, you know a -ircle is also a )hape, and the co#%iler "reely allows an u%cast assign#ent, but you donJt know that a )hape is necessarily a -ircle, so the co#%iler doesn t allow you to %er"or# a downcast assign#ent without using an e&%licit cast. RFSURFSTIJLT+(6PTE5MKTIK@U There s a third "or# o" 5TTI in Java. This is the keyword instanceof that tells you i" an ob0ect is an instance o" a %articular ty%e. It returns a boolean so you use it in the "or# o" a Auestion, like this=

if-6 instanceof Dog. --Dog.6..bark-.<


The above if state#ent checks to see i" the ob0ect 4 belongs to the class og be$ore casting 4 to a og. It s i#%ortant to use instanceof be"ore a downcast when you don t have other in"or#ation that tells you the ty%e o" the ob0ect; otherwise you ll end u% with a -lass-ast&4ception. RFSURF STIJLT+(6PTE5MKTIKMU )rdinarily, you #ight be hunting "or one ty%e *triangles to turn %ur%le, "or e&a#%le,, but you can easily tally all o" the ob0ects using instanceof. Su%%ose you have a "a#ily o" #et classes=

//3 c( 3Pets.Hava class Pet @A class Dog e6ten!s Pet @A class Pug e6ten!s Dog @A class Cat e6ten!s Pet @A

7;2

Thinking in Java

,,,'0ruceEckel'com

class 5o!ent e6ten!s Pet @A class aerbil e6ten!s 5o!ent @A class Ma#ster e6ten!s 5o!ent @A class Counter @ int i< A ///3>
The -o*nter class is used to kee% track o" the nu#ber o" any %articular ty%e o" #et. /ou could think o" it as an Integer that can be #odi"ied. RF SURFSTIJLT+(6PTE5MKTIKKU 4sing instanceof, all the %ets can be counted=

//3 c( 3PetCount.Hava // Ysing instanceof. i#"ort Hava.util.B< "ublic class PetCount @ static %tringNO ty"ena#es ? @ 8Pet8, 8Dog8, 8Pug8, 8Cat8, 85o!ent8, 8aerbil8, 8Ma#ster8, A< // E6ce"tions thro:n out to console3 "ublic static voi! #ain-%tringNO args. thro:s E6ce"tion @ 0rrayList "ets ? ne: 0rrayList-.< try @ ClassNO "etTy"es ? @ Class.for&a#e-8Dog8., Class.for&a#e-8Pug8., Class.for&a#e-8Cat8., Class.for&a#e-85o!ent8., Class.for&a#e-8aerbil8., Class.for&a#e-8Ma#ster8., A< for-int i ? '< i P (,< iKK. "ets.a!!"etTy"esN -int.-Jath.ran!o#-.B"etTy"es.length.O .ne:$nstance-..< A catch-$nstantiationE6ce"tion e. @ %yste#.err."rintln-8Cannot instantiate8.< thro: e<

7;3

A catch-$llegal0ccessE6ce"tion e. @ %yste#.err."rintln-8Cannot access8.< thro: e< A catch-Class&otLoun!E6ce"tion e. @ %yste#.err."rintln-8Cannot fin! class8.< thro: e< A MashJa" h ? ne: MashJa"-.< for-int i ? '< i P ty"ena#es.length< iKK. h."ut-ty"ena#esNiO, ne: Counter-..< for-int i ? '< i P "ets.siUe-.< iKK. @ GbHect o ? "ets.get-i.< if-o instanceof Pet. --Counter.h.get-8Pet8...iKK< if-o instanceof Dog. --Counter.h.get-8Dog8...iKK< if-o instanceof Pug. --Counter.h.get-8Pug8...iKK< if-o instanceof Cat. --Counter.h.get-8Cat8...iKK< if-o instanceof 5o!ent. --Counter.h.get-85o!ent8...iKK< if-o instanceof aerbil. --Counter.h.get-8aerbil8...iKK< if-o instanceof Ma#ster. --Counter.h.get-8Ma#ster8...iKK< A for-int i ? '< i P "ets.siUe-.< iKK. %yste#.out."rintln-"ets.get-i..getClass-..< for-int i ? '< i P ty"ena#es.length< iKK. %yste#.out."rintlnty"ena#esNiO K 8 =uantity3 8 K --Counter.h.get-ty"ena#esNiO...i.< A A ///3>
There s a rather narrow restriction on instanceof= you can co#%are it to a na#ed ty%e only, and not to a -lass ob0ect. In the e&a#%le above you #ight "eel that it s tedious to write out all o" those instanceof e&%ressions, and you re right. But there is no way to cleverly auto#ate instanceof by creating an Array+ist o" -lass ob0ects and co#%aring it

7;4

Thinking in Java

,,,'0ruceEckel'com

to those instead *stay tuned9you ll see an alternative,. This isn t as great a restriction as you #ight think, because you ll eventually understand that your design is %robably "lawed i" you end u% writing a lot o" instanceof e&%ressions. RFSURFSTIJLT+(6PTE5MKTIKLU )" course this e&a#%le is contrived9you d %robably %ut a static data #e#ber in each ty%e and incre#ent it in the constructor to kee% track o" the counts. /ou would do so#ething like that i$ you had control o" the source code "or the class and could change it. Since this is not always the case, 5TTI can co#e in handy. RFSURFSTIJLT+(6PTE5MKTIK?U

Csing class literals


It s interesting to see how the #et-o*nt!8ava e&a#%le can be rewritten using class literals. The result is cleaner in #any ways=

//3 c( 3PetCount .Hava // Ysing class literals. i#"ort Hava.util.B< "ublic class PetCount @ "ublic static voi! #ain-%tringNO args. thro:s E6ce"tion @ 0rrayList "ets ? ne: 0rrayList-.< ClassNO "etTy"es ? @ // Class literals3 Pet.class, Dog.class, Pug.class, Cat.class, 5o!ent.class, aerbil.class, Ma#ster.class, A< try @ for-int i ? '< i P (,< iKK. @ // Gffset by one to eli#inate Pet.class3 int rn! ? ( K -int.Jath.ran!o#-. B -"etTy"es.length - (..< "ets.a!!"etTy"esNrn!O.ne:$nstance-..<

7;5

A A catch-$nstantiationE6ce"tion e. @ %yste#.err."rintln-8Cannot instantiate8.< thro: e< A catch-$llegal0ccessE6ce"tion e. @ %yste#.err."rintln-8Cannot access8.< thro: e< A MashJa" h ? ne: MashJa"-.< for-int i ? '< i P "etTy"es.length< iKK. h."ut-"etTy"esNiO.to%tring-., ne: Counter-..< for-int i ? '< i P "ets.siUe-.< iKK. @ GbHect o ? "ets.get-i.< if-o instanceof Pet. --Counter.h.get-8class Pet8...iKK< if-o instanceof Dog. --Counter.h.get-8class Dog8...iKK< if-o instanceof Pug. --Counter.h.get-8class Pug8...iKK< if-o instanceof Cat. --Counter.h.get-8class Cat8...iKK< if-o instanceof 5o!ent. --Counter.h.get-8class 5o!ent8...iKK< if-o instanceof aerbil. --Counter.h.get-8class aerbil8...iKK< if-o instanceof Ma#ster. --Counter.h.get-8class Ma#ster8...iKK< A for-int i ? '< i P "ets.siUe-.< iKK. %yste#.out."rintln-"ets.get-i..getClass-..< $terator keys ? h.key%et-..iterator-.< :hile-keys.has&e6t-.. @ %tring n# ? -%tring.keys.ne6t-.< Counter cnt ? -Counter.h.get-n#.< %yste#.out."rintlnn#.substring-n#.last$n!e6Gf-2.2. K (. K 8 =uantity3 8 K cnt.i.< A A A ///3>

7;7

Thinking in Java

,,,'0ruceEckel'com

(ere, the typenames array has been re#oved in "avor o" getting the ty%e na#e strings "ro# the -lass ob0ect. Cotice that the syste# can distinguish between classes and inter"aces. RFSURF STIJLT+(6PTE5MKTIKHU /ou can also see that the creation o" petTypes does not need to be surrounded by a try block since it s evaluated at co#%ile'ti#e and thus won t throw any e&ce%tions, unlike -lass!for/ameA B. RFSURF STIJLT+(6PTE5MKTIK3U :hen the #et ob0ects are dyna#ically created, you can see that the rando# nu#ber is restricted so it is between one and petTypes!length and does not include 1ero. That s because 1ero re"ers to #et!class, and %resu#ably a generic #et ob0ect is not interesting. (owever, since #et! class is %art o" petTypes the result is that all o" the %ets get counted. RF SURFSTIJLT+(6PTE5MKTIKGU

A d:namic instanceo!
The -lass isInstance #ethod %rovides a way to dyna#ically call the instanceof o%erator. Thus, all those tedious instanceof state#ents can be re#oved in the #et-o*nt e&a#%le=

//3 c( 3PetCount).Hava // Ysing is$nstance-.. i#"ort Hava.util.B< "ublic class PetCount) @ "ublic static voi! #ain-%tringNO args. thro:s E6ce"tion @ 0rrayList "ets ? ne: 0rrayList-.< ClassNO "etTy"es ? @ Pet.class, Dog.class, Pug.class, Cat.class, 5o!ent.class, aerbil.class, Ma#ster.class, A< try @

7;8

for-int i ? '< i P (,< iKK. @ // Gffset by one to eli#inate Pet.class3 int rn! ? ( K -int.Jath.ran!o#-. B -"etTy"es.length - (..< "ets.a!!"etTy"esNrn!O.ne:$nstance-..< A A catch-$nstantiationE6ce"tion e. @ %yste#.err."rintln-8Cannot instantiate8.< thro: e< A catch-$llegal0ccessE6ce"tion e. @ %yste#.err."rintln-8Cannot access8.< thro: e< A MashJa" h ? ne: MashJa"-.< for-int i ? '< i P "etTy"es.length< iKK. h."ut-"etTy"esNiO.to%tring-., ne: Counter-..< for-int i ? '< i P "ets.siUe-.< iKK. @ GbHect o ? "ets.get-i.< // Ysing is$nstance to eli#inate in!ivi!ual // instanceof e6"ressions3 for -int H ? '< H P "etTy"es.length< KKH. if -"etTy"esNHO.is$nstance-o.. @ %tring key ? "etTy"esNHO.to%tring-.< --Counter.h.get-key...iKK< A A for-int i ? '< i P "ets.siUe-.< iKK. %yste#.out."rintln-"ets.get-i..getClass-..< $terator keys ? h.key%et-..iterator-.< :hile-keys.has&e6t-.. @ %tring n# ? -%tring.keys.ne6t-.< Counter cnt ? -Counter.h.get-n#.< %yste#.out."rintlnn#.substring-n#.last$n!e6Gf-2.2. K (. K 8 =uantity3 8 K cnt.i.< A A A ///3>

7;:

Thinking in Java

,,,'0ruceEckel'com

/ou can see that the isInstanceA B #ethod has eli#inated the need "or the instanceof e&%ressions. In addition, this #eans that you can add new ty%es o" %ets si#%ly by changing the petTypes array; the rest o" the %rogra# does not need #odi"ication *as it did when using the instanceof e&%ressions,. RFSURFSTIJLT+(6PTE5MKTIKIU

instanceo! vs) $lass e%uivalence


:hen Auerying "or ty%e in"or#ation, there s an i#%ortant di""erence between either "or# o" instanceof *that is, instanceof or isInstance A B, which %roduce eAuivalent results, and the direct co#%arison o" the -lass ob0ects. (ere s an e&a#%le that de#onstrates the di""erence=

//3 c( 3La#ilyWsE6actTy"e.Hava // The !ifference bet:een instanceof an! class class Base @A class Derive! e6ten!s Base @A "ublic class La#ilyWsE6actTy"e @ static voi! test-GbHect 6. @ %yste#.out."rintln-8Testing 6 of ty"e 8 K 6.getClass-..< %yste#.out."rintln-86 instanceof Base 8 K -6 instanceof Base..< %yste#.out."rintln-86 instanceof Derive! 8 K -6 instanceof Derive!..< %yste#.out."rintln-8Base.is$nstance-6. 8 K Base.class.is$nstance-6..< %yste#.out."rintln-8Derive!.is$nstance-6. 8 K Derive!.class.is$nstance-6..< %yste#.out."rintln86.getClass-. ?? Base.class 8 K -6.getClass-. ?? Base.class..< %yste#.out."rintln86.getClass-. ?? Derive!.class 8 K -6.getClass-. ?? Derive!.class..< %yste#.out."rintln86.getClass-..e=uals-Base.class.. 8 K -6.getClass-..e=uals-Base.class...< %yste#.out."rintln-

7;;

86.getClass-..e=uals-Derive!.class.. 8 K -6.getClass-..e=uals-Derive!.class...< A "ublic static voi! #ain-%tringNO args. @ test-ne: Base-..< test-ne: Derive!-..< A A ///3>
The testA B #ethod %er"or#s ty%e checking with its argu#ent using both "or#s o" instanceof. It then gets the -lass re"erence and uses PP and eC*alsA B to test "or eAuality o" the -lass ob0ects. (ere is the out%ut=

Testing 6 of ty"e class Base 6 instanceof Base true 6 instanceof Derive! false Base.is$nstance-6. true Derive!.is$nstance-6. false 6.getClass-. ?? Base.class true 6.getClass-. ?? Derive!.class false 6.getClass-..e=uals-Base.class.. true 6.getClass-..e=uals-Derive!.class.. false Testing 6 of ty"e class Derive! 6 instanceof Base true 6 instanceof Derive! true Base.is$nstance-6. true Derive!.is$nstance-6. true 6.getClass-. ?? Base.class false 6.getClass-. ?? Derive!.class true 6.getClass-..e=uals-Base.class.. false 6.getClass-..e=uals-Derive!.class.. true
5eassuringly, instanceof and isInstanceA B %roduce e&actly the sa#e results, as do eC*alsA B and PP. But the tests the#selves draw di""erent conclusions. In kee%ing with the conce%t o" ty%e, instanceof says !are you this class, or a class derived "ro# this classO$ )n the other hand, i" you co#%are the actual -lass ob0ects using PP, there is no concern with inheritance9it s either the e&act ty%e or it isn t. RFSURF STIJLT+(6PTE5MKTIK2U

8==

Thinking in Java

,,,'0ruceEckel'com

$##I s:nta0
Java %er"or#s its 5TTI using the -lass ob0ect, even i" you re doing so#ething like a cast. The class -lass also has a nu#ber o" other ways you can use 5TTI. RFSURFSTIJLT+(6PTE5MKTIL@U Eirst, you #ust get a re"erence to the a%%ro%riate -lass ob0ect. )ne way to do this, as shown in the %revious e&a#%le, is to use a string and the -lass!for/ameA B #ethod. This is convenient because you don t need an ob0ect o" that ty%e in order to get the -lass re"erence. (owever, i" you do already have an ob0ect o" the ty%e you re interested in, you can "etch the -lass re"erence by calling a #ethod that s %art o" the .b8ect root class= get-lassA B. This returns the -lass re"erence re%resenting the actual ty%e o" the ob0ect. -lass has #any interesting #ethods, de#onstrated in the "ollowing e&a#%le=

//3 c( 3ToyTest.Hava // Testing class Class. interface MasBatteries @A interface \ater"roof @A interface %hootsThings @A class Toy @ // Co##ent out the follo:ing !efault // constructor to see // &o%uchJetho!Error fro# -B(B. Toy-. @A Toy-int i. @A A class LancyToy e6ten!s Toy i#"le#ents MasBatteries, \ater"roof, %hootsThings @ LancyToy-. @ su"er-(.< A A "ublic class ToyTest @ "ublic static voi! #ain-%tringNO args. thro:s E6ce"tion @ Class c ? null<

8=1

try @ c ? Class.for&a#e-8LancyToy8.< A catch-Class&otLoun!E6ce"tion e. @ %yste#.err."rintln-8Can2t fin! LancyToy8.< thro: e< A "rint$nfo-c.< ClassNO faces ? c.get$nterfaces-.< for-int i ? '< i P faces.length< iKK. "rint$nfo-facesNiO.< Class cy ? c.get%u"erclass-.< GbHect o ? null< try @ // 5e=uires !efault constructor3 o ? cy.ne:$nstance-.< // -B(B. A catch-$nstantiationE6ce"tion e. @ %yste#.err."rintln-8Cannot instantiate8.< thro: e< A catch-$llegal0ccessE6ce"tion e. @ %yste#.err."rintln-8Cannot access8.< thro: e< A "rint$nfo-o.getClass-..< A static voi! "rint$nfo-Class cc. @ %yste#.out."rintln8Class na#e3 8 K cc.get&a#e-. K 8 is interface[ N8 K cc.is$nterface-. K 8O8.< A A ///3>
/ou can see that class FancyToy is Auite co#%licated, since it inherits "ro# Toy and implements the interfaces o" Has2atteries, 0aterproof, and )hootsThings. In mainA B, a -lass re"erence is created and initiali1ed to the FancyToy -lass using for/ameA B inside an a%%ro%riate try block. RFSURFSTIJLT+(6PTE5MKTILMU The -lass!getInterfacesA B #ethod returns an array o" -lass ob0ects re%resenting the inter"aces that are contained in the -lass ob0ect o" interest. RFSURFSTIJLT+(6PTE5MKTILKU

8=2

Thinking in Java

,,,'0ruceEckel'com

I" you have a -lass ob0ect you can also ask it "or its direct base class using get)*perclassA B. This, o" course, returns a -lass re"erence that you can "urther Auery. This #eans that, at run'ti#e, you can discover an ob0ect s entire class hierarchy. RFSURFSTIJLT+(6PTE5MKTILLU The ne(InstanceA B #ethod o" -lass can, at "irst, see# like 0ust another way to cloneA B an ob0ect. (owever, you can create a new ob0ect with ne(InstanceA B ,ithout an e&isting ob0ect, as seen here, because there is no Toy ob0ect9only cy, which is a re"erence to y s -lass ob0ect. This is a way to i#%le#ent a !virtual constructor,$ which allows you to say !I don t know e&actly what ty%e you are, but create yoursel" %ro%erly anyway.$ In the e&a#%le above, cy is 0ust a -lass re"erence with no "urther ty%e in"or#ation known at co#%ile'ti#e. 6nd when you create a new instance, you get back an .b8ect reference. But that re"erence is %ointing to a Toy ob0ect. )" course, be"ore you can send any #essages other than those acce%ted by .b8ect, you have to investigate it a bit and do so#e casting. In addition, the class that s being created with ne(InstanceA B #ust have a de"ault constructor. In the ne&t section, you ll see how to dyna#ically create ob0ects o" classes using any constructor, with the Java re$lection 6PI. RFSURF STIJLT+(6PTE5MKTIL?U The "inal #ethod in the listing is printInfoA B, which takes a -lass re"erence and gets its na#e with get/ameA B, and "inds out whether it s an inter"ace with isInterfaceA B. RFSURFSTIJLT+(6PTE5MKTILHU The out%ut "ro# this %rogra# is=

Class Class Class Class Class

na#e3 na#e3 na#e3 na#e3 na#e3

LancyToy is interface[ NfalseO MasBatteries is interface[ NtrueO \ater"roof is interface[ NtrueO %hootsThings is interface[ NtrueO Toy is interface[ NfalseO

Thus, with the -lass ob0ect you can "ind out 0ust about everything you want to know about an ob0ect. RFSURFSTIJLT+(6PTE5MKTIL3U

8=3

$eflection: run@time class information


I" you don t know the %recise ty%e o" an ob0ect, 5TTI will tell you. (owever, there s a li#itation= the ty%e #ust be known at co#%ile'ti#e in order "or you to be able to detect it using 5TTI and do so#ething use"ul with the in"or#ation. Put another way, the co#%iler #ust know about all the classes you re working with "or 5TTI. RFSURF STIJLT+(6PTE5MKTILGU This doesn t see# like that #uch o" a li#itation at "irst, but su%%ose you re given a re"erence to an ob0ect that s not in your %rogra# s%ace. In "act, the class o" the ob0ect isn t even available to your %rogra# at co#%ile'ti#e. Eor e&a#%le, su%%ose you get a bunch o" bytes "ro# a disk "ile or "ro# a network connection and you re told that those bytes re%resent a class. Since the co#%iler can t know about the class while it s co#%iling the code, how can you %ossibly use such a classO RFSURF STIJLT+(6PTE5MKTILIU In a traditional %rogra##ing environ#ent this see#s like a "ar'"etched scenario. But as we #ove into a larger %rogra##ing world there are i#%ortant cases in which this ha%%ens. The "irst is co#%onent'based %rogra##ing, in which you build %ro0ects using -a id " lication %evelo ment *567, in an a%%lication builder tool. This is a visual a%%roach to creating a %rogra# *which you see on the screen as a !"or#$, by #oving icons that re%resent co#%onents onto the "or#. These co#%onents are then con"igured by setting so#e o" their values at %rogra# ti#e. This design'ti#e con"iguration reAuires that any co#%onent be instantiable, that it e&%oses %arts o" itsel", and that it allows its values to be read and set. In addition, co#%onents that handle 84I events #ust e&%ose in"or#ation about a%%ro%riate #ethods so that the 567 environ#ent can assist the %rogra##er in overriding these event'handling #ethods. 5e"lection %rovides the #echanis# to detect the available #ethods and %roduce the #ethod na#es. Java %rovides a structure "or co#%onent'based %rogra##ing through JavaBeans *described in +ha%ter ML,. RFSURFSTIJLT+(6PTE5MKTIL2U

8=4

Thinking in Java

,,,'0ruceEckel'com

6nother co#%elling #otivation "or discovering class in"or#ation at run' ti#e is to %rovide the ability to create and e&ecute ob0ects on re#ote %lat"or#s across a network. This is called -emote Method Invocation *5MI, and it allows a Java %rogra# to have ob0ects distributed across #any #achines. This distribution can ha%%en "or a nu#ber o" reasons= "or e&a#%le, %erha%s you re doing a co#%utation'intensive task and you want to break it u% and %ut %ieces on #achines that are idle in order to s%eed things u%. In so#e situations you #ight want to %lace code that handles %articular ty%es o" tasks *e.g., !Business 5ules$ in a #ultitier clientFserver architecture, on a %articular #achine, so that #achine beco#es a co##on re%ository describing those actions and it can be easily changed to a""ect everyone in the syste#. *This is an interesting develo%#ent, since the #achine e&ists solely to #ake so"tware changes easy., 6long these lines, distributed co#%uting also su%%orts s%eciali1ed hardware that #ight be good at a %articular task9#atri& inversions, "or e&a#%le9but ina%%ro%riate or too e&%ensive "or general %ur%ose %rogra##ing. RFSURFSTIJLT+(6PTE5MKTI?@U The class -lass *described %reviously in this cha%ter, su%%orts the conce%t o" re$lection, and there s an additional library, 8ava!lang! reflect, with classes Fiel', 1etho', and -onstr*ctor *each o" which i#%le#ent the 1ember interface,. )b0ects o" these ty%es are created by the JVM at run'ti#e to re%resent the corres%onding #e#ber in the unknown class. /ou can then use the -onstr*ctors to create new ob0ects, the getA B and setA B #ethods to read and #odi"y the "ields associated with Fiel' ob0ects, and the invokeA B #ethod to call a #ethod associated with a 1etho' ob0ect. In addition, you can call the convenience #ethods getFiel'sA B, get1etho'sA B, get-onstr*ctors A B, etc., to return arrays o" the ob0ects re%resenting the "ields, #ethods, and constructors. */ou can "ind out #ore by looking u% the class -lass in your online docu#entation., Thus, the class in"or#ation "or anony#ous ob0ects can be co#%letely deter#ined at run'ti#e, and nothing need be known at co#%ile'ti#e. RFSURFSTIJLT+(6PTE5MKTI?MU It s i#%ortant to reali1e that there s nothing #agic about re"lection. :hen you re using re"lection to interact with an ob0ect o" an unknown ty%e, the JVM will si#%ly look at the ob0ect and see that it belongs to a %articular class *0ust like ordinary 5TTI, but then, be"ore it can do anything else, the -lass ob0ect #ust be loaded. Thus, the !class "ile "or that %articular ty%e

8=5

#ust still be available to the JVM, either on the local #achine or across the network. So the true di""erence between 5TTI and re"lection is that with 5TTI, the co#%iler o%ens and e&a#ines the !class "ile at co#%ile' ti#e. Put another way, you can call all the #ethods o" an ob0ect in the !nor#al$ way. :ith re"lection, the !class "ile is unavailable at co#%ile' ti#e; it is o%ened and e&a#ined by the run'ti#e environ#ent. RFSURF STIJLT+(6PTE5MKTI?KU

A class method e0tractor


/ou ll rarely need to use the re"lection tools directly; they re in the language to su%%ort other Java "eatures, such as ob0ect seriali1ation *+ha%ter MM,, JavaBeans *+ha%ter ML,, and 5MI *+ha%ter MH,. (owever, there are ti#es when it s Auite use"ul to be able to dyna#ically e&tract in"or#ation about a class. )ne e&tre#ely use"ul tool is a class #ethod e&tractor. 6s #entioned be"ore, looking at a class de"inition source code or online docu#entation shows only the #ethods that are de"ined or overridden ,ithin that class de$inition. But there could be do1ens #ore available to you that have co#e "ro# base classes. To locate these is both tedious and ti#e consu#ing @. Eortunately, re"lection %rovides a way to write a si#%le tool that will auto#atically show you the entire inter"ace. (ere s the way it works=

//3 c( 3%ho:Jetho!s.Hava // Ysing reflection to sho: all the #etho!s of // a class, even if the #etho!s are !efine! in // the base class. i#"ort Hava.lang.reflect.B< "ublic class %ho:Jetho!s @ static final %tring usage ? 8usage3 _n8 K 8%ho:Jetho!s =ualifie!.class.na#e_n8 K 8To sho: all #etho!s in class or3 _n8 K 8%ho:Jetho!s =ualifie!.class.na#e :or!_n8 K 8To search for #etho!s involving 2:or!28< "ublic static voi! #ain-%tringNO args. @
@ Es%ecially in the %ast. (owever, Sun has greatly i#%roved its (TMD Java docu#entation

so that it s easier to see base'class #ethods.

8=7

Thinking in Java

,,,'0ruceEckel'com

if-args.length P (. @ %yste#.out."rintln-usage.< %yste#.e6it-'.< A try @ Class c ? Class.for&a#e-argsN'O.< Jetho!NO # ? c.getJetho!s-.< ConstructorNO ctor ? c.getConstructors-.< if-args.length ?? (. @ for -int i ? '< i P #.length< iKK. %yste#.out."rintln-#NiO.< for -int i ? '< i P ctor.length< iKK. %yste#.out."rintln-ctorNiO.< A else @ for -int i ? '< i P #.length< iKK. if-#NiO.to%tring-. .in!e6Gf-argsN(O.4? -(. %yste#.out."rintln-#NiO.< for -int i ? '< i P ctor.length< iKK. if-ctorNiO.to%tring-. .in!e6Gf-argsN(O.4? -(. %yste#.out."rintln-ctorNiO.< A A catch-Class&otLoun!E6ce"tion e. @ %yste#.err."rintln-8&o such class3 8 K e.< A A A ///3>
The -lass #ethods get1etho'sA B and get-onstr*ctorsA B return an array o" 1etho' and -onstr*ctor, res%ectively. Each o" these classes has "urther #ethods to dissect the na#es, argu#ents, and return values o" the #ethods they re%resent. But you can also 0ust use to)tringA B, as is done here, to %roduce a )tring with the entire #ethod signature. The rest o" the code is 0ust "or e&tracting co##and line in"or#ation, deter#ining i" a %articular signature #atches with your target string *using in'e4.fA B,, and %rinting the results. RFSURF STIJLT+(6PTE5MKTI?LU This shows re"lection in action, since the result %roduced by -lass! for/ameA B cannot be known at co#%ile'ti#e, and there"ore all the

8=8

#ethod signature in"or#ation is being e&tracted at run'ti#e. I" you investigate your online docu#entation on re"lection, you ll see that there is enough su%%ort to actually set u% and #ake a #ethod call on an ob0ect that s totally unknown at co#%ile'ti#e *there will be e&a#%les o" this later in this book,. 6gain, this is so#ething you #ay never need to do yoursel"9the su%%ort is there "or 5MI and so a %rogra##ing environ#ent can #ani%ulate JavaBeans9but it s interesting. RFSURF STIJLT+(6PTE5MKTI??U 6n enlightening e&%eri#ent is to run

Hava %ho:Jetho!s %ho:Jetho!s


This %roduces a listing that includes a p*blic de"ault constructor, even though you can see "ro# the code that no constructor was de"ined. The constructor you see is the one that s auto#atically synthesi1ed by the co#%iler. I" you then #ake )ho(1etho's a non' p*blic class *that is, "riendly,, the synthesi1ed de"ault constructor no longer shows u% in the out%ut. The synthesi1ed de"ault constructor is auto#atically given the sa#e access as the class. RFSURFSTIJLT+(6PTE5MKTI?HU The out%ut "or )ho(1etho's is still a little tedious. Eor e&a#%le, here s a %ortion o" the out%ut %roduced by invoking 8ava )ho(1etho's 8ava! lang!)tring=

"ublic boolean Hava.lang.%tring.starts\ith-Hava.lang.%tring,int. "ublic boolean Hava.lang.%tring.starts\ith-Hava.lang.%tring. "ublic boolean Hava.lang.%tring.en!s\ith-Hava.lang.%tring.


It would be even nicer i" the Auali"iers like 8ava!lang could be stri%%ed o"". The )treamTokeni7er class introduced in the %revious cha%ter can hel% create a tool to solve this %roble#=

//3 co#3bruceeckel3util3%tri"/ualifiers.Hava "ackage co#.bruceeckel.util< i#"ort Hava.io.B< "ublic class %tri"/ualifiers @ "rivate %trea#TokeniUer st<

8=:

Thinking in Java

,,,'0ruceEckel'com

"ublic %tri"/ualifiers-%tring =ualifie!. @ st ? ne: %trea#TokeniUerne: %tring5ea!er-=ualifie!..< st.or!inaryChar-2 2.< // `ee" the s"aces A "ublic %tring get&e6t-. @ %tring s ? null< try @ int token ? st.ne6tToken-.< if-token 4? %trea#TokeniUer.TTbEGL. @ s:itch-st.tty"e. @ case %trea#TokeniUer.TTbEGL3 s ? null< break< case %trea#TokeniUer.TTb&YJBE53 s ? Double.to%tring-st.nval.< break< case %trea#TokeniUer.TTb\G5D3 s ? ne: %tring-st.sval.< break< !efault3 // single character in tty"e s ? %tring.valueGf--char.st.tty"e.< A A A catch-$GE6ce"tion e. @ %yste#.err."rintln-8Error fetching token8.< A return s< A "ublic static %tring stri"-%tring =ualifie!. @ %tri"/ualifiers s= ? ne: %tri"/ualifiers-=ualifie!.< %tring s ? 88, si< :hile--si ? s=.get&e6t-.. 4? null. @ int lastDot ? si.last$n!e6Gf-2.2.< if-lastDot 4? -(. si ? si.substring-lastDot K (.< s K? si< A return s< A

8=;

A ///3>
To "acilitate reuse, this class is %laced in com!br*ceeckel!*til. 6s you can see, this uses the )treamTokeni7er and )tring #ani%ulation to do its work. RFSURFSTIJLT+(6PTE5MKTI?3U The new version o" the %rogra# uses the above class to clean u% the out%ut=

//3 c( 3%ho:Jetho!sClean.Hava // %ho:Jetho!s :ith the =ualifiers stri""e! // to #ake the results easier to rea!. i#"ort Hava.lang.reflect.B< i#"ort co#.bruceeckel.util.B< "ublic class %ho:Jetho!sClean @ static final %tring usage ? 8usage3 _n8 K 8%ho:Jetho!sClean =ualifie!.class.na#e_n8 K 8To sho: all #etho!s in class or3 _n8 K 8%ho:Jetho!sClean =ualif.class.na#e :or!_n8 K 8To search for #etho!s involving 2:or!28< "ublic static voi! #ain-%tringNO args. @ if-args.length P (. @ %yste#.out."rintln-usage.< %yste#.e6it-'.< A try @ Class c ? Class.for&a#e-argsN'O.< Jetho!NO # ? c.getJetho!s-.< ConstructorNO ctor ? c.getConstructors-.< // Convert to an array of cleane! %trings3 %tringNO n ? ne: %tringN#.length K ctor.lengthO< for-int i ? '< i P #.length< iKK. @ %tring s ? #NiO.to%tring-.< nNiO ? %tri"/ualifiers.stri"-s.< A for-int i ? '< i P ctor.length< iKK. @ %tring s ? ctorNiO.to%tring-.< nNi K #.lengthO ? %tri"/ualifiers.stri"-s.<

81=

Thinking in Java

,,,'0ruceEckel'com

A if-args.length ?? (. for -int i ? '< i P n.length< iKK. %yste#.out."rintln-nNiO.< else for -int i ? '< i P n.length< iKK. if-nNiO.in!e6Gf-argsN(O.4? -(. %yste#.out."rintln-nNiO.< A catch-Class&otLoun!E6ce"tion e. @ %yste#.err."rintln-8&o such class3 8 K e.< A A A ///3>
The class )ho(1etho's-lean is Auite si#ilar to the %revious )ho(1etho's, e&ce%t that it takes the arrays o" 1etho' and -onstr*ctor and converts the# into a single array o" )tring. Each o" these )tring ob0ects is then %assed through )trip3*alifiers!)tripA B to re#ove all the #ethod Auali"ication. RFSURFSTIJLT+(6PTE5MKTI?GU This tool can be a real ti#e'saver while you re %rogra##ing, when you can t re#e#ber i" a class has a %articular #ethod and you don t want to go walking through the class hierarchy in the online docu#entation, or i" you don t know whether that class can do anything with, "or e&a#%le, -olor ob0ects. RFSURFSTIJLT+(6PTE5MKTI?IU +ha%ter ML contains a 84I version o" this %rogra# *custo#i1ed to e&tract in"or#ation "or Swing co#%onents, so you can leave it running while you re writing code, to allow Auick looku%s. RFSURF STIJLT+(6PTE5MKTI?2U

1ummar:
5TTI allows you to discover ty%e in"or#ation "ro# an anony#ous base' class re"erence. Thus, it s ri%e "or #isuse by the novice since it #ight #ake sense be"ore %oly#or%hic #ethod calls do. Eor #any %eo%le co#ing "ro# a %rocedural background, it s di""icult not to organi1e their %rogra#s into sets o" s(itch state#ents. They could acco#%lish this with 5TTI and thus lose the i#%ortant value o" %oly#or%his# in code

811

develo%#ent and #aintenance. The intent o" Java is that you use %oly#or%hic #ethod calls throughout your code, and you use 5TTI only when you #ust. RFSURFSTIJLT+(6PTE5MKTIH@U (owever, using %oly#or%hic #ethod calls as they are intended reAuires that you have control o" the base'class de"inition because at so#e %oint in the e&tension o" your %rogra# you #ight discover that the base class doesn t include the #ethod you need. I" the base class co#es "ro# a library or is otherwise controlled by so#eone else, a solution to the %roble# is 5TTI= /ou can inherit a new ty%e and add your e&tra #ethod. Elsewhere in the code you can detect your %articular ty%e and call that s%ecial #ethod. This doesn t destroy the %oly#or%his# and e&tensibility o" the %rogra# because adding a new ty%e will not reAuire you to hunt "or switch state#ents in your %rogra#. (owever, when you add new code in your #ain body that reAuires your new "eature, you #ust use 5TTI to detect your %articular ty%e. RFSURFSTIJLT+(6PTE5MKTIHMU Putting a "eature in a base class #ight #ean that, "or the bene"it o" one %articular class, all o" the other classes derived "ro# that base reAuire so#e #eaningless stub o" a #ethod. This #akes the inter"ace less clear and annoys those who #ust override abstract #ethods when they derive "ro# that base class. Eor e&a#%le, consider a class hierarchy re%resenting #usical instru#ents. Su%%ose you wanted to clear the s%it valves o" all the a%%ro%riate instru#ents in your orchestra. )ne o%tion is to %ut a clear)pitValveA B #ethod in the base class Instr*ment, but this is con"using because it i#%lies that #erc*ssion and &lectronic instru#ents also have s%it valves. 5TTI %rovides a #uch #ore reasonable solution in this case because you can %lace the #ethod in the s%eci"ic class * 0in' in this case,, where it s a%%ro%riate. (owever, a #ore a%%ro%riate solution is to %ut a prepareInstr*mentA B #ethod in the base class, but you #ight not see this when you re "irst solving the %roble# and could #istakenly assu#e that you #ust use 5TTI. RFSURF STIJLT+(6PTE5MKTIHKU Einally, 5TTI will so#eti#es solve e""iciency %roble#s. I" your code nicely uses %oly#or%his#, but it turns out that one o" your ob0ects reacts to this general %ur%ose code in a horribly ine""icient way, you can %ick out that ty%e using 5TTI and write case's%eci"ic code to i#%rove the e""iciency. Be wary, however, o" %rogra##ing "or e""iciency too soon. It s

812

Thinking in Java

,,,'0ruceEckel'com

a seductive tra%. It s best to get the %rogra# working $irst, then decide i" it s running "ast enough, and only then should you attack e""iciency issues 9with a %ro"iler. RFSURFSTIJLT+(6PTE5MKTIHLU

/0ercises
Solutions to selected e&ercises can be "ound in the electronic docu#entThe Thinking in Java "nnotated Solution @uide, available "or a s#all "ee "ro# ,,,'0ruceEckel'com.

!7,) 6dd $homboi' to )hapes!8ava. +reate a $homboi',


u%cast it to a )hape, then downcast it back to a $homboi'. Try downcasting to a -ircle and see what ha%%ens. RFSURF STIJLT+(6PTE5MKTIH?U

!7-) Modi"y E&ercise M so that it uses instanceof to check the ty%e


be"ore %er"or#ing the downcast. RFSURF STIJLT+(6PTE5MKTIHHU

!74) Modi"y )hapes!8ava so that it can !highlight$ *set a "lag, in all


sha%es o" a %articular ty%e. The to)tringA B #ethod "or each derived )hape should indicate whether that )hape is !highlighted.$ RFSURFSTIJLT+(6PTE5MKTIH3U

!75) Modi"y )(eet)hop!8ava so that each ty%e o" ob0ect creation is


controlled by a co##and'line argu#ent. That is, i" your co##and line is ! 8ava )(eet)hop -an'y,$ then only the -an'y ob0ect is created. Cotice how you can control which -lass ob0ects are loaded via the co##and'line argu#ent. RFSURF STIJLT+(6PTE5MKTIHGU

!76) 6dd a new ty%e o" #et to #et-o*ntJ!8ava. Veri"y that it is


created and counted correctly in mainA B. RFSURF STIJLT+(6PTE5MKTIHIU

!(7) :rite a #ethod that takes an ob0ect and recursively %rints all
the classes in that ob0ect s hierarchy. RFSURF STIJLT+(6PTE5MKTIH2U

813

!(() Modi"y E&ercise 3 so that it uses -lass!get eclare'Fiel'sA B


to also dis%lay in"or#ation about the "ields in a class. RFSURF STIJLT+(6PTE5MKTI3@U

!(!) In ToyTest!8ava, co##ent out Toy s de"ault constructor and


e&%lain what ha%%ens. RFSURFSTIJLT+(6PTE5MKTI3MU

!(*) Incor%orate a new kind o" interface into ToyTest!8ava and


veri"y that it is detected and dis%layed %ro%erly. RFSURF STIJLT+(6PTE5MKTI3KU

!(+) +reate a new ty%e o" container that uses a private Array+ist
to hold the ob0ects. +a%ture the ty%e o" the "irst ob0ect you %ut in it, and then allow the user to insert ob0ects o" only that ty%e "ro# then on. RFSURFSTIJLT+(6PTE5MKTI3LU

!(,) :rite a %rogra# to deter#ine whether an array o" char is a


%ri#itive ty%e or a true ob0ect. RFSURFSTIJLT+(6PTE5MKTI3?U

!(-) I#%le#ent clear)pitValveA B as described in the su##ary.


RFSURFSTIJLT+(6PTE5MKTI3HU

!(4) I#%le#ent the rotateA)hapeB #ethod described in this


cha%ter, such that it checks to see i" it is rotating a -ircle *and, i" so, doesn t %er"or# the o%eration,. RFSURF STIJLT+(6PTE5MKTI33U

!(5) Modi"y E&ercise 3 so that it uses re"lection instead o" 5TTI. RF


SURFSTIJLT+(6PTE5MKTI3GU

!(6) Modi"y E&ercise G so that it uses re"lection instead o" 5TTI. RF


SURFSTIJLT+(6PTE5MKTI3IU

!!7) In ToyTest!8ava, use re"lection to create a Toy ob0ect using


the nonde"ault constructor. RFSURFSTIJLT+(6PTE5MKTI32U

!!() Dook u% the inter"ace "or 8ava!lang!-lass in the (TMD Java


docu#entation "ro# >ava'sun'com. :rite a %rogra# that takes the na#e o" a class as a co##and'line argu#ent, then uses the -lass #ethods to du#% all the in"or#ation available "or that

814

Thinking in Java

,,,'0ruceEckel'com

class. Test your %rogra# with a standard library class and a class you create. RFSU

815

(*: Creating Windows L A..lets


RFSTIJLT+(6PTE5MLTI@U6 "unda#ental design guideline is !#ake si#%le things easy, and di""icult things %ossible.$
@

The original design goal o" the gra%hical user inter"ace *84I, library in Java M.@ was to allow the %rogra##er to build a 84I that looks good on all %lat"or#s. That goal was not achieved. Instead, the Java M.@ "bstract Bindo, Toolkit *6:T, %roduces a 84I that looks eAually #ediocre on all syste#s. In addition, it s restrictive= you can use only "our "onts and you cannot access any o" the #ore so%histicated 84I ele#ents that e&ist in your o%erating syste#. The Java M.@ 6:T %rogra##ing #odel is also awkward and non'ob0ect'oriented. 6 student in one o" #y se#inars *who had been at Sun during the creation o" Java, e&%lained why= the original 6:T had been conce%tuali1ed, designed, and i#%le#ented in a #onth. +ertainly a #arvel o" %roductivity, and also an ob0ect lesson in why design is i#%ortant. RFSURFSTIJLT+(6PTE5MLTIMU The situation i#%roved with the Java M.M 6:T event #odel, which takes a #uch clearer, ob0ect'oriented a%%roach, along with the addition o" JavaBeans, a co#%onent %rogra##ing #odel that is oriented toward the easy creation o" visual %rogra##ing environ#ents. Java K "inishes the trans"or#ation away "ro# the old Java M.@ 6:T by essentially re%lacing everything with the Java 9oundation Classes *JE+,, the 84I %ortion o" which is called !Swing.$ These are a rich set o" easy'to'use, easy'to' understand JavaBeans that can be dragged and dro%%ed *as well as hand
@ 6 variation on this is called !the %rinci%le o" least astonish#ent,$ which essentially says= !don t sur%rise the user.$

817

%rogra##ed, to create a 84I that you can *"inally, be satis"ied with. The !revision L$ rule o" the so"tware industry *a %roduct isn t good until revision L, see#s to hold true with %rogra##ing languages as well. RF SURFSTIJLT+(6PTE5MLTIKU This cha%ter does not cover anything but the #odern, Java K Swing library, and #akes the reasonable assu#%tion that Swing is the "inal destination 84I library "or Java. I" "or so#e reason you need to use the original !old$ 6:T *because you re su%%orting old code or you have browser li#itations,, you can "ind that introduction in the "irst edition o" this book, downloadable at ,,,'0ruceEckel'com *also included on the +7 5)M bound with this book,. RFSURFSTIJLT+(6PTE5MLTILU Early in this cha%ter, you ll see how things are di""erent when you want to create an a%%let vs. a regular a%%lication using Swing, and how to create %rogra#s that are both a%%lets and a%%lications so they can be run either inside a browser or "ro# the co##and line. 6l#ost all the 84I e&a#%les in this book will be e&ecutable as either a%%lets or a%%lications. RFSURF STIJLT+(6PTE5MLTI?U Please be aware that this is not a co#%rehensive glossary o" either all the Swing co#%onents, or all the #ethods "or the described classes. :hat you see here is intended to be si#%le. The Swing library is vast, and the goal o" this cha%ter is only to get you started with the essentials and co#"ortable with the conce%ts. I" you need to do #ore, then Swing can %robably give you what you want i" you re willing to do the research. RF SURFSTIJLT+(6PTE5MLTIHU I assu#e here that you have downloaded and installed the *"ree, Java library docu#ents in (TMD "or#at "ro# >ava'sun'com and will browse the 8ava4!s(ing classes in that docu#entation to see the "ull details and #ethods o" the Swing library. Because o" the si#%licity o" the Swing design, this will o"ten be enough in"or#ation to solve your %roble#. There are nu#erous *rather thick, books dedicated solely to Swing and you ll want to go to those i" you need #ore de%th, or i" you want to #odi"y the de"ault Swing behavior. RFSURFSTIJLT+(6PTE5MLTI3U 6s you learn about Swing you ll discover= RFSURF STIJLT+(6PTE5MLTIGU

Cha ter 13! Creating Bindo,s & "

lets

818

((+) Swing is a #uch better %rogra##ing #odel than you ve %robably


seen in other languages and develo%#ent environ#ents. JavaBeans *which will be introduced toward the end o" this cha%ter, is the "ra#ework "or that library. RFSURF STIJLT+(6PTE5MLTIIU

((,) !84I builders$ *visual %rogra##ing environ#ents, are a de rigueur as%ect o" a co#%lete Java develo%#ent environ#ent.
JavaBeans and Swing allow the 84I builder to write code "or you as you %lace co#%onents onto "or#s using gra%hical tools. This not only ra%idly s%eeds develo%#ent during 84I building, but it allows "or greater e&%eri#entation and thus the ability to try out #ore designs and %resu#ably co#e u% with a better one. RFSURF STIJLT+(6PTE5MLTI2U

((-) The si#%licity and well'designed nature o" Swing #eans that even
i" you do use a 84I builder rather than coding by hand, the resulting code will still be co#%rehensible9this solves a big %roble# with 84I builders "ro# the %ast, which could easily generate unreadable code. RFSURFSTIJLT+(6PTE5MLTIM@U Swing contains all the co#%onents that you e&%ect to see in a #odern 4I, everything "ro# buttons that contain %ictures to trees and tables. It s a big library, but it s designed to have a%%ro%riate co#%le&ity "or the task at hand9i" so#ething is si#%le, you don t have to write #uch code but as you try to do #ore co#%le& things, your code beco#es %ro%ortionally #ore co#%le&. This #eans an easy entry %oint, but you ve got the %ower i" you need it. RFSURFSTIJLT+(6PTE5MLTIMMU Much o" what you ll like about Swing could be called !orthogonality o" use.$ That is, once you %ick u% the general ideas about the library you can a%%ly the# everywhere. Pri#arily because o" the standard na#ing conventions, #uch o" the ti#e that I was writing these e&a#%les I could guess at the #ethod na#es and get it right the "irst ti#e, without looking anything u%. This is certainly the hall#ark o" a good library design. In addition, you can generally %lug co#%onents into other co#%onents and things will work correctly. RFSURFSTIJLT+(6PTE5MLTIMKU Eor s%eed, all the co#%onents are !lightweight,$ and Swing is written entirely in Java "or %ortability. RFSURFSTIJLT+(6PTE5MLTIMLU

81:

>eyboard navigation is auto#atic9you can run a Swing a%%lication without using the #ouse, and this doesn t reAuire any e&tra %rogra##ing. Scrolling su%%ort is e""ortless9you si#%ly wra% your co#%onent in a J)croll#ane as you add it to your "or#. Eeatures such as tool ti%s ty%ically reAuire a single line o" code to use. RFSURF STIJLT+(6PTE5MLTIM?U Swing also su%%orts a rather radical "eature called !%luggable look and "eel,$ which #eans that the a%%earance o" the 4I can be dyna#ically changed to suit the e&%ectations o" users working under di""erent %lat"or#s and o%erating syste#s. It s even %ossible *albeit di""icult, to invent your own look and "eel. RFSURFSTIJLT+(6PTE5MLTIMHU

#he basic a..let


)ne o" Java s design goals is to create a lets, which are little %rogra#s that run inside a :eb browser. Because they #ust be sa"e, a%%lets are li#ited in what they can acco#%lish. (owever, a%%lets are a %ower"ul tool that su%%ort client'side %rogra##ing, a #a0or issue "or the :eb. RFSURF STIJLT+(6PTE5MLTIM3U

A..let restrictions
Progra##ing within an a%%let is so restrictive that it s o"ten re"erred to as being !inside the sandbo&,$ since you always have so#eone9that is, the Java run'ti#e security syste#9watching over you. RFSURF STIJLT+(6PTE5MLTIMGU (owever, you can also ste% outside the sandbo& and write regular a%%lications rather than a%%lets, in which case you can access the other "eatures o" your )S. :e ve been writing regular a%%lications all along in this book, but they ve been console a lications without any gra%hical co#%onents. Swing can also be used to build 84I inter"aces "or regular a%%lications. RFSURFSTIJLT+(6PTE5MLTIMIU /ou can generally answer the Auestion o" what an a%%let is able to do by looking at what it is su osed to do= e&tend the "unctionality o" a :eb %age in a browser. Since, as a Cet sur"er, you never really know i" a :eb

Cha ter 13! Creating Bindo,s & "

lets

81;

%age is "ro# a "riendly %lace or not, you want any code that it runs to be sa"e. So the biggest restrictions you ll notice are %robably= RFSURF STIJLT+(6PTE5MLTIM2U

((4) "n a

let canJt touch the local disk. This #eans writing or reading,

since you wouldn t want an a%%let to read and trans#it %rivate in"or#ation over the Internet without your %er#ission. :riting is %revented, o" course, since that would be an o%en invitation to a virus. Java o""ers digital signing "or a%%lets. Many a%%let restrictions are rela&ed when you choose to allow trusted a lets *those signed by a trusted source, to have access to your #achine. RFSURFSTIJLT+(6PTE5MLTIK@U

((5) "

lets can take longer to dis la)D since you #ust download the whole thing every ti#e, including a se%arate server hit "or each di""erent class. /our browser can cache the a%%let, but there are no guarantees. Because o" this, you should always %ackage your a%%lets in a J65 *Java 65chive, "ile that co#bines all the a%%let co#%onents *including other !class "iles as well as i#ages and sounds, together into a single co#%ressed "ile that can be downloaded in a single server transaction. !7igital signing$ is available "or each individual entry in the J65 "ile. RFSURF STIJLT+(6PTE5MLTIKMU

A..let advantages
I" you can live within the restrictions, a%%lets have de"inite advantages, es%ecially when building clientFserver or other networked a%%lications= RFSURFSTIJLT+(6PTE5MLTIKKU

((6) There is no installation issue' 6n a%%let has true %lat"or#


inde%endence *including the ability to easily %lay audio "iles, etc., so you don t need to #ake any changes in your code "or di""erent %lat"or#s nor does anyone have to %er"or# any !tweaking$ on installation. In "act, installation is auto#atic every ti#e the user loads the :eb %age that contains a%%lets, so u%dates ha%%en silently and auto#atically. In traditional clientFserver syste#s, building and installing a new version o" the client so"tware is o"ten a night#are. RFSURFSTIJLT+(6PTE5MLTIKLU

82=

(!7) Lou donJt have to ,orr) about bad code causing damage to someoneJs s)stemD because o" the security built into the core Java
language and a%%let structure. This, along with the %revious %oint, #akes Java %o%ular "or so'called intranet clientFserver a%%lications that live only within a co#%any or restricted arena o" o%eration where the user environ#ent *:eb browser and add'ins, can be s%eci"ied andFor controlled. RFSURF STIJLT+(6PTE5MLTIK?U Because a%%lets are auto#atically integrated with (TMD, you have a built'in %lat"or#'inde%endent docu#entation syste# to su%%ort the a%%let. It s an interesting twist, since we re used to having the docu#entation %art o" the %rogra# rather than vice versa. RFSURF STIJLT+(6PTE5MLTIKHU

A..lication frameworks
Dibraries are o"ten grou%ed according to their "unctionality. So#e libraries, "or e&a#%le, are used as is, o"" the shel". The standard Java library )tring and Array+ist classes are e&a#%les o" these. )ther libraries are designed s%eci"ically as building blocks to create other classes. 6 certain category o" library is the a lication $rame,ork, whose goal is to hel% you build a%%lications by %roviding a class or set o" classes that %roduces the basic behavior that you need in every a%%lication o" a %articular ty%e. Then, to custo#i1e the behavior to your own needs, you inherit "ro# the a%%lication class and override the #ethods o" interest. The a%%lication "ra#ework s de"ault control #echanis# will call your overridden #ethods at the a%%ro%riate ti#e. 6n a%%lication "ra#ework is a good e&a#%le o" !se%arating the things that change "ro# the things that stay the sa#e,$ since it atte#%ts to locali1e all the uniAue %arts o" a %rogra# in the overridden #ethods @. RFSURFSTIJLT+(6PTE5MLTIK3U 6%%lets are built using an a%%lication "ra#ework. /ou inherit "ro# class JApplet and override the a%%ro%riate #ethods. There are a "ew #ethods that control the creation and e&ecution o" an a%%let on a :eb %age=

@ This is an e&a#%le o" the design %attern called the tem late method.

Cha ter 13! Creating Bindo,s & "

lets

821

1etho' initA B startA B

.peration
6uto#atically called to %er"or# "irst'ti#e initiali1ation o" the a%%let, including co#%onent layout. /ou ll always override this #ethod. +alled every ti#e the a%%let #oves into sight on the :eb browser to allow the a%%let to start u% its nor#al o%erations *es%ecially those that are shut o"" by stop A B,. 6lso called a"ter initA B. +alled every ti#e the a%%let #oves out o" sight on the :eb browser to allow the a%%let to shut o"" e&%ensive o%erations. 6lso called right be"ore 'estroyA B. +alled when the a%%let is being unloaded "ro# the %age to %er"or# "inal release o" resources when the a%%let is no longer used

stopA B 'estroy AB

:ith this in"or#ation you are ready to create a si#%le a%%let=

//3 c()30""let(.Hava // Wery si#"le a""let. i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< "ublic class 0""let( e6ten!s J0""let @ "ublic voi! init-. @ getContentPane-..a!!-ne: JLabel-80""let48..< A A ///3>
Cote that a%%lets are not reAuired to have a mainA B. That s all wired into the a%%lication "ra#ework; you %ut any startu% code in initA B. RFSURF STIJLT+(6PTE5MLTIKGU In this %rogra#, the only activity is %utting a te&t label on the a%%let, via the J+abel class *the old 6:T a%%ro%riated the na#e +abel as well as other na#es o" co#%onents, so you will o"ten see a leading ! J$ used with Swing co#%onents,. The constructor "or this class takes a )tring and uses it to create the label. In the above %rogra# this label is %laced on the "or#. RFSURFSTIJLT+(6PTE5MLTIKIU The initA B #ethod is res%onsible "or %utting all the co#%onents on the "or# using the a''A B #ethod. /ou #ight think that you ought to be able

822

to si#%ly call a''A B by itsel", and in "act that s the way it used to be in the old 6:T. (owever, Swing reAuires you to add all co#%onents to the !content %ane$ o" a "or#, and so you #ust call get-ontent#aneA B as %art o" the a''A B %rocess. RFSURFSTIJLT+(6PTE5MLTIK2U

$unning a..lets inside a Web browser


To run this %rogra# you #ust %lace it inside a :eb %age and view that %age inside your Java'enabled :eb browser. To %lace an a%%let inside a :eb %age you %ut a s%ecial tag inside the (TMD source "or that :eb %age @ to tell the %age how to load and run the a%%let. RFSURF STIJLT+(6PTE5MLTIL@U This %rocess used to be very si#%le, when Java itsel" was si#%le and everyone was on the sa#e bandwagon and incor%orated the sa#e Java su%%ort inside their :eb browsers. Then you #ight have been able to get away with a very si#%le bit o" (TMD inside your :eb %age, like this=

Pa""let co!e?0""let( :i!th?('' height?,'Q P/a""letQ


Then along ca#e the browser and language wars, and we *%rogra##ers and end users alike, lost. 6"ter awhile, JavaSo"t reali1ed that we could no longer e&%ect browsers to su%%ort the correct "lavor o" Java, and the only solution was to %rovide so#e kind o" add'on that would con"or# to a browser s e&tension #echanis#. By using the e&tension #echanis# *which a browser vendor cannot disable9in an atte#%t to gain co#%etitive advantage9without breaking all the third'%arty e&tensions,, JavaSo"t guarantees that Java cannot be shut out o" the :eb browser by an antagonistic vendor. RFSURFSTIJLT+(6PTE5MLTILMU :ith Internet E&%lorer, the e&tension #echanis# is the 6ctiveZ control, and with Cetsca%e it is the %lug'in. In your (TMD code, you #ust %rovide tags to su%%ort both. (ere s what the si#%lest resulting (TMD %age looks like "or Applet>= D

@ It is assu#ed that the reader is "a#iliar with the basics o" (TMD. It s not too hard to "igure out, and there are lots o" books and resources.

Cha ter 13! Creating Bindo,s & "

lets

823

//34 c()30""let(.ht#l Pht#lQPhea!QPtitleQ0""let(P/titleQP/hea!QPhrQ PGBJECT classi!?8clsi!310DCC1I'-'IIE-((D(-B)EC''1',LICCDC)8 :i!th?8(''8 height?8,'8 align?8baseline8 co!ebase?8htt"3//Hava.sun.co#/"ro!ucts/"lugin/(. . / Hinstall-(b b -:in.cabSWersion?(, , ,'8Q PP050J &0JE?8co!e8 W0LYE?80""let(.class8Q PP050J &0JE?8co!ebase8 W0LYE?8.8Q PP050J &0JE?8ty"e8 W0LYE?8a""lication/6-Hava-a""let< version?(. . 8Q PCGJJE&TQ PEJBED ty"e? 8a""lication/6-Hava-a""let<version?(. . 8 :i!th?8 ''8 height?8 ''8 align?8baseline8 co!e?80""let(.class8 co!ebase?8.8 "lugins"age?8htt"3//Hava.sun.co#/"ro!ucts/"lugin/(. / "lugin-install.ht#l8Q P&GEJBEDQ P/CGJJE&TQ &o Java su""ort for 0PPLET44 P/&GEJBEDQ P/EJBEDQ P/GBJECTQ PhrQP/bo!yQP/ht#lQ ///3>
So#e o" these lines were too long and had to be wra%%ed to "it on the %age. The code in this book s source code *on the book s +7 5)M, and downloadable "ro# ,,,'0ruceEckel'com, will work without having to worry about correcting line wra%s. RFSURFSTIJLT+(6PTE5MLTILKU The co'e value gives the na#e o" the !class "ile where the a%%let resides. The (i'th and height s%eci"y the initial si1e o" the a%%let *in %i&els, as be"ore,. There are other ite#s you can %lace within the a%%let tag= a %lace to "ind other !class "iles on the Internet * co'ebase,, align#ent in"or#ation * align,, a s%ecial identi"ier that #akes it %ossible "or a%%lets
@ This %age9in %articular, the [clsid %ortion9see#ed to work "ine with both J7>M.K.K and J7>M.L rc'M. (owever, you #ay "ind that you have to change the tag so#eti#e in the "uture. 7etails can be "ound at >ava'sun'com.

824

to co##unicate with each other * name,, and a%%let %ara#eters to %rovide in"or#ation that the a%%let can retrieve. Para#eters are in the "or#=

P"ara# na#e?8i!entifier8 value ? 8infor#ation8Q


and there can be as #any as you want. RFSURFSTIJLT+(6PTE5MLTILLU The source code %ackage "or this book %rovides an (TMD %age "or each o" the a%%lets in this book, and thus #any e&a#%les o" the a%%let tag. /ou can "ind a "ull and current descri%tion o" the details o" %lacing a%%lets in :eb %ages at >ava'sun'com. RFSURFSTIJLT+(6PTE5MLTIL?U

Csing Appletviewer
Sun s J7> *"reely downloadable "ro# >ava'sun'com, contains a tool called the " letvie,er that %icks the NappletO tags out o" the (TMD "ile and runs the a%%lets without dis%laying the surrounding (TMD te&t. Because the 6%%letviewer ignores everything but 6PPDET tags, you can %ut those tags in the Java source "ile as co##ents=

// Pa""let co!e?Jy0""let :i!th? '' height?(''Q // P/a""letQ


This way, you can run ! appletvie(er 1yApplet!8ava$ and you don t need to create tiny (TMD "iles to run tests. Eor e&a#%le, you can add the co##ented (TMD tags to Applet>!8ava=

//3 c()30""let(b.Hava // E#be!!ing the a""let tag for 0""letvie:er. // Pa""let co!e?0""let(b :i!th?('' height?,'Q // P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< "ublic class 0""let(b e6ten!s J0""let @ "ublic voi! init-. @ getContentPane-..a!!-ne: JLabel-80""let48..< A A ///3>
Cow you can invoke the a%%let with the co##and

Cha ter 13! Creating Bindo,s & "

lets

825

a""letvie:er 0""let(b.Hava
In this book, this "or# will be used "or easy testing o" a%%lets. Shortly, you ll see another coding a%%roach which will allow you to e&ecute a%%lets "ro# the co##and line without the 6%%letviewer. RFSURF STIJLT+(6PTE5MLTILHU

#esting a..lets
/ou can %er"or# a si#%le test without any network connection by starting u% your :eb browser and o%ening the (TMD "ile containing the a%%let tag. 6s the (TMD "ile is loaded, the browser will discover the a%%let tag and go hunt "or the !class "ile s%eci"ied by the co'e value. )" course, it looks at the +D6SSP6T( to "ind out where to hunt, and i" your ! class "ile isn t in the +D6SSP6T( then it will give an error #essage on the status line o" the browser to the e""ect that it couldn t "ind that !class "ile. RFSURFSTIJLT+(6PTE5MLTIL3U :hen you want to try this out on your :eb site things are a little #ore co#%licated. Eirst o" all, you #ust have a :eb site, which "or #ost %eo%le #eans a third'%arty Internet Service Provider *ISP, at a re#ote location. Since the a%%let is 0ust a "ile or set o" "iles, the ISP does not have to %rovide any s%ecial su%%ort "or Java. /ou #ust also have a way to #ove the (TMD "iles and the !class "iles "ro# your site to the correct directory on the ISP #achine. This is ty%ically done with a Eile Trans"er Protocol *ETP, %rogra#, o" which there are #any di""erent ty%es available "or "ree or as shareware. So it would see# that all you need to do is #ove the "iles to the ISP #achine with ETP, then connect to the site and (TMD "ile using your browser; i" the a%%let co#es u% and works, then everything checks out, rightO RFSURFSTIJLT+(6PTE5MLTILGU (ere s where you can get "ooled. I" the browser on the client #achine cannot locate the !class "ile on the server, it will hunt through the +D6SSP6T( on your local #achine. Thus, the a%%let #ight not be loading %ro%erly "ro# the server, but to you it looks "ine during your testing %rocess because the browser "inds it on your #achine. :hen so#eone else connects, however, his or her browser can t "ind it. So when you re testing, #ake sure you erase the relevant !class "iles *or !8ar "ile,

827

on your local #achine to veri"y that they e&ist in the %ro%er location on the server. RFSURFSTIJLT+(6PTE5MLTILIU )ne o" the #ost insidious %laces where this ha%%ened to #e is when I innocently %laced an a%%let inside a package. 6"ter u%loading the (TMD "ile and a%%let, it turned out that the server %ath to the a%%let was con"used because o" the %ackage na#e. (owever, #y browser "ound it in the local +D6SSP6T(. So I was the only one who could %ro%erly load the a%%let. It took so#e ti#e to discover that the package state#ent was the cul%rit. In general, you ll want to leave the package state#ent out o" an a%%let. RFSURFSTIJLT+(6PTE5MLTIL2U

$unning a..lets from the command line


There are ti#es when you d like to #ake a windowed %rogra# do so#ething else other than sit on a :eb %age. Perha%s you d also like it to do so#e o" the things a !regular$ a%%lication can do but still have the vaunted instant %ortability %rovided by Java. In %revious cha%ters in this book we ve #ade co##and'line a%%lications, but in so#e o%erating environ#ents *the Macintosh, "or e&a#%le, there isn t a co##and line. So "or any nu#ber o" reasons you d like to build a windowed, non'a%%let %rogra# using Java. This is certainly a reasonable desire. RFSURF STIJLT+(6PTE5MLTI?@U The Swing library allows you to #ake an a%%lication that %reserves the look and "eel o" the underlying o%erating environ#ent. I" you want to build windowed a%%lications, it #akes sense to do so @ only i" you can use the latest version o" Java and associated tools so you can deliver a%%lications that won t con"ound your users. I" "or so#e reason you re "orced to use an older version o" Java, think hard be"ore co##itting to building a signi"icant windowed a%%lication. RFSURF STIJLT+(6PTE5MLTI?MU

@ In #y o%inion. 6nd a"ter you learn about Swing, you won t want to waste your ti#e on the earlier stu"".

Cha ter 13! Creating Bindo,s & "

lets

828

)"ten you ll want to be able to create a class that can be invoked as either a window or an a%%let. This is es%ecially convenient when you re testing the a%%lets, since it s ty%ically #uch "aster and easier to run the resulting a%%let'a%%lication "ro# the co##and line than it is to start u% a :eb browser or the 6%%letviewer. RFSURFSTIJLT+(6PTE5MLTI?KU To create an a%%let that can be run "ro# the console co##and line, you si#%ly add a mainA B to your a%%let that builds an instance o" the a%%let inside a JFrame.D 6s a si#%le e&a#%le, let s look at Applet>b!8ava #odi"ied to work as both an a%%lication and an a%%let=

//3 c()30""let(c.Hava // 0n a""lication an! an a""let. // Pa""let co!e?0""let(c :i!th?('' height?,'Q // P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class 0""let(c e6ten!s J0""let @ "ublic voi! init-. @ getContentPane-..a!!-ne: JLabel-80""let48..< A // 0 #ain-. for the a""lication3 "ublic static voi! #ain-%tringNO args. @ J0""let a""let ? ne: 0""let(c-.< JLra#e fra#e ? ne: JLra#e-80""let(c8.< // To close the a""lication3 Console.setu"Closing-fra#e.< fra#e.getContentPane-..a!!-a""let.< fra#e.set%iUe-('',,'.< a""let.init-.< a""let.start-.< fra#e.setWisible-true.< A A ///3> mainA B is the only ele#ent added to the a%%let, and the rest o" the a%%let is untouched. The a%%let is created and added to a JFrame so that it can be dis%layed. RFSURFSTIJLT+(6PTE5MLTI?LU
@ 6s described earlier, !Era#e$ was already taken by the 6:T, so Swing uses JEra#e.

82:

The line=

Console.setu"Closing-fra#e.<
+auses the window to be %ro%erly closed. -onsole co#es "ro# com! br*ceeckel!s(ing and will be e&%lained a little later. RFSURF STIJLT+(6PTE5MLTI??U /ou can see that in mainA B, the a%%let is e&%licitly initiali1ed and started since in this case the browser isn t available to do it "or you. )" course, this doesn t %rovide the "ull behavior o" the browser, which also calls stop A B and 'estroyA B, but "or #ost situations it s acce%table. I" it s a %roble#, you can "orce the calls yoursel". @ RFSURF STIJLT+(6PTE5MLTI?HU Cotice the last line=

fra#e.setWisible-true.<
:ithout this, you won t see anything on the screen. RFSURF STIJLT+(6PTE5MLTI?3U

A dis.la: framework
6lthough the code that turns %rogra#s into both a%%lets and a%%lications %roduces valuable results, i" used everywhere it beco#es distracting and wastes %a%er. Instead, the "ollowing dis%lay "ra#ework will be used "or the Swing e&a#%les in the rest o" this book=

//3 co#3bruceeckel3s:ing3Console.Hava // Tool for running %:ing !e#os fro# the // console, both a""lets an! JLra#es. "ackage co#.bruceeckel.s:ing< i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.event.B< "ublic class Console @ // Create a title string fro# the class na#e3
@ This will #ake sense a"ter you ve read "urther in this cha%ter. Eirst, #ake the re"erence

JApplet a static #e#ber o" the class *instead o" a local variable o" mainA B,, and then call applet!stopA B and applet!'estroyA B inside 0in'o(A'apter!(in'o(-losing A B be"ore you call )ystem!e4itA B.

Cha ter 13! Creating Bindo,s & "

lets

82;

"ublic static %tring title-GbHect o. @ %tring t ? o.getClass-..to%tring-.< // 5e#ove the :or! 8class83 if-t.in!e6Gf-8class8. 4? -(. t ? t.substring-+.< return t< A "ublic static voi! setu"Closing-JLra#e fra#e. @ // The JD` (. %olution as an // anony#ous inner class3 fra#e.a!!\in!o:Listener-ne: \in!o:0!a"ter-. @ "ublic voi! :in!o:Closing-\in!o:Event e. @ %yste#.e6it-'.< A A.< // The i#"rove! solution in JD` (.)3 // fra#e.setDefaultCloseG"eration// E9$TbG&bCLG%E.< A "ublic static voi! run-JLra#e fra#e, int :i!th, int height. @ setu"Closing-fra#e.< fra#e.set%iUe-:i!th, height.< fra#e.setWisible-true.< A "ublic static voi! run-J0""let a""let, int :i!th, int height. @ JLra#e fra#e ? ne: JLra#e-title-a""let..< setu"Closing-fra#e.< fra#e.getContentPane-..a!!-a""let.< fra#e.set%iUe-:i!th, height.< a""let.init-.< a""let.start-.< fra#e.setWisible-true.< A "ublic static voi! run-JPanel "anel, int :i!th, int height. @ JLra#e fra#e ? ne: JLra#e-title-"anel..< setu"Closing-fra#e.< fra#e.getContentPane-..a!!-"anel.< fra#e.set%iUe-:i!th, height.<

83=

fra#e.setWisible-true.< A A ///3>
This is a tool you #ay want to use yoursel", so it s %laced in the library com!br*ceeckel!s(ing. The -onsole class consists entirely o" static #ethods. The "irst is used to e&tract the class na#e *using 5TTI, "ro# any ob0ect and to re#ove the word !class,$ which is ty%ically %re%ended by get-lassA B. This uses the )tring #ethods in'e4.fA B to deter#ine whether the word !class$ is there, and s*bstringA B to %roduce the new string without !class$ or the trailing s%ace. This na#e is used to label the window that is dis%layed by the r*nA B #ethods. RFSURF STIJLT+(6PTE5MLTI?GU

set*p-losingA B is used to hide the code that causes a JFrame to e&it a %rogra# when that JFrame is closed. The de"ault behavior is to do nothing, so i" you don t call set*p-losingA B or write the eAuivalent code "or your JFrame, the a%%lication won t close. The reason this code is hidden rather than %lacing it directly in the subseAuent r*nA B #ethods is %artly because it allows you to use the #ethod by itsel" when what you want to do is #ore co#%licated than what r*nA B %rovides. (owever, it also isolates a change "actor= Java K has two ways o" causing certain ty%es o" windows to close. In J7> M.K, the solution is to create a new 0in'o(A'apter class and i#%le#ent (in'o(-losingA B, as seen above *the #eaning o" this will be "ully e&%lained later in this cha%ter,. (owever, during the creation o" J7> M.L the library designers observed that you ty%ically need to close windows whenever you re creating a non' a%%let, and so they added the set efa*lt-lose.perationA B to JFrame and J ialog. Ero# the stand%oint o" writing code, the new #ethod is #uch nicer to use but this book was written while there was still no J7> M.L i#%le#ented on Dinu& and other %lat"or#s, so in the interest o" cross'version %ortability the change was isolated inside set*p-losingA B. RFSURFSTIJLT+(6PTE5MLTI?IU
The r*nA B #ethod is overloaded to work with JApplets, J#anels, and JFrames. Cote that only i" it s a JApplet are initA B and startA B called. RFSURFSTIJLT+(6PTE5MLTI?2U Cow any a%%let can be run "ro# the console by creating a mainA B containing a line like this=

Cha ter 13! Creating Bindo,s & "

lets

831

Console.run-ne: JyClass-., ,'', )''.<


in which the last two argu#ents are the dis%lay width and height. (ere s

Applet>c!8ava #odi"ied to use -onsole= //3 c()30""let(!.Hava // Console runs a""lets fro# the co##an! line. // Pa""let co!e?0""let(! :i!th?('' height?,'Q // P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class 0""let(! e6ten!s J0""let @ "ublic voi! init-. @ getContentPane-..a!!-ne: JLabel-80""let48..< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: 0""let(!-., ('', ,'.< A A ///3>
This allows the eli#ination o" re%eated code while %roviding the greatest "le&ibility in running the e&a#%les. RFSURFSTIJLT+(6PTE5MLTIH@U

Csing the Windows /0.lorer


I" you re using :indows, you can si#%li"y the %rocess o" running a co##and'line Java %rogra# by con"iguring the :indows E&%lorer9the "ile browser in :indows, not the Internet E&%lorer9so that you can si#%ly double'click on a !class "ile to e&ecute it. There are several ste%s in this %rocess. RFSURFSTIJLT+(6PTE5MLTIHMU Eirst, download and install the Perl %rogra##ing language "ro# ,,,' Perl'org. /ou ll "ind the instructions and language docu#entation on that site. RFSURFSTIJLT+(6PTE5MLTIHKU Ce&t, create the "ollowing scri%t without the "irst and last lines *this scri%t is %art o" this book s source'code %ackage,=

//34 c()35unJava.bat Rre# ? 2--B-Perl-B--

832

Recho off "erl -6 -% 8V'8 V( V V) VI V, V+ V* V1 VC goto en!of"erl Rre# 2< S4"erl cfile ? c05aWN'O< cfile ?> s/-.B._..B/_(/< cfile ?> s/-.B__.B-.B./cK/< dHava cfiled< bbE&Dbb 3en!of"erl ///3>
Cow, o%en the :indows E&%lorer, select !View,$ !Eolder )%tions,$ then click on the !Eile Ty%es$ tab. Press the !Cew Ty%e$ button. Eor !7escri%tion o" Ty%e$ enter !Java class "ile.$ Eor !6ssociated E&tension,$ enter !class.$ 4nder !6ctions$ %ress the !Cew$ button. Eor !6ction$ enter !)%en,$ and "or !6%%lication used to %er"or# action$ enter a line like this=

8c3_aaa_Perl_5unJava.bat8 8VL8
/ou #ust custo#i1e the %ath be"ore !5unJava.bat$ to con"or# to the location where you %laced the batch "ile. RFSURF STIJLT+(6PTE5MLTIHLU )nce you %er"or# this installation, you #ay run any Java %rogra# by si#%ly double'clicking on the !class "ile containing a mainA B. RFSURF STIJLT+(6PTE5MLTIH?U

Making a button
Making a button is Auite si#%le= you 0ust call the J2*tton constructor with the label you want on the button. /ou ll see later that you can do "ancier things, like %utting gra%hic i#ages on buttons. RFSURF STIJLT+(6PTE5MLTIHHU 4sually you ll want to create a "ield "or the button inside your class so that you can re"er to it later. RFSURFSTIJLT+(6PTE5MLTIH3U The J2*tton is a co#%onent9its own little window9that will auto#atically get re%ainted as %art o" an u%date. This #eans that you

Cha ter 13! Creating Bindo,s & "

lets

833

don t e&%licitly %aint a button or any other kind o" control; you si#%ly %lace the# on the "or# and let the# auto#atically take care o" %ainting the#selves. So to %lace a button on a "or#, you do it inside initA B=

//3 c()3Button(.Hava // Putting buttons on an a""let. // Pa""let co!e?Button( :i!th? '' height?,'Q // P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Button( e6ten!s J0""let @ JButton b( ? ne: JButton-8Button (8., b ? ne: JButton-8Button 8.< "ublic voi! init-. @ Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< c".a!!-b(.< c".a!!-b .< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Button(-., '', ,'.< A A ///3>
So#ething new has been added here= be"ore any ele#ents are %laced on the content %ane, it is given a new !layout #anager,$ o" ty%e Flo(+ayo*t. The layout #anager is the way that the %ane i#%licitly decides where to %lace the control on the "or#. The nor#al behavior o" an a%%let is to use the 2or'er+ayo*t, but that won t work here because *as you will learn later in this cha%ter when controlling the layout o" a "or# is e&a#ined in #ore detail, it de"aults to covering each control entirely with every new one that is added. (owever, Flo(+ayo*t causes the controls to "low evenly onto the "or#, le"t to right and to% to botto#. RFSURF STIJLT+(6PTE5MLTIHGU

834

Ca.turing an event
/ou ll notice that i" you co#%ile and run the a%%let above, nothing ha%%ens when you %ress the buttons. This is where you #ust ste% in and write so#e code to deter#ine what will ha%%en. The basis o" event'driven %rogra##ing, which co#%rises a lot o" what a 84I is about, is tying events to code that res%onds to those events. RFSURF STIJLT+(6PTE5MLTIHIU The way that this is acco#%lished in Swing is by cleanly se%arating the inter"ace *the gra%hical co#%onents, and the i#%le#entation *the code that you want to run when an event ha%%ens to a co#%onent,. Each Swing co#%onent can re%ort all the events that #ight ha%%en to it, and it can re%ort each kind o" event individually. So i" you re not interested in, "or e&a#%le, whether the #ouse is being #oved over your button, you don t register your interest in that event. It s a very straight"orward and elegant way to handle event'driven %rogra##ing, and once you understand the basic conce%ts you can easily use Swing co#%onents that you haven t seen be"ore9in "act, this #odel e&tends to anything that can be classi"ied as a JavaBean *which you ll learn about later in the cha%ter,. RFSURFSTIJLT+(6PTE5MLTIH2U 6t "irst, we will 0ust "ocus on the #ain event o" interest "or the co#%onents being used. In the case o" a J2*tton, this !event o" interest$ is that the button is %ressed. To register your interest in when a button is %ressed, you call the J2*tton s a''Action+istenerA B #ethod. This #ethod e&%ects an argu#ent that is an ob0ect that i#%le#ents the Action+istener inter"ace, which contains a single #ethod called action#erforme'A B. So all you have to do to attach code to a J2*tton is to i#%le#ent the Action+istener inter"ace in a class, and register an ob0ect o" that class with the J2*tton via a''Action+istenerA B. The #ethod will be called when the button is %ressed *this is nor#ally re"erred to as a callback,. RFSURFSTIJLT+(6PTE5MLTI3@U But what should the result o" %ressing that button beO :e d like to see so#ething change on the screen, so a new Swing co#%onent will be introduced= the JTe4tFiel'. This is a %lace where te&t can be ty%ed, or in this case #odi"ied by the %rogra#. 6lthough there are a nu#ber o" ways

Cha ter 13! Creating Bindo,s & "

lets

835

to create a JTe4tFiel', the si#%lest is 0ust to tell the constructor how wide you want that "ield to be. )nce the JTe4tFiel' is %laced on the "or#, you can #odi"y its contents by using the setTe4tA B #ethod *there are #any other #ethods in JTe4tFiel', but you #ust look these u% in the (TMD docu#entation "or the J7> "ro# >ava'sun'com,. (ere is what it looks like=

//3 c()3Button .Hava // 5es"on!ing to button "resses. // Pa""let co!e?Button :i!th? '' height?*,Q // P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.event.B< i#"ort Hava.a:t.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Button e6ten!s J0""let @ JButton b( ? ne: JButton-8Button (8., b ? ne: JButton-8Button 8.< JTe6tLiel! t6t ? ne: JTe6tLiel!-('.< class BL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e.@ %tring na#e ? --JButton.e.get%ource-...getTe6t-.< t6t.setTe6t-na#e.< A A BL al ? ne: BL-.< "ublic voi! init-. @ b(.a!!0ctionListener-al.< b .a!!0ctionListener-al.< Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< c".a!!-b(.< c".a!!-b .< c".a!!-t6t.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Button -., '', *,.< A

837

A ///3>
+reating a JTe4tFiel' and %lacing it on the canvas takes the sa#e ste%s as "or J2*ttons, or "or any Swing co#%onent. The di""erence in the above %rogra# is in the creation o" the a"ore#entioned Action+istener class 2+. The argu#ent to action#erforme'A B is o" ty%e Action&vent, which contains all the in"or#ation about the event and where it ca#e "ro#. In this case, I wanted to describe the button that was %ressed= get)o*rceA B %roduces the ob0ect where the event originated, and I assu#ed that is a J2*tton. getTe4tA B returns the te&t that s on the button, and this is %laced in the JTe4tFiel' to %rove that the code was actually called when the button was %ressed. RFSURF STIJLT+(6PTE5MLTI3MU In initA B, a''Action+istenerA B is used to register the 2+ ob0ect with both the buttons. RFSURFSTIJLT+(6PTE5MLTI3KU It is o"ten #ore convenient to code the Action+istener as an anony#ous inner class, es%ecially since you tend to only use a single instance o" each listener class. 2*ttonI!8ava can be #odi"ied to use an anony#ous inner class as "ollows= RFSURFSTIJLT+(6PTE5MLTI3LU

//3 c()3Button b.Hava // Ysing anony#ous inner classes. // Pa""let co!e?Button b :i!th? '' height?*,Q // P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.event.B< i#"ort Hava.a:t.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Button b e6ten!s J0""let @ JButton b( ? ne: JButton-8Button (8., b ? ne: JButton-8Button 8.< JTe6tLiel! t6t ? ne: JTe6tLiel!-('.< 0ctionListener al ? ne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e.@ %tring na#e ? --JButton.e.get%ource-...getTe6t-.< t6t.setTe6t-na#e.<

Cha ter 13! Creating Bindo,s & "

lets

838

A A< "ublic voi! init-. @ b(.a!!0ctionListener-al.< b .a!!0ctionListener-al.< Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< c".a!!-b(.< c".a!!-b .< c".a!!-t6t.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Button b-., '', *,.< A A ///3>
The a%%roach o" using an anony#ous inner class will be %re"erred *when %ossible, "or the e&a#%les in this book. RFSURF STIJLT+(6PTE5MLTI3?U

#e0t areas
6 JTe4tArea is like a JTe4tFiel' e&ce%t that it can have #ulti%le lines and has #ore "unctionality. 6 %articularly use"ul #ethod is appen'A B; with this you can easily %our out%ut into the JTe4tArea, thus #aking a Swing %rogra# an i#%rove#ent *since you can scroll backward, over what has been acco#%lished thus "ar using co##and'line %rogra#s that %rint to standard out%ut. 6s an e&a#%le, the "ollowing %rogra# "ills a JTe4tArea with the out%ut "ro# the geography generator in +ha%ter 2=

//3 c()3Te6t0rea.Hava // Ysing the JTe6t0rea control. // Pa""let co!e?Te6t0rea :i!th?I*, height?I ,Q // P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.event.B< i#"ort Hava.a:t.B< i#"ort Hava.util.B< i#"ort co#.bruceeckel.s:ing.B< i#"ort co#.bruceeckel.util.B<

83:

"ublic class Te6t0rea e6ten!s J0""let @ JButton b ? ne: JButton-80!! Data8., c ? ne: JButton-8Clear Data8.< JTe6t0rea t ? ne: JTe6t0rea- ', I'.< Ja" # ? ne: MashJa"-.< "ublic voi! init-. @ // Yse u" all the !ata3 Collections .fill-#, Collections .geogra"hy, CountryCa"itals."airs.length.< b.a!!0ctionListener-ne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e.@ for-$terator it? #.entry%et-..iterator-.< it.has&e6t-.<.@ Ja".Entry #e ? -Ja".Entry.-it.ne6t-..< t.a""en!-#e.get`ey-. K 83 8 K #e.getWalue-. K 8_n8.< A A A.< c.a!!0ctionListener-ne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e.@ t.setTe6t-88.< A A.< Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< c".a!!-ne: J%crollPane-t..< c".a!!-b.< c".a!!-c.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Te6t0rea-., I*,, I ,.< A A ///3>
In initA B, the 1ap is "illed with all the countries and their ca%itals. Cote that "or both buttons the Action+istener is created and added without de"ining an inter#ediate variable, since you never need to re"er to that

Cha ter 13! Creating Bindo,s & "

lets

83;

listener again during the %rogra#. The !6dd 7ata$ button "or#ats and a%%ends all the data, while the !+lear 7ata$ button uses setTe4tA B to re#ove all the te&t "ro# the JTe4tArea. RFSURF STIJLT+(6PTE5MLTI3HU 6s the JTe4tArea is added to the a%%let, it is wra%%ed in a J)croll#ane, to control scrolling when too #uch te&t is %laced on the screen. That s all you #ust do in order to %roduce "ull scrolling ca%abilities. (aving tried to "igure out how to do the eAuivalent in so#e other 84I %rogra##ing environ#ents, I a# very i#%ressed with the si#%licity and good design o" co#%onents like J)croll#ane. RFSURF STIJLT+(6PTE5MLTI33U

Controlling la:out
The way that you %lace co#%onents on a "or# in Java is %robably di""erent "ro# any other 84I syste# you ve used. Eirst, it s all code; there are no !resources$ that control %lace#ent o" co#%onents. Second, the way co#%onents are %laced on a "or# is controlled not by absolute %ositioning but by a !layout #anager$ that decides how the co#%onents lie based on the order that you a''A B the#. The si1e, sha%e, and %lace#ent o" co#%onents will be re#arkably di""erent "ro# one layout #anager to another. In addition, the layout #anagers ada%t to the di#ensions o" your a%%let or a%%lication window, so i" the window di#ension is changed, the si1e, sha%e, and %lace#ent o" the co#%onents can change in res%onse. RFSURFSTIJLT+(6PTE5MLTI3GU

JApplet, JFrame J0in'o(, and J ialog can all %roduce a -ontainer with get-ontent#aneA B that can contain and dis%lay -omponents. In -ontainer, there s a #ethod called set+ayo*tA B that
allows you to choose a di""erent layout #anager. )ther classes, such as J#anel, contain and dis%lay co#%onents directly and so you also set the layout #anager directly, without using the content %ane. RFSURF STIJLT+(6PTE5MLTI3IU In this section we ll e&%lore the various layout #anagers by %lacing buttons in the# *since that s the si#%lest thing to do,. There won t be any

84=

ca%turing o" button events since these e&a#%les are 0ust intended to show how the buttons are laid out. RFSURFSTIJLT+(6PTE5MLTI32U

;order&a:out
The a%%let uses a de"ault layout sche#e= the 2or'er+ayo*t *a nu#ber o" the %revious e&a#%le have changed the layout #anager to Flo(+ayo*t,. :ithout any other instruction, this takes whatever you a''A B to it and %laces it in the center, stretching the ob0ect all the way out to the edges. RFSURFSTIJLT+(6PTE5MLTIG@U (owever, there s #ore to the 2or'er+ayo*t. This layout #anager has the conce%t o" "our border regions and a center area. :hen you add so#ething to a %anel that s using a 2or'er+ayo*t you can use the overloaded a''A B #ethod that takes a constant value as its "irst argu#ent. This value can be any o" the "ollowing=

2or'er+ayo*t! /.$TH *to%, 2or'er+ayo*t! ).UTH *botto#, 2or'er+ayo*t! &A)T *right, 2or'er+ayo*t! 0&)T *le"t, 2or'er+ayo*t!-&/T&$ *"ill the #iddle, u% to the other
co#%onents or to the edges, RFSURFSTIJLT+(6PTE5MLTIGMU I" you don t s%eci"y an area to %lace the ob0ect, it de"aults to -&/T&$. RF SURFSTIJLT+(6PTE5MLTIGKU (ere s a si#%le e&a#%le. The de"ault layout is used, since JApplet de"aults to 2or'er+ayo*t=

//3 c()3Bor!erLayout(.Hava // De#onstrates Bor!erLayout. // Pa""let co!e?Bor!erLayout( // :i!th?)'' height? ,'Q P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Bor!erLayout( e6ten!s J0""let @ "ublic voi! init-. @ Container c" ? getContentPane-.<

Cha ter 13! Creating Bindo,s & "

lets

841

c".a!!-Bor!erLayout.&G5TM, ne: JButton-8&orth8..< c".a!!-Bor!erLayout.%GYTM, ne: JButton-8%outh8..< c".a!!-Bor!erLayout.E0%T, ne: JButton-8East8..< c".a!!-Bor!erLayout.\E%T, ne: JButton-8\est8..< c".a!!-Bor!erLayout.CE&TE5, ne: JButton-8Center8..< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Bor!erLayout(-., )'', ,'.< A A ///3>
Eor every %lace#ent but -&/T&$, the ele#ent that you add is co#%ressed to "it in the s#allest a#ount o" s%ace along one di#ension while it is stretched to the #a&i#u# along the other di#ension. -&/T&$, however, s%reads out in both di#ensions to occu%y the #iddle. RFSURFSTIJLT+(6PTE5MLTIGLU

<low&a:out
This si#%ly !"lows$ the co#%onents onto the "or#, "ro# le"t to right until the to% s%ace is "ull, then #oves down a row and continues "lowing. RF SURFSTIJLT+(6PTE5MLTIG?U (ere s an e&a#%le that sets the layout #anager to Flo(+ayo*t and then %laces buttons on the "or#. /ou ll notice that with Flo(+ayo*t the co#%onents take on their !natural$ si1e. 6 J2*tton, "or e&a#%le, will be the si1e o" its string. RFSURFSTIJLT+(6PTE5MLTIGHU

//3 c()3Llo:Layout(.Hava // De#onstrates Llo:Layout. // Pa""let co!e?Llo:Layout( // :i!th?)'' height? ,'Q P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort co#.bruceeckel.s:ing.B<

842

"ublic class Llo:Layout( e6ten!s J0""let @ "ublic voi! init-. @ Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< for-int i ? '< i P '< iKK. c".a!!-ne: JButton-8Button 8 K i..< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Llo:Layout(-., )'', ,'.< A A ///3>
6ll co#%onents will be co#%acted to their s#allest si1e in a Flo(+ayo*t, so you #ight get a little bit o" sur%rising behavior. Eor e&a#%le, because a J+abel will be the si1e o" its string, atte#%ting to right'0usti"y its te&t yields an unchanged dis%lay when using Flo(+ayo*t. RFSURFSTIJLT+(6PTE5MLTIG3U

'rid&a:out
6 "ri'+ayo*t allows you to build a table o" co#%onents, and as you add the# they are %laced le"t'to'right and to%'to'botto# in the grid. In the constructor you s%eci"y the nu#ber o" rows and colu#ns that you need and these are laid out in eAual %ro%ortions. RFSURF STIJLT+(6PTE5MLTIGGU

//3 c()3ari!Layout(.Hava // De#onstrates ari!Layout. // Pa""let co!e?ari!Layout( // :i!th?)'' height? ,'Q P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class ari!Layout( e6ten!s J0""let @ "ublic voi! init-. @ Container c" ? getContentPane-.< c".setLayout-ne: ari!Layout-*,)..< for-int i ? '< i P '< iKK. c".a!!-ne: JButton-8Button 8 K i..< A

Cha ter 13! Creating Bindo,s & "

lets

843

"ublic static voi! #ain-%tringNO args. @ Console.run-ne: ari!Layout(-., )'', ,'.< A A ///3>
In this case there are KM slots but only K@ buttons. The last slot is le"t e#%ty because no !balancing$ goes on with a "ri'+ayo*t. RFSURF STIJLT+(6PTE5MLTIGIU

'rid;ag&a:out
The "ri'2ag+ayo*t %rovides you with tre#endous control in deciding e&actly how the regions o" your window will lay the#selves out and re"or#at the#selves when the window is resi1ed. (owever, it s also the #ost co#%licated layout #anager, and Auite di""icult to understand. It is intended %ri#arily "or auto#atic code generation by a 84I builder *good 84I builders will use "ri'2ag+ayo*t instead o" absolute %lace#ent,. I" your design is so co#%licated that you "eel you need to use "ri'2ag+ayo*t, then you should be using a 84I builder tool to generate that design. I" you "eel you #ust know the intricate details, I ll re"er you to Core Java 2 by (orst#ann N +ornell *Prentice'(all, M222,, or a dedicated Swing book, as a starting %oint. RFSURF STIJLT+(6PTE5MLTIG2U

Absolute .ositioning
It is also %ossible to set the absolute %osition o" the gra%hical co#%onents in this way=

(!() Set a n*ll layout #anager "or your -ontainer= set+ayo*tAn*llB.


RFSURFSTIJLT+(6PTE5MLTII@U

(!!) +all set2o*n'sA B or reshapeA B *de%ending on the language


version, "or each co#%onent, %assing a bounding rectangle in %i&el coordinates. /ou can do this in the constructor, or in paintA B, de%ending on what you want to achieve. RFSURF STIJLT+(6PTE5MLTIIMU

844

So#e 84I builders use this a%%roach e&tensively, but this is usually not the best way to generate code. More use"ul 84I builders will use "ri'2ag+ayo*t instead. RFSURFSTIJLT+(6PTE5MLTIIKU

;o0&a:out
Because %eo%le had so #uch trouble understanding and working with

"ri'2ag+ayo*t, Swing also includes the 2o4+ayo*t, which gives you #any o" the bene"its o" "ri'2ag+ayo*t without the co#%le&ity, so you
can o"ten use it when you need to do hand'coded layouts *again, i" your design beco#es too co#%le&, use a 84I builder that generates "ri'2ag+ayo*ts "or you,. 2o4+ayo*t allows you to control the %lace#ent o" co#%onents either vertically or hori1ontally, and to control the s%ace between the co#%onents using so#ething called !struts and glue.$ Eirst, let s see how to use the 2o4+ayo*t directly, in the sa#e way that the other layout #anagers have been de#onstrated=

//3 c()3Bo6Layout(.Hava // Wertical an! horiUontal Bo6Layouts. // Pa""let co!e?Bo6Layout( // :i!th?I,' height? ''Q P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Bo6Layout( e6ten!s J0""let @ "ublic voi! init-. @ JPanel H"v ? ne: JPanel-.< H"v.setLayoutne: Bo6Layout-H"v, Bo6Layout.;b09$%..< for-int i ? '< i P ,< iKK. H"v.a!!-ne: JButton-88 K i..< JPanel H"h ? ne: JPanel-.< H"h.setLayoutne: Bo6Layout-H"h, Bo6Layout.9b09$%..< for-int i ? '< i P ,< iKK. H"h.a!!-ne: JButton-88 K i..< Container c" ? getContentPane-.< c".a!!-Bor!erLayout.E0%T, H"v.< c".a!!-Bor!erLayout.%GYTM, H"h.<

Cha ter 13! Creating Bindo,s & "

lets

845

A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Bo6Layout(-., I,', ''.< A A ///3>
The constructor "or 2o4+ayo*t is a bit di""erent than the other layout #anagers9you %rovide the -ontainer that is to be controlled by the 2o4+ayo*t as the "irst argu#ent, and the direction o" the layout as the second argu#ent. RFSURFSTIJLT+(6PTE5MLTIILU To si#%li"y #atters, there s a s%ecial container called 2o4 that uses 2o4+ayo*t as its native #anager. The "ollowing e&a#%le lays out co#%onents hori1ontally and vertically using 2o4, which has two static #ethods to create bo&es with vertical and hori1ontal align#ent=

//3 c()3Bo6(.Hava // Wertical an! horiUontal Bo6Layouts. // Pa""let co!e?Bo6( // :i!th?I,' height? ''Q P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Bo6( e6ten!s J0""let @ "ublic voi! init-. @ Bo6 bv ? Bo6.createWerticalBo6-.< for-int i ? '< i P ,< iKK. bv.a!!-ne: JButton-88 K i..< Bo6 bh ? Bo6.createMoriUontalBo6-.< for-int i ? '< i P ,< iKK. bh.a!!-ne: JButton-88 K i..< Container c" ? getContentPane-.< c".a!!-Bor!erLayout.E0%T, bv.< c".a!!-Bor!erLayout.%GYTM, bh.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Bo6(-., I,', ''.< A A ///3>

847

)nce you have a 2o4, you %ass it as a second argu#ent when adding co#%onents to the content %ane. RFSURFSTIJLT+(6PTE5MLTII?U Struts add s%ace between co#%onents, #easured in %i&els. To use a strut, you si#%ly add it in between the addition o" the co#%onents that you want s%aced a%art=

//3 c()3Bo6 .Hava // 0!!ing struts. // Pa""let co!e?Bo6 // :i!th?I,' height?)''Q P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Bo6 e6ten!s J0""let @ "ublic voi! init-. @ Bo6 bv ? Bo6.createWerticalBo6-.< for-int i ? '< i P ,< iKK. @ bv.a!!-ne: JButton-88 K i..< bv.a!!-Bo6.createWertical%trut-iB('..< A Bo6 bh ? Bo6.createMoriUontalBo6-.< for-int i ? '< i P ,< iKK. @ bh.a!!-ne: JButton-88 K i..< bh.a!!-Bo6.createMoriUontal%trut-iB('..< A Container c" ? getContentPane-.< c".a!!-Bor!erLayout.E0%T, bv.< c".a!!-Bor!erLayout.%GYTM, bh.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Bo6 -., I,', )''.< A A ///3>
Struts se%arate co#%onents by a "i&ed a#ount, but glue is the o%%osite= it se%arates co#%onents by as #uch as %ossible. Thus it s #ore o" a !s%ring$ than !glue$ *and the design on which this was based was called !s%rings and struts$ so the choice o" the ter# is a bit #ysterious,. RFSURF STIJLT+(6PTE5MLTIIHU

Cha ter 13! Creating Bindo,s & "

lets

848

//3 c()3Bo6).Hava // Ysing alue. // Pa""let co!e?Bo6) // :i!th?I,' height?)''Q P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Bo6) e6ten!s J0""let @ "ublic voi! init-. @ Bo6 bv ? Bo6.createWerticalBo6-.< bv.a!!-ne: JLabel-8Mello8..< bv.a!!-Bo6.createWerticalalue-..< bv.a!!-ne: JLabel-80""let8..< bv.a!!-Bo6.createWerticalalue-..< bv.a!!-ne: JLabel-8\orl!8..< Bo6 bh ? Bo6.createMoriUontalBo6-.< bh.a!!-ne: JLabel-8Mello8..< bh.a!!-Bo6.createMoriUontalalue-..< bh.a!!-ne: JLabel-80""let8..< bh.a!!-Bo6.createMoriUontalalue-..< bh.a!!-ne: JLabel-8\orl!8..< bv.a!!-Bo6.createWerticalalue-..< bv.a!!-bh.< bv.a!!-Bo6.createWerticalalue-..< getContentPane-..a!!-bv.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Bo6)-., I,', )''.< A A ///3>
6 strut works in one direction, but a rigid area "i&es the s%acing between co#%onents in both directions=

//3 c()3Bo6I.Hava // 5igi! 0reas are like "airs of struts. // Pa""let co!e?Bo6I // :i!th?I,' height?)''Q P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort co#.bruceeckel.s:ing.B<

84:

"ublic class Bo6I e6ten!s J0""let @ "ublic voi! init-. @ Bo6 bv ? Bo6.createWerticalBo6-.< bv.a!!-ne: JButton-8To"8..< bv.a!!-Bo6.create5igi!0reane: Di#ension-( ', C'...< bv.a!!-ne: JButton-8Botto#8..< Bo6 bh ? Bo6.createMoriUontalBo6-.< bh.a!!-ne: JButton-8Left8..< bh.a!!-Bo6.create5igi!0reane: Di#ension-(+', 1'...< bh.a!!-ne: JButton-85ight8..< bv.a!!-bh.< getContentPane-..a!!-bv.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Bo6I-., I,', )''.< A A ///3>
/ou should be aware that rigid areas are a bit controversial. Since they use absolute values, so#e %eo%le "eel that they cause #ore trouble than they are worth. RFSURFSTIJLT+(6PTE5MLTII3U

#he best a..roachA


Swing is %ower"ul; it can get a lot done with a "ew lines o" code. The e&a#%les shown in this book are reasonably si#%le, and "or learning %ur%oses it #akes sense to write the# by hand. /ou can actually acco#%lish Auite a bit by co#bining si#%le layouts. 6t so#e %oint, however, it sto%s #aking sense to hand'code 84I "or#s9it beco#es too co#%licated and is not a good use o" your %rogra##ing ti#e. The Java and Swing designers oriented the language and libraries to su%%ort 84I building tools, which have been created "or the e&%ress %ur%ose o" #aking your %rogra##ing e&%erience easier. 6s long as you understand what s going on with layouts and how to deal with the events *described ne&t,, it s not %articularly i#%ortant that you actually know the details o" how to lay out co#%onents by hand9let the a%%ro%riate tool do that "or you

Cha ter 13! Creating Bindo,s & "

lets

84;

*Java is, a"ter all, designed to increase %rogra##er %roductivity,. RFSURF STIJLT+(6PTE5MLTIIGU

#he 1wing event model


In the Swing event #odel a co#%onent can initiate *!"ire$, an event. Each ty%e o" event is re%resented by a distinct class. :hen an event is "ired, it is received by one or #ore !listeners,$ which act on that event. Thus, the source o" an event and the %lace where the event is handled can be se%arate. Since you ty%ically use Swing co#%onents as they are, but need to write code that is called when the co#%onents receive an event, this is an e&cellent e&a#%le o" the se%aration o" inter"ace and i#%le#entation. RFSURFSTIJLT+(6PTE5MLTIIIU Each event listener is an ob0ect o" a class that i#%le#ents a %articular ty%e o" listener interface. So as a %rogra##er, all you do is create a listener ob0ect and register it with the co#%onent that s "iring the event. This registration is %er"or#ed by calling an a''XXX+istenerA B #ethod in the event'"iring co#%onent, in which ! XXX$ re%resents the ty%e o" event listened "or. /ou can easily know what ty%es o" events can be handled by noticing the na#es o" the !addDistener$ #ethods, and i" you try to listen "or the wrong events you ll discover your #istake at co#%ile' ti#e. /ou ll see later in the cha%ter that JavaBeans also use the na#es o" the !addDistener$ #ethods to deter#ine what events a Bean can handle. RFSURFSTIJLT+(6PTE5MLTII2U 6ll o" your event logic, then, will go inside a listener class. :hen you create a listener class, the sole restriction is that it #ust i#%le#ent the a%%ro%riate inter"ace. /ou can create a global listener class, but this is a situation in which inner classes tend to be Auite use"ul, not only because they %rovide a logical grou%ing o" your listener classes inside the 4I or business logic classes they are serving, but because *as you shall see later, the "act that an inner class ob0ect kee%s a re"erence to its %arent ob0ect %rovides a nice way to call across class and subsyste# boundaries. RF SURFSTIJLT+(6PTE5MLTI2@U

85=

6ll the e&a#%les so "ar in this cha%ter have been using the Swing event #odel, but the re#ainder o" this section will "ill out the details o" that #odel. RFSURFSTIJLT+(6PTE5MLTI2MU

/vent and listener t:.es


6ll Swing co#%onents include a''XXX+istenerA B and removeXXX+istenerA B #ethods so that the a%%ro%riate ty%es o" listeners can be added and re#oved "ro# each co#%onent. /ou ll notice that the ! XXX$ in each case also re%resents the argu#ent "or the #ethod, "or e&a#%le= a''1y+istenerA1y+istener mB. The "ollowing table includes the basic associated events, listeners, and #ethods, along with the basic co#%onents that su%%ort those %articular events by %roviding the a''XXX+istenerA B and removeXXX+istenerA B #ethods. /ou should kee% in #ind that the event #odel is designed to be e&tensible, so you #ay encounter other events and listener ty%es that are not covered in this table.
&vent, listener interface an' a''6 an' remove6metho's Action&vent Action+istener a''Action+istenerA B removeAction+istenerA B A'8*stment&vent A'8*stment+istener a''A'8*stment+istenerA B removeA'8*stment+istenerA B -omponent&vent -omponent+istener a''-omponent+istenerA B remove-omponent+istenerA B -omponents s*pporting this event J2*tton, J+ist, JTe4tFiel', J1en*Item and its derivatives including J-heck2o41en*Item, J1en*, and Jpop*p1en*! J)crollbar and anything you create that i#%le#ents the A'8*stable interface! K-omponent and its derivatives, including J2*tton, J-anvas, J-heck2o4, J-ombo2o4, -ontainer, J#anel, JApplet, J)croll#ane, 0in'o(, J ialog, JFile ialog, JFrame, J+abel, J+ist, J)crollbar, JTe4tArea, and JTe4tFiel'! -ontainer and its derivatives, including J#anel, JApplet, J)croll#ane, 0in'o(, J ialog, JFile ialog, and JFrame!

-ontainer&vent -ontainer+istener a''-ontainer+istenerA B remove-ontainer+istenerA B

Cha ter 13! Creating Bindo,s & "

lets

851

&vent, listener interface an' a''6 an' remove6metho's Foc*s&vent Foc*s+istener a''Foc*s+istenerA B removeFoc*s+istenerA B %ey&vent %ey+istener a''%ey+istenerA B remove%ey+istenerA B 1o*se&vent *"or both clicks and #otion, 1o*se+istener a''1o*se+istenerA B remove1o*se+istenerA B 1o*se&ventD *"or both clicks and #otion, 1o*se1otion+istener a''1o*se1otion+istenerA B remove1o*se1otion+istener AB 0in'o(&vent 0in'o(+istener a''0in'o(+istenerA B remove0in'o(+istenerA B Item&vent Item+istener a''Item+istenerA B removeItem+istenerA B Te4t&vent Te4t+istener a''Te4t+istenerA B removeTe4t+istenerA B

-omponents s*pporting this event -omponent and 'erivativesK!

-omponent and 'erivativesK!

-omponent and 'erivativesK!

-omponent and 'erivativesK!

0in'o( and its derivatives, including J ialog, JFile ialog, an' JFrame! J-heck2o4, J-heck2o41en*Item, J-ombo2o4, J+ist, and anything that i#%le#ents the Item)electable interface! 6nything derived "ro# JTe4t-omponent, including JTe4tArea and JTe4tFiel'!

/ou can see that each ty%e o" co#%onent su%%orts only certain ty%es o" events. It turns out to be rather di""icult to look u% all the events su%%orted by each co#%onent. 6 si#%ler a%%roach is to #odi"y the )ho(1etho's-lean!8ava %rogra# "ro# +ha%ter MK so that it dis%lays all the event listeners su%%orted by any Swing co#%onent that you enter.
@ There is no 1o*se1otion&vent even though it see#s like there ought to be. +licking and #otion is co#bined into 1o*se&vent, so this second a%%earance o" 1o*se&vent in the table is not an error.

852

+ha%ter MK introduced re$lection and used that "eature to look u% #ethods "or a %articular class9either the entire list o" #ethods or a subset o" those whose na#es #atch a keyword that you %rovide. The #agic o" this is that it can auto#atically show you all the #ethods "or a class without "orcing you to walk u% the inheritance hierarchy e&a#ining the base classes at each level. Thus, it %rovides a valuable ti#esaving tool "or %rogra##ing= because the na#es o" #ost Java #ethods are #ade nicely verbose and descri%tive, you can search "or the #ethod na#es that contain a %articular word o" interest. :hen you "ind what you think you re looking "or, check the online docu#entation. RFSURF STIJLT+(6PTE5MLTI2KU (owever, by +ha%ter MK you hadn t seen Swing, so the tool in that cha%ter was develo%ed as a co##and'line a%%lication. (ere is the #ore use"ul 84I version, s%eciali1ed to look "or the !addDistener$ #ethods in Swing co#%onents=

//3 c()3%ho:0!!Listeners.Hava // Dis"lay the 8a!!999Listener8 #etho!s of any // %:ing class. // Pa""let co!e ? %ho:0!!Listeners // :i!th?,'' height?I''QP/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava6.s:ing.event.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort Hava.lang.reflect.B< i#"ort Hava.io.B< i#"ort co#.bruceeckel.s:ing.B< i#"ort co#.bruceeckel.util.B< "ublic class %ho:0!!Listeners e6ten!s J0""let @ Class cl< Jetho!NO #< ConstructorNO ctor< %tringNO n ? ne: %tringN'O< JTe6tLiel! na#e ? ne: JTe6tLiel!- ,.< JTe6t0rea results ? ne: JTe6t0rea-I', +,.< class &a#eL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @

Cha ter 13! Creating Bindo,s & "

lets

853

%tring n# ? na#e.getTe6t-..tri#-.< if-n#.length-. ?? '. @ results.setTe6t-8&o #atch8.< n ? ne: %tringN'O< return< A try @ cl ? Class.for&a#e-8Hava6.s:ing.8 K n#.< A catch-Class&otLoun!E6ce"tion e6. @ results.setTe6t-8&o #atch8.< return< A # ? cl.getJetho!s-.< // Convert to an array of %trings3 n ? ne: %tringN#.lengthO< for-int i ? '< i P #.length< iKK. nNiO ? #NiO.to%tring-.< reDis"lay-.< A A voi! reDis"lay-. @ // Create the result set3 %tringNO rs ? ne: %tringNn.lengthO< int H ? '< for -int i ? '< i P n.length< iKK. if-nNiO.in!e6Gf-8a!!8. 4? -( DD nNiO.in!e6Gf-8Listener8. 4? -(. rsNHKKO ? nNiO.substring-nNiO.in!e6Gf-8a!!8..< results.setTe6t-88.< for -int i ? '< i P H< iKK. results.a""en!%tri"/ualifiers.stri"-rsNiO. K 8_n8.< A "ublic voi! init-. @ na#e.a!!0ctionListener-ne: &a#eL-..< JPanel to" ? ne: JPanel-.< to".a!!-ne: JLabel8%:ing class na#e -"ress E&TE5.38..< to".a!!-na#e.< Container c" ? getContentPane-.<

854

c".a!!-Bor!erLayout.&G5TM, to".< c".a!!-ne: J%crollPane-results..< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: %ho:0!!Listeners-., ,'',I''.< A A ///3>
The )trip3*alifiers class de"ined in +ha%ter MK is reused here by i#%orting the com!br*ceeckel!*til library. RFSURF STIJLT+(6PTE5MLTI2LU The 84I contains a JTe4tFiel' name in which you can enter the Swing class na#e you want to look u%. The results are dis%layed in a JTe4tArea. RFSURFSTIJLT+(6PTE5MLTI2?U /ou ll notice that there are no buttons or other co#%onents by which to indicate that you want the search to begin. That s because the JTe4tFiel' is #onitored by an Action+istener. :henever you #ake a change and %ress ECTE5, the list is i##ediately u%dated. I" the te&t isn t e#%ty, it is used inside -lass!for/ameA B to try to look u% the class. I" the na#e is incorrect, -lass!for/ameA B will "ail, which #eans that it throws an e&ce%tion. This is tra%%ed and the JTe4tArea is set to !Co #atch.$ But i" you ty%e in a correct na#e *ca%itali1ation counts,, -lass! for/ameA B is success"ul and get1etho'sA B will return an array o" 1etho' ob0ects. Each o" the ob0ects in the array is turned into a )tring via to)tringA B *this %roduces the co#%lete #ethod signature, and added to n, a )tring array. The array n is a #e#ber o" class )ho(A''+isteners and is used in u%dating the dis%lay whenever re isplayA B is called. RFSURFSTIJLT+(6PTE5MLTI2HU

re isplayA B creates an array o" )tring called rs *"or !result set$,. The result set is conditionally co%ied "ro# the )trings in n that contain !add$ and !Distener.$ in'e4.fA B and s*bstringA B are then used to re#ove the Auali"iers like p*blic, static, etc. Einally, )trip3*alifiers!stripA B re#oves the e&tra na#e Auali"iers. RFSURFSTIJLT+(6PTE5MLTI23U
This %rogra# is a convenient way to investigate the ca%abilities o" a Swing co#%onent. )nce you know which events a %articular co#%onent

Cha ter 13! Creating Bindo,s & "

lets

855

su%%orts, you don t need to look anything u% to react to that event. /ou si#%ly=

(!*) Take the na#e o" the event class and re#ove the word !&vent.$ 6dd the word ! +istener$ to what re#ains. This is the listener
inter"ace you #ust i#%le#ent in your inner class. RFSURF STIJLT+(6PTE5MLTI2GU

(!+) I#%le#ent the inter"ace above and write out the #ethods "or the
events you want to ca%ture. Eor e&a#%le, you #ight be looking "or #ouse #ove#ents, so you write code "or the mo*se1ove'A B #ethod o" the 1o*se1otion+istener inter"ace. */ou #ust i#%le#ent the other #ethods, o" course, but there s o"ten a shortcut "or that which you ll see soon., RFSURF STIJLT+(6PTE5MLTI2IU

(!,) +reate an ob0ect o" the listener class in Ste% K. 5egister it with your co#%onent with the #ethod %roduced by %re"i&ing ! a''$ to your listener na#e. Eor e&a#%le, a''1o*se1otion+istenerA B. RF
SURFSTIJLT+(6PTE5MLTI22U (ere are so#e o" the listener inter"aces=

+istener interface (5 a'apter Action+istener A'8*stment+istener -omponent+istener -omponentA'apter

1etho's in interface action#erforme'AAction&ventB a'8*stmentVal*e-hange'A A'8*stment&ventB componentHi''en A-omponent&ventB component)ho(nA-omponent&ventB component1ove'A-omponent&ventB component$esi7e' A-omponent&ventB componentA''e'A-ontainer&ventB component$emove' A-ontainer&ventB foc*s"aine'AFoc*s&ventB foc*s+ostAFoc*s&ventB

-ontainer+istener -ontainerA'apter Foc*s+istener Foc*sA'apter

857

+istener interface (5 a'apter %ey+istener %eyA'apter 1o*se+istener 1o*seA'apter

1etho's in interface key#resse'A%ey&ventB key$elease'A%ey&ventB keyType'A%ey&ventB mo*se-licke'A1o*se&ventB mo*se&ntere'A1o*se&ventB mo*se&4ite'A1o*se&ventB mo*se#resse'A1o*se&ventB mo*se$elease'A1o*se&ventB mo*se ragge'A1o*se&ventB mo*se1ove'A1o*se&ventB (in'o(.pene'A0in'o(&ventB (in'o(-losingA0in'o(&ventB (in'o(-lose'A0in'o(&ventB (in'o(Activate'A0in'o(&ventB (in'o( eactivate'A0in'o(&ventB (in'o(Iconifie'A0in'o(&ventB (in'o( eiconifie'A0in'o(&ventB item)tate-hange'AItem&ventB

1o*se1otion+isten er 1o*se1otionA'apt er 0in'o(+istener 0in'o(A'apter

Item+istener

This is not an e&haustive listing, %artly because the event #odel allows you to create your own event ty%es and associated listeners. Thus, you ll regularly co#e across libraries that have invented their own events, and the knowledge gained in this cha%ter will allow you to "igure out how to use these events.

Csing listener ada.ters for sim.licit:


In the table above, you can see that so#e listener inter"aces have only one #ethod. These are trivial to i#%le#ent since you ll i#%le#ent the# only when you want to write that %articular #ethod. (owever, the listener inter"aces that have #ulti%le #ethods can be less %leasant to use. Eor e&a#%le, so#ething you #ust always do when creating an a%%lication is %rovide a 0in'o(+istener to the JFrame so that when you get the (in'o(-losingA B event you can call )ystem!e4itA B to e&it the a%%lication. But since 0in'o(+istener is an interface, you #ust

Cha ter 13! Creating Bindo,s & "

lets

858

i#%le#ent all o" the other #ethods even i" they don t do anything. This can be annoying. RFSURFSTIJLT+(6PTE5MLTIM@@U To solve the %roble#, so#e *but not all, o" the listener inter"aces that have #ore than one #ethod are %rovided with ada ters, the na#es o" which you can see in the table above. Each ada%ter %rovides de"ault e#%ty #ethods "or each o" the inter"ace #ethods. Then all you need to do is inherit "ro# the ada%ter and override only the #ethods you need to change. Eor e&a#%le, the ty%ical 0in'o(+istener you ll use looks like this *re#e#ber that this has been wra%%ed inside the -onsole class in com!br*ceeckel!s(ing,=

class Jy\in!o:Listener e6ten!s \in!o:0!a"ter @ "ublic voi! :in!o:Closing-\in!o:Event e. @ %yste#.e6it-'.< A A


The whole %oint o" the ada%ters is to #ake the creation o" listener classes easy. RFSURFSTIJLT+(6PTE5MLTIM@MU There is a downside to ada%ters, however, in the "or# o" a %it"all. Su%%ose you write a 0in'o(A'apter like the one above=

class Jy\in!o:Listener e6ten!s \in!o:0!a"ter @ "ublic voi! \in!o:Closing-\in!o:Event e. @ %yste#.e6it-'.< A A


This doesn t work, but it will drive you cra1y trying to "igure out why, since everything will co#%ile and run "ine9e&ce%t that closing the window won t e&it the %rogra#. +an you see the %roble#O It s in the na#e o" the #ethod= 0in'o(-losingA B instead o" (in'o(-losing A B. 6 si#%le sli% in ca%itali1ation results in the addition o" a co#%letely new #ethod. (owever, this is not the #ethod that s called when the window is closing, so you don t get the desired results. 7es%ite the inconvenience, an interface will guarantee that the #ethods are %ro%erly i#%le#ented. RFSURFSTIJLT+(6PTE5MLTIM@KU

85:

#racking multi.le events


To %rove to yoursel" that these events are in "act being "ired, and as an interesting e&%eri#ent, it s worth creating an a%%let that tracks e&tra behavior in a J2*tton *other than 0ust whether it s %ressed or not,. This e&a#%le also shows you how to inherit your own button ob0ect because that s what is used as the target o" all the events o" interest. To do so, you can 0ust inherit "ro# J2*tton.D RFSURFSTIJLT+(6PTE5MLTIM@LU The 1y2*tton class is an inner class o" Track&vent, so 1y2*tton can reach into the %arent window and #ani%ulate its te&t "ields, which is what s necessary to be able to write the status in"or#ation into the "ields o" the %arent. )" course this is a li#ited solution, since my2*tton can be used only in con0unction with Track&vent. This kind o" code is so#eti#es called !highly cou%led$=

//3 c()3TrackEvent.Hava // %ho: events as they ha""en. // Pa""let co!e?TrackEvent // :i!th?*'' height?,''QP/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort Hava.util.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class TrackEvent e6ten!s J0""let @ MashJa" h ? ne: MashJa"-.< %tringNO event ? @ 8focusaaine!8, 8focusLost8, 8keyPresse!8, 8key5elease!8, 8keyTy"e!8, 8#ouseClicke!8, 8#ouseEntere!8, 8#ouseE6ite!8,8#ousePresse!8, 8#ouse5elease!8, 8#ouseDragge!8, 8#ouseJove!8 A< JyButton b( ? ne: JyButton-Color.blue, 8test(8., b ? ne: JyButton-Color.re!, 8test 8.< class JyButton e6ten!s JButton @
@ In Java M.@FM.M you could not use"ully inherit "ro# the button ob0ect. This was only one o" nu#erous "unda#ental design "laws.

Cha ter 13! Creating Bindo,s & "

lets

85;

voi! re"ort-%tring fiel!, %tring #sg. @ --JTe6tLiel!.h.get-fiel!...setTe6t-#sg.< A LocusListener fl ? ne: LocusListener-. @ "ublic voi! focusaaine!-LocusEvent e. @ re"ort-8focusaaine!8, e."ara#%tring-..< A "ublic voi! focusLost-LocusEvent e. @ re"ort-8focusLost8, e."ara#%tring-..< A A< `eyListener kl ? ne: `eyListener-. @ "ublic voi! keyPresse!-`eyEvent e. @ re"ort-8keyPresse!8, e."ara#%tring-..< A "ublic voi! key5elease!-`eyEvent e. @ re"ort-8key5elease!8, e."ara#%tring-..< A "ublic voi! keyTy"e!-`eyEvent e. @ re"ort-8keyTy"e!8, e."ara#%tring-..< A A< JouseListener #l ? ne: JouseListener-. @ "ublic voi! #ouseClicke!-JouseEvent e. @ re"ort-8#ouseClicke!8, e."ara#%tring-..< A "ublic voi! #ouseEntere!-JouseEvent e. @ re"ort-8#ouseEntere!8, e."ara#%tring-..< A "ublic voi! #ouseE6ite!-JouseEvent e. @ re"ort-8#ouseE6ite!8, e."ara#%tring-..< A "ublic voi! #ousePresse!-JouseEvent e. @ re"ort-8#ousePresse!8, e."ara#%tring-..< A "ublic voi! #ouse5elease!-JouseEvent e. @ re"ort-8#ouse5elease!8, e."ara#%tring-..< A A< JouseJotionListener ##l ? ne: JouseJotionListener-. @

87=

"ublic voi! #ouseDragge!-JouseEvent e. @ re"ort-8#ouseDragge!8, e."ara#%tring-..< A "ublic voi! #ouseJove!-JouseEvent e. @ re"ort-8#ouseJove!8, e."ara#%tring-..< A A< "ublic JyButton-Color color, %tring label. @ su"er-label.< setBackgroun!-color.< a!!LocusListener-fl.< a!!`eyListener-kl.< a!!JouseListener-#l.< a!!JouseJotionListener-##l.< A A "ublic voi! init-. @ Container c ? getContentPane-.< c.setLayout-ne: ari!Layout-event.lengthK(, ..< for-int i ? '< i P event.length< iKK. @ JTe6tLiel! t ? ne: JTe6tLiel!-.< t.setE!itable-false.< c.a!!-ne: JLabel-eventNiO, JLabel.5$aMT..< c.a!!-t.< h."ut-eventNiO, t.< A c.a!!-b(.< c.a!!-b .< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: TrackEvent-., *'', ,''.< A A ///3>
In the 1y2*tton constructor, the button s color is set with a call to )et2ackgro*n'A B. The listeners are all installed with si#%le #ethod calls. RFSURFSTIJLT+(6PTE5MLTIM@?U The Track&vent class contains a Hash1ap to hold the strings re%resenting the ty%e o" event and JTe4tFiel's where in"or#ation about that event is held. )" course, these could have been created statically

Cha ter 13! Creating Bindo,s & "

lets

871

rather than %utting the# in a Hash1ap, but I think you ll agree that it s a lot easier to use and change. In %articular, i" you need to add or re#ove a new ty%e o" event in Track&vent, you si#%ly add or re#ove a string in the event array9everything else ha%%ens auto#atically. RFSURF STIJLT+(6PTE5MLTIM@HU :hen reportA B is called it is given the na#e o" the event and the %ara#eter string "ro# the event. It uses the Hash1ap h in the outer class to look u% the actual JTe4tFiel' associated with that event na#e, and then %laces the %ara#eter string into that "ield. RFSURF STIJLT+(6PTE5MLTIM@3U This e&a#%le is "un to %lay with since you can really see what s going on with the events in your %rogra#. RFSURFSTIJLT+(6PTE5MLTIM@GU

A catalog of 1wing com.onents


Cow that you understand layout #anagers and the event #odel, you re ready to see how Swing co#%onents can be used. This section is a none&haustive tour o" the Swing co#%onents and "eatures that you ll %robably use #ost o" the ti#e. Each e&a#%le is intended to be reasonably s#all so that you can easily li"t the code and use it in your own %rogra#s. RFSURFSTIJLT+(6PTE5MLTIM@IU /ou can easily see what each o" these e&a#%les looks like while running by viewing the (TMD %ages in the downloadable source code "or this cha%ter. RFSURFSTIJLT+(6PTE5MLTIM@2U

>ee% in #ind= (!-) The (TMD docu#entation "ro# >ava'sun'com contains all o" the
Swing classes and #ethods *only a "ew are shown here,. RFSURF STIJLT+(6PTE5MLTIMM@U

(!4) Because o" the na#ing convention used "or Swing events, it s "airly
easy to guess how to write and install a handler "or a %articular ty%e o" event. 4se the looku% %rogra# )ho(A''+isteners!8ava

872

"ro# earlier in this cha%ter to aid in your investigation o" a %articular co#%onent. RFSURFSTIJLT+(6PTE5MLTIMMMU

(!5) :hen things start to get co#%licated you should graduate to a 84I
builder. RFSURFSTIJLT+(6PTE5MLTIMMKU

;uttons
Swing includes a nu#ber o" di""erent ty%es o" buttons. 6ll buttons, check bo&es, radio buttons, and even #enu ite#s are inherited "ro# Abstract2*tton *which, since #enu ite#s are included, would %robably have been better na#ed !6bstract+hooser$ or so#ething eAually general,. /ou ll see the use o" #enu ite#s shortly, but the "ollowing e&a#%le shows the various ty%es o" buttons available= RFSURF STIJLT+(6PTE5MLTIMMLU

//3 c()3Buttons.Hava // Warious %:ing buttons. // Pa""let co!e?Buttons // :i!th?),' height?(''QP/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort Hava6.s:ing."laf.basic.B< i#"ort Hava6.s:ing.bor!er.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Buttons e6ten!s J0""let @ JButton Hb ? ne: JButton-8JButton8.< Basic0rro:Button u" ? ne: Basic0rro:ButtonBasic0rro:Button.&G5TM., !o:n ? ne: Basic0rro:ButtonBasic0rro:Button.%GYTM., right ? ne: Basic0rro:ButtonBasic0rro:Button.E0%T., left ? ne: Basic0rro:ButtonBasic0rro:Button.\E%T.< "ublic voi! init-. @ Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..<

Cha ter 13! Creating Bindo,s & "

lets

873

c".a!!-Hb.< c".a!!-ne: JToggleButton-8JToggleButton8..< c".a!!-ne: JCheckBo6-8JCheckBo68..< c".a!!-ne: J5a!ioButton-8J5a!ioButton8..< JPanel H" ? ne: JPanel-.< H".setBor!er-ne: Title!Bor!er-8Directions8..< H".a!!-u".< H".a!!-!o:n.< H".a!!-left.< H".a!!-right.< c".a!!-H".< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Buttons-., ),', (''.< A A ///3>
This begins with the 2asicArro(2*tton "ro# 8ava4!s(ing!plaf! basic, then continues with the various s%eci"ic ty%es o" buttons. :hen you run the e&a#%le, you ll see that the toggle button holds its last %osition, in or out. But the check bo&es and radio buttons behave identically to each other, 0ust clicking on or o"" *they are inherited "ro# JToggle2*tton,. RFSURFSTIJLT+(6PTE5MLTIMM?U

;utton grou.s
I" you want radio buttons to behave in an !e&clusive or$ "ashion, you #ust add the# to a !button grou%.$ But, as the e&a#%le below de#onstrates, any Abstract2*tton can be added to a 2*tton"ro*p. RFSURF STIJLT+(6PTE5MLTIMMHU To avoid re%eating a lot o" code, this e&a#%le uses re"lection to generate the grou%s o" di""erent ty%es o" buttons. This is seen in make2#anelA B, which creates a button grou% and a J#anel. The second argu#ent to make2#anelA B is an array o" )tring. Eor each )tring, a button o" the class re%resented by the "irst argu#ent is added to the J#anel=

//3 c()3Buttonarou"s.Hava // Yses reflection to create grou"s // of !ifferent ty"es of 0bstractButton. // Pa""let co!e?Buttonarou"s

874

// :i!th?,'' height?)''QP/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort Hava6.s:ing.bor!er.B< i#"ort Hava.lang.reflect.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Buttonarou"s e6ten!s J0""let @ static %tringNO i!s ? @ 8June8, 8\ar!8, 8Beaver8, 8\ally8, 8E!!ie8, 8Lu#"y8, A< static JPanel #akeBPanel-Class bClass, %tringNO i!s. @ Buttonarou" bg ? ne: Buttonarou"-.< JPanel H" ? ne: JPanel-.< %tring title ? bClass.get&a#e-.< title ? title.substringtitle.last$n!e6Gf-2.2. K (.< H".setBor!er-ne: Title!Bor!er-title..< for-int i ? '< i P i!s.length< iKK. @ 0bstractButton ab ? ne: JButton-8faile!8.< try @ // aet the !yna#ic constructor #etho! // that takes a %tring argu#ent3 Constructor ctor ? bClass.getConstructorne: ClassNO @ %tring.class A.< // Create a ne: obHect3 ab ? -0bstractButton.ctor.ne:$nstancene: GbHectNO@i!sNiOA.< A catch-E6ce"tion e6. @ %yste#.err."rintln-8can2t create 8 K bClass.< A bg.a!!-ab.< H".a!!-ab.< A return H"< A "ublic voi! init-. @

Cha ter 13! Creating Bindo,s & "

lets

875

Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< c".a!!-#akeBPanel-JButton.class, i!s..< c".a!!-#akeBPanel-JToggleButton.class, i!s..< c".a!!-#akeBPanel-JCheckBo6.class, i!s..< c".a!!-#akeBPanel-J5a!ioButton.class, i!s..< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Buttonarou"s-., ,'', )''.< A A ///3>
The title "or the border is taken "ro# the na#e o" the class, stri%%ing o"" all the %ath in"or#ation. The Abstract2*tton is initiali1ed to a J2*tton that has the label !Eailed$ so i" you ignore the e&ce%tion #essage, you ll still see the %roble# on screen. The get-onstr*ctorA B #ethod %roduces a -onstr*ctor ob0ect that takes the array o" argu#ents o" the ty%es in the -lass array %assed to get-onstr*ctorA B. Then all you do is call ne(InstanceA B, %assing it an array o" .b8ect containing your actual argu#ents9in this case, 0ust the )tring "ro# the i's array. RFSURFSTIJLT+(6PTE5MLTIMM3U This adds a little co#%le&ity to what is a si#%le %rocess. To get !e&clusive or$ behavior with buttons, you create a button grou% and add each button "or which you want that behavior to the grou%. :hen you run the %rogra#, you ll see that all the buttons e&ce%t J2*tton e&hibit this !e&clusive or$ behavior. RFSURFSTIJLT+(6PTE5MLTIMMGU

Icons
/ou can use an Icon inside a J+abel or anything that inherits "ro# Abstract2*tton *including J2*tton, J-heck2o4, J$a'io2*tton, and the di""erent kinds o" J1en*Item,. 4sing Icons with J+abels is Auite straight"orward *you ll see an e&a#%le later,. The "ollowing e&a#%le e&%lores all the additional ways you can use Icons with buttons and their descendants. RFSURFSTIJLT+(6PTE5MLTIMMIU /ou can use any gif "iles you want, but the ones used in this e&a#%le are %art o" this book s code distribution, available at ,,,'0ruceEckel'com. To o%en a "ile and bring in the i#age, si#%ly create an ImageIcon and

877

hand it the "ile na#e. Ero# then on, you can use the resulting Icon in your %rogra#. RFSURFSTIJLT+(6PTE5MLTIMM2U Cote that %ath in"or#ation is hard'coded into this e&a#%le; you will need to change the %ath to corres%ond to the location o" the i#age "iles.

//3 c()3Laces.Hava // $con behavior in Jbuttons. // Pa""let co!e?Laces // :i!th? ,' height?(''QP/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Laces e6ten!s J0""let @ // The follo:ing "ath infor#ation is necessary // to run via an a""let !irectly fro# the !isk3 static %tring "ath ? 8C3/aaa-T$J -!istribution/co!e/c()/8< static $conNO faces ? @ ne: $#age$con-"ath K 8face'.gif8., ne: $#age$con-"ath K 8face(.gif8., ne: $#age$con-"ath K 8face .gif8., ne: $#age$con-"ath K 8face).gif8., ne: $#age$con-"ath K 8faceI.gif8., A< JButton Hb ? ne: JButton-8JButton8, facesN)O., Hb ? ne: JButton-8Disable8.< boolean #a! ? false< "ublic voi! init-. @ Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< Hb.a!!0ctionListener-ne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e.@ if-#a!. @ Hb.set$con-facesN)O.< #a! ? false< A else @ Hb.set$con-facesN'O.<

Cha ter 13! Creating Bindo,s & "

lets

878

#a! ? true< A Hb.setWertical0lign#ent-JButton.TGP.< Hb.setMoriUontal0lign#ent-JButton.LELT.< A A.< Hb.set5olloverEnable!-true.< Hb.set5ollover$con-facesN(O.< Hb.setPresse!$con-facesN O.< Hb.setDisable!$con-facesNIO.< Hb.setToolTi"Te6t-8;o:48.< c".a!!-Hb.< Hb .a!!0ctionListener-ne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e.@ if-Hb.isEnable!-.. @ Hb.setEnable!-false.< Hb .setTe6t-8Enable8.< A else @ Hb.setEnable!-true.< Hb .setTe6t-8Disable8.< A A A.< c".a!!-Hb .< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Laces-., I'', ''.< A A ///3>
6n Icon can be used in #any constructors, but you can also use setIcon A B to add or change an Icon. This e&a#%le also shows how a J2*tton *or any Abstract2*tton, can set the various di""erent sorts o" icons that a%%ear when things ha%%en to that button= when it s %ressed, disabled, or !rolled over$ *the #ouse #oves over it without clicking,. /ou ll see that this gives the button a nice ani#ated "eel. RFSURF STIJLT+(6PTE5MLTIMK@U

87:

#ool ti.s
The %revious e&a#%le added a !tool ti%$ to the button. 6l#ost all o" the classes that you ll be using to create your user inter"aces are derived "ro# J-omponent, which contains a #ethod called setToolTipTe4t A)tringB. So, "or virtually anything you %lace on your "or#, all you need to do is say *"or an ob0ect 8c o" any J-omponent'derived class,=

Hc.setToolTi"Te6t-8Jy ti"8.<
and when the #ouse stays over that J-omponent "or a %redeter#ined %eriod o" ti#e, a tiny bo& containing your te&t will %o% u% ne&t to the #ouse. RFSURFSTIJLT+(6PTE5MLTIMKMU

#e0t fields
This e&a#%le shows the e&tra behavior that JTe4tFiel's are ca%able o"=

//3 c()3Te6tLiel!s.Hava // Te6t fiel!s an! Java events. // Pa""let co!e?Te6tLiel!s :i!th?)*, // height?( ,QP/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava6.s:ing.event.B< i#"ort Hava6.s:ing.te6t.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Te6tLiel!s e6ten!s J0""let @ JButton b( ? ne: JButton-8aet Te6t8., b ? ne: JButton-8%et Te6t8.< JTe6tLiel! t( ? ne: JTe6tLiel!-)'., t ? ne: JTe6tLiel!-)'., t) ? ne: JTe6tLiel!-)'.< %tring s ? ne: %tring-.< Y""erCaseDocu#ent uc! ? ne: Y""erCaseDocu#ent-.< "ublic voi! init-. @

Cha ter 13! Creating Bindo,s & "

lets

87;

t(.setDocu#ent-uc!.< uc!.a!!Docu#entListener-ne: T(-..< b(.a!!0ctionListener-ne: B(-..< b .a!!0ctionListener-ne: B -..< Docu#entListener !l ? ne: T(-.< t(.a!!0ctionListener-ne: T(0-..< Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< c".a!!-b(.< c".a!!-b .< c".a!!-t(.< c".a!!-t .< c".a!!-t).< A class T( i#"le#ents Docu#entListener @ "ublic voi! change!Y"!ate-Docu#entEvent e.@A "ublic voi! insertY"!ate-Docu#entEvent e.@ t .setTe6t-t(.getTe6t-..< t).setTe6t-8Te6t3 8K t(.getTe6t-..< A "ublic voi! re#oveY"!ate-Docu#entEvent e.@ t .setTe6t-t(.getTe6t-..< A A class T(0 i#"le#ents 0ctionListener @ "rivate int count ? '< "ublic voi! actionPerfor#e!-0ctionEvent e. @ t).setTe6t-8t( 0ction Event 8 K countKK.< A A class B( i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ if-t(.get%electe!Te6t-. ?? null. s ? t(.getTe6t-.< else s ? t(.get%electe!Te6t-.< t(.setE!itable-true.< A A class B i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @

88=

uc!.setY""erCase-false.< t(.setTe6t-8$nserte! by Button uc!.setY""erCase-true.< t(.setE!itable-false.<

3 8 K s.<

A A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Te6tLiel!s-., )*,, ( ,.< A A class Y""erCaseDocu#ent e6ten!s PlainDocu#ent @ boolean u""erCase ? true< "ublic voi! setY""erCase-boolean flag. @ u""erCase ? flag< A "ublic voi! insert%tring-int offset, %tring string, 0ttribute%et attribute%et. thro:s Ba!LocationE6ce"tion @ if-u""erCase. string ? string.toY""erCase-.< su"er.insert%tring-offset, string, attribute%et.< A A ///3>
The JTe4tFiel' tJ is included as a %lace to re%ort when the action listener "or the JTe4tFiel' t> is "ired. /ou ll see that the action listener "or a JTe4tFiel' is "ired only when you %ress the !enter$ key. RFSURF STIJLT+(6PTE5MLTIMKKU The JTe4tFiel' t> has several listeners attached to it. The T> listener is a oc*ment+istener that res%onds to any change in the !docu#ent$ *the contents o" the JTe4tFiel', in this case,. It auto#atically co%ies all te&t "ro# t> into tI. In addition, t> s docu#ent is set to a derived class o" #lain oc*ment, called Upper-ase oc*ment, which "orces all characters to u%%ercase. It auto#atically detects backs%aces and %er"or#s the deletion, ad0usting the caret and handling everything as you would e&%ect. RFSURFSTIJLT+(6PTE5MLTIMKLU

Cha ter 13! Creating Bindo,s & "

lets

881

;orders
J-omponent contains a #ethod called set2or'erA B, which allows you
to %lace various interesting borders on any visible co#%onent. The "ollowing e&a#%le de#onstrates a nu#ber o" the di""erent borders that are available, using a #ethod called sho(2or'erA B that creates a J#anel and %uts on the border in each case. 6lso, it uses 5TTI to "ind the na#e o" the border that you re using *stri%%ing o"" all the %ath in"or#ation,, then %uts that na#e in a J+abel in the #iddle o" the %anel=

//3 c()3Bor!ers.Hava // Different %:ing bor!ers. // Pa""let co!e?Bor!ers // :i!th?,'' height?)''QP/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort Hava6.s:ing.bor!er.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Bor!ers e6ten!s J0""let @ static JPanel sho:Bor!er-Bor!er b. @ JPanel H" ? ne: JPanel-.< H".setLayout-ne: Bor!erLayout-..< %tring n# ? b.getClass-..to%tring-.< n# ? n#.substring-n#.last$n!e6Gf-2.2. K (.< H".a!!-ne: JLabel-n#, JLabel.CE&TE5., Bor!erLayout.CE&TE5.< H".setBor!er-b.< return H"< A "ublic voi! init-. @ Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< c".setLayout-ne: ari!Layout- ,I..< c".a!!-sho:Bor!er-ne: Title!Bor!er-8Title8...< c".a!!-sho:Bor!er-ne: Etche!Bor!er-...< c".a!!-sho:Bor!er-ne: LineBor!er-Color.blue...< c".a!!-sho:Bor!erne: JatteBor!er-,,,,)',)',Color.green...< c".a!!-sho:Bor!er-

882

ne: BevelBor!er-BevelBor!er.50$%ED...< c".a!!-sho:Bor!erne: %oftBevelBor!er-BevelBor!er.LG\E5ED...< c".a!!-sho:Bor!er-ne: Co#"oun!Bor!erne: Etche!Bor!er-., ne: LineBor!er-Color.re!....< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Bor!ers-., ,'', )''.< A A ///3>
/ou can also create your own borders and %ut the# inside buttons, labels, etc.9anything derived "ro# J-omponent. RFSURF STIJLT+(6PTE5MLTIMK?U

"1croll anes
Most o" the ti#e you ll 0ust want to let a J)croll#ane do it s 0ob, but you can also control which scroll bars are allowed9vertical, hori1ontal, both, or neither=

//3 c()3J%crollPanes.Hava // Controlling the scrollbars in a J%crollPane. // Pa""let co!e?J%crollPanes :i!th?)'' height?* ,Q // P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort Hava6.s:ing.bor!er.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class JButton b( ? ne: b ? ne: b) ? ne: bI ? ne: JTe6t0rea t( ? ne: t ? ne: J%crollPanes e6ten!s J0""let @ JButton-8Te6t 0rea (8., JButton-8Te6t 0rea 8., JButton-85e"lace Te6t8., JButton-8$nsert Te6t8.< JTe6t0rea-8t(8, (, JTe6t0rea-8t 8, I, '., '.,

Cha ter 13! Creating Bindo,s & "

lets

883

t) ? ne: JTe6t0rea-8t)8, (, '., tI ? ne: JTe6t0rea-8tI8, (', ('., t, ? ne: JTe6t0rea-8t,8, I, '., t+ ? ne: JTe6t0rea-8t+8, (', ('.< J%crollPane s") ? ne: J%crollPane-t), J%crollPane.WE5T$C0Lb%C5GLLB05b&EWE5, J%crollPane.MG5$TG&T0Lb%C5GLLB05b&EWE5., s"I ? ne: J%crollPane-tI, J%crollPane.WE5T$C0Lb%C5GLLB05b0L\0;%, J%crollPane.MG5$TG&T0Lb%C5GLLB05b&EWE5., s", ? ne: J%crollPane-t,, J%crollPane.WE5T$C0Lb%C5GLLB05b&EWE5, J%crollPane.MG5$TG&T0Lb%C5GLLB05b0L\0;%., s"+ ? ne: J%crollPane-t+, J%crollPane.WE5T$C0Lb%C5GLLB05b0L\0;%, J%crollPane.MG5$TG&T0Lb%C5GLLB05b0L\0;%.< class B(L i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ t,.a""en!-t(.getTe6t-. K 8_n8.< A A class B L i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ t .setTe6t-8$nserte! by Button 8.< t .a""en!-83 8 K t(.getTe6t-..< t,.a""en!-t .getTe6t-. K 8_n8.< A A class B)L i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ %tring s ? 8 5e"lace#ent 8< t .re"lace5ange-s, ), ) K s.length-..< A A class BIL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ t .insert-8 $nserte! 8, ('.< A A "ublic voi! init-. @

884

Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< // Create Bor!ers for co#"onents3 Bor!er br! ? Bor!erLactory.createJatteBor!er(, (, (, (, Color.black.< t(.setBor!er-br!.< t .setBor!er-br!.< s").setBor!er-br!.< s"I.setBor!er-br!.< s",.setBor!er-br!.< s"+.setBor!er-br!.< // $nitialiUe listeners an! a!! co#"onents3 b(.a!!0ctionListener-ne: B(L-..< c".a!!-b(.< c".a!!-t(.< b .a!!0ctionListener-ne: B L-..< c".a!!-b .< c".a!!-t .< b).a!!0ctionListener-ne: B)L-..< c".a!!-b).< bI.a!!0ctionListener-ne: BIL-..< c".a!!-bI.< c".a!!-s").< c".a!!-s"I.< c".a!!-s",.< c".a!!-s"+.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: J%crollPanes-., )'', * ,.< A A ///3>
4sing di""erent argu#ents in the J)croll#ane constructor controls the scrollbars that are available. This e&a#%le also dresses things u% a bit using borders. RFSURFSTIJLT+(6PTE5MLTIMKHU

A mini@editor
The JTe4t#ane control %rovides a great deal o" su%%ort "or editing, without #uch e""ort. The "ollowing e&a#%le #akes very si#%le use o" this, ignoring the bulk o" the "unctionality o" the class=

Cha ter 13! Creating Bindo,s & "

lets

885

//3 c()3Te6tPane.Hava // The JTe6tPane control is a little e!itor. // Pa""let co!e?Te6tPane :i!th?I*, height?I ,Q // P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort co#.bruceeckel.s:ing.B< i#"ort co#.bruceeckel.util.B< "ublic class Te6tPane e6ten!s J0""let @ JButton b ? ne: JButton-80!! Te6t8.< JTe6tPane t" ? ne: JTe6tPane-.< static aenerator sg ? ne: 0rrays .5an!%tringaenerator-*.< "ublic voi! init-. @ b.a!!0ctionListener-ne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e.@ for-int i ? (< i P ('< iKK. t".setTe6t-t".getTe6t-. K sg.ne6t-. K 8_n8.< A A.< Container c" ? getContentPane-.< c".a!!-ne: J%crollPane-t"..< c".a!!-Bor!erLayout.%GYTM, b.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Te6tPane-., I*,, I ,.< A A ///3>
The button 0ust adds rando#ly generated te&t. The intent o" the JTe4t#ane is to allow te&t to be edited in %lace, so you will see that there is no appen'A B #ethod. In this case *ad#ittedly, a %oor use o" the ca%abilities o" JTe4t#ane,, the te&t #ust be ca%tured, #odi"ied, and %laced back into the %ane using setTe4tA B. RFSURF STIJLT+(6PTE5MLTIMK3U 6s #entioned be"ore, the de"ault layout behavior o" an a%%let is to use the 2or'er+ayo*t. I" you add so#ething to the %ane without s%eci"ying any

887

details, it 0ust "ills the center o" the %ane out to the edges. (owever, i" you s%eci"y one o" the surrounding regions *C)5T(, S)4T(, E6ST, or :EST, as is done here, the co#%onent will "it itsel" into that region9in this case, the button will nest down at the botto# o" the screen. RFSURF STIJLT+(6PTE5MLTIMKGU Cotice the built'in "eatures o" JTe4t#ane, such as auto#atic line wra%%ing. There are lots o" other "eatures that you can look u% using the J7> docu#entation. RFSURFSTIJLT+(6PTE5MLTIMKIU

Check bo0es
6 check bo& %rovides a way to #ake a single onFo"" choice; it consists o" a tiny bo& and a label. The bo& ty%ically holds a little !&$ *or so#e other indication that it is set, or is e#%ty, de%ending on whether that ite# was selected. RFSURFSTIJLT+(6PTE5MLTIMK2U /ou ll nor#ally create a J-heck2o4 using a constructor that takes the label as an argu#ent. /ou can get and set the state, and also get and set the label i" you want to read or change it a"ter the J-heck2o4 has been created. RFSURFSTIJLT+(6PTE5MLTIML@U :henever a J-heck2o4 is set or cleared, an event occurs, which you can ca%ture the sa#e way you do a button, by using an Action+istener. The "ollowing e&a#%le uses a JTe4tArea to enu#erate all the check bo&es that have been checked=

//3 c()3CheckBo6es.Hava // Ysing JCheckBo6es. // Pa""let co!e?CheckBo6es :i!th? '' height? ''Q // P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.event.B< i#"ort Hava.a:t.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class CheckBo6es e6ten!s J0""let @ JTe6t0rea t ? ne: JTe6t0rea-+, (,.< JCheckBo6 cb( ? ne: JCheckBo6-8Check Bo6 (8.,

Cha ter 13! Creating Bindo,s & "

lets

888

cb ? ne: JCheckBo6-8Check Bo6 8., cb) ? ne: JCheckBo6-8Check Bo6 )8.< "ublic voi! init-. @ cb(.a!!0ctionListener-ne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e.@ trace-8(8, cb(.< A A.< cb .a!!0ctionListener-ne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e.@ trace-8 8, cb .< A A.< cb).a!!0ctionListener-ne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e.@ trace-8)8, cb).< A A.< Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< c".a!!-ne: J%crollPane-t..< c".a!!-cb(.< c".a!!-cb .< c".a!!-cb).< A voi! trace-%tring b, JCheckBo6 cb. @ if-cb.is%electe!-.. t.a""en!-8Bo6 8 K b K 8 %et_n8.< else t.a""en!-8Bo6 8 K b K 8 Cleare!_n8.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: CheckBo6es-., '', ''.< A A ///3>
The traceA B #ethod sends the na#e o" the selected J-heck2o4 and its current state to the JTe4tArea using appen'A B, so you ll see a cu#ulative list o" the checkbo&es that were selected and what their state is. RFSURFSTIJLT+(6PTE5MLTIMLMU

88:

$adio buttons
The conce%t o" a radio button in 84I %rogra##ing co#es "ro# %re' electronic car radios with #echanical buttons= when you %ush one in, any other button that was %ressed %o%s out. Thus, it allows you to "orce a single choice a#ong #any. RFSURFSTIJLT+(6PTE5MLTIMLKU 6ll you need to do to set u% an associated grou% o" J$a'io2*ttons is to add the# to a 2*tton"ro*p *you can have any nu#ber o" 2*tton"ro*ps on a "or#,. )ne o" the buttons can o%tionally have its starting state set to tr*e *using the second argu#ent in the constructor,. I" you try to set #ore than one radio button to tr*e then only the "inal one set will be tr*e. RFSURFSTIJLT+(6PTE5MLTIMLLU (ere s a si#%le e&a#%le o" the use o" radio buttons. Cote that you ca%ture radio button events like all others=

//3 c()35a!ioButtons.Hava // Ysing J5a!ioButtons. // Pa""let co!e?5a!ioButtons // :i!th? '' height?(''Q P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.event.B< i#"ort Hava.a:t.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class 5a!ioButtons e6ten!s J0""let @ JTe6tLiel! t ? ne: JTe6tLiel!-(,.< Buttonarou" g ? ne: Buttonarou"-.< J5a!ioButton rb( ? ne: J5a!ioButton-8one8, false., rb ? ne: J5a!ioButton-8t:o8, false., rb) ? ne: J5a!ioButton-8three8, false.< 0ctionListener al ? ne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ t.setTe6t-85a!io button 8 K --J5a!ioButton.e.get%ource-...getTe6t-..< A A< "ublic voi! init-. @ rb(.a!!0ctionListener-al.<

Cha ter 13! Creating Bindo,s & "

lets

88;

rb .a!!0ctionListener-al.< rb).a!!0ctionListener-al.< g.a!!-rb(.< g.a!!-rb .< g.a!!-rb).< t.setE!itable-false.< Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< c".a!!-t.< c".a!!-rb(.< c".a!!-rb .< c".a!!-rb).< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: 5a!ioButtons-., '', (''.< A A ///3>
To dis%lay the state, a te&t "ield is used. This "ield is set to noneditable because it s used only to dis%lay data, not to collect it. Thus it is an alternative to using a J+abel. RFSURFSTIJLT+(6PTE5MLTIML?U

Combo bo0es 8dro.@down lists9


Dike a grou% o" radio buttons, a dro%'down list is a way to "orce the user to select only one ele#ent "ro# a grou% o" %ossibilities. (owever, it s a #ore co#%act way to acco#%lish this, and it s easier to change the ele#ents o" the list without sur%rising the user. */ou can change radio buttons dyna#ically, but that tends to be visibly 0arring,. RFSURF STIJLT+(6PTE5MLTIMLHU Java s J-ombo2o4 bo& is not like the co#bo bo& in :indows, which lets you select "ro# a list or ty%e in your own selection. :ith a J-ombo2o4 bo& you choose one and only one ele#ent "ro# the list. In the "ollowing e&a#%le, the J-ombo2o4 bo& starts with a certain nu#ber o" entries and then new entries are added to the bo& when a button is %ressed. RFSURFSTIJLT+(6PTE5MLTIML3U

//3 c()3Co#boBo6es.Hava // Ysing !ro"-!o:n lists. // Pa""let co!e?Co#boBo6es // :i!th? '' height?(''Q P/a""letQ i#"ort Hava6.s:ing.B<

8:=

i#"ort Hava.a:t.event.B< i#"ort Hava.a:t.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Co#boBo6es e6ten!s J0""let @ %tringNO !escri"tion ? @ 8Ebullient8, 8Gbtuse8, 85ecalcitrant8, 8Brilliant8, 8%o#nescent8, 8Ti#orous8, 8Llori!8, 8Putrescent8 A< JTe6tLiel! t ? ne: JTe6tLiel!-(,.< JCo#boBo6 c ? ne: JCo#boBo6-.< JButton b ? ne: JButton-80!! ite#s8.< int count ? '< "ublic voi! init-. @ for-int i ? '< i P I< iKK. c.a!!$te#-!escri"tionNcountKKO.< t.setE!itable-false.< b.a!!0ctionListener-ne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e.@ if-count P !escri"tion.length. c.a!!$te#-!escri"tionNcountKKO.< A A.< c.a!!0ctionListener-ne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e.@ t.setTe6t-8in!e63 8K c.get%electe!$n!e6-. K 8 8 K --JCo#boBo6.e.get%ource-.. .get%electe!$te#-..< A A.< Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< c".a!!-t.< c".a!!-c.< c".a!!-b.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Co#boBo6es-., '', (''.< A A ///3>

Cha ter 13! Creating Bindo,s & "

lets

8:1

The JTe4tFiel' dis%lays the !selected inde&,$ which is the seAuence nu#ber o" the currently selected ele#ent, as well as the label on the radio button. RFSURFSTIJLT+(6PTE5MLTIMLGU

&ist bo0es
Dist bo&es are signi"icantly di""erent "ro# J-ombo2o4 bo&es, and not 0ust in a%%earance. :hile a J-ombo2o4 bo& dro%s down when you activate it, a J+ist occu%ies so#e "i&ed nu#ber o" lines on a screen all the ti#e and doesn t change. I" you want to see the ite#s in a list, you si#%ly call get)electe'Val*esA B, which %roduces an array o" )tring o" the ite#s that have been selected. RFSURFSTIJLT+(6PTE5MLTIMLIU 6 J+ist allows #ulti%le selection= i" you control'click on #ore than one ite# *holding down the !control$ key while %er"or#ing additional #ouse clicks, the original ite# stays highlighted and you can select as #any as you want. I" you select an ite#, then shi"t'click on another ite#, all the ite#s in the s%an between the two are selected. To re#ove an ite# "ro# a grou% you can control'click it. RFSURFSTIJLT+(6PTE5MLTIML2U

//3 c()3List.Hava // Pa""let co!e?List :i!th? ,' // height?)*,Q P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava6.s:ing.event.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort Hava6.s:ing.bor!er.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class List e6ten!s J0""let @ %tringNO flavors ? @ 8Chocolate8, 8%tra:berry8, 8Wanilla Lu!ge %:irl8, 8Jint Chi"8, 8Jocha 0l#on! Lu!ge8, 85u# 5aisin8, 8Praline Crea#8, 8Ju! Pie8 A< DefaultListJo!el l$te#s?ne: DefaultListJo!el-.< JList lst ? ne: JList-l$te#s.< JTe6t0rea t ? ne: JTe6t0rea-flavors.length, '.< JButton b ? ne: JButton-80!! $te#8.< 0ctionListener bl ? ne: 0ctionListener-. @

8:2

"ublic voi! actionPerfor#e!-0ctionEvent e. @ if-count P flavors.length. @ l$te#s.a!!-', flavorsNcountKKO.< A else @ // Disable, since there are no #ore // flavors left to be a!!e! to the List b.setEnable!-false.< A A A< List%electionListener ll ? ne: List%electionListener-. @ "ublic voi! valueChange!List%electionEvent e. @ t.setTe6t-88.< GbHectNO ite#s?lst.get%electe!Walues-.< for-int i ? '< i P ite#s.length< iKK. t.a""en!-ite#sNiO K 8_n8.< A A< int count ? '< "ublic voi! init-. @ Container c" ? getContentPane-.< t.setE!itable-false.< c".setLayout-ne: Llo:Layout-..< // Create Bor!ers for co#"onents3 Bor!er br! ? Bor!erLactory.createJatteBor!er(, (, , , Color.black.< lst.setBor!er-br!.< t.setBor!er-br!.< // 0!! the first four ite#s to the List for-int i ? '< i P I< iKK. l$te#s.a!!Ele#ent-flavorsNcountKKO.< // 0!! ite#s to the Content Pane for Dis"lay c".a!!-t.< c".a!!-lst.< c".a!!-b.< // 5egister event listeners lst.a!!List%electionListener-ll.< b.a!!0ctionListener-bl.< A

Cha ter 13! Creating Bindo,s & "

lets

8:3

"ublic static voi! #ain-%tringNO args. @ Console.run-ne: List-., ,', )*,.< A A ///3>
:hen you %ress the button it adds ite#s to the to o" the list *because a''ItemA B s second argu#ent is @,. RFSURF STIJLT+(6PTE5MLTIM?@U /ou can see that borders have also been added to the lists. RFSURF STIJLT+(6PTE5MLTIM?MU I" you 0ust want to %ut an array o" )trings into a J+ist, there s a #uch si#%ler solution= you %ass the array to the J+ist constructor, and it builds the list auto#atically. The only reason "or using the !list #odel$ in the above e&a#%le is so that the list could be #ani%ulated during the e&ecution o" the %rogra#. RFSURFSTIJLT+(6PTE5MLTIM?KU

J+ists do not auto#atically %rovide direct su%%ort "or scrolling. )" course, all you need to do is wra% the J+ist in a J)croll#ane and all the
details are auto#atically #anaged "or you. RFSURF STIJLT+(6PTE5MLTIM?LU

#abbed .anes
The JTabbe'#ane allows you to create a !tabbed dialog,$ which has "ile' "older tabs running across one edge, and all you have to do is %ress a tab to bring "orward a di""erent dialog.

//3 c()3Tabbe!Pane(.Hava // De#onstrates the Tabbe! Pane. // Pa""let co!e?Tabbe!Pane( // :i!th?),' height? ''Q P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava6.s:ing.event.B< i#"ort Hava.a:t.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Tabbe!Pane( e6ten!s J0""let @ %tringNO flavors ? @ 8Chocolate8, 8%tra:berry8, 8Wanilla Lu!ge %:irl8, 8Jint Chi"8,

8:4

8Jocha 0l#on! Lu!ge8, 85u# 5aisin8, 8Praline Crea#8, 8Ju! Pie8 A< JTabbe!Pane tabs ? ne: JTabbe!Pane-.< JTe6tLiel! t6t ? ne: JTe6tLiel!- '.< "ublic voi! init-. @ for-int i ? '< i P flavors.length< iKK. tabs.a!!Tab-flavorsNiO, ne: JButton-8Tabbe! "ane 8 K i..< tabs.a!!ChangeListener-ne: ChangeListener-.@ "ublic voi! stateChange!-ChangeEvent e. @ t6t.setTe6t-8Tab selecte!3 8 K tabs.get%electe!$n!e6-..< A A.< Container c" ? getContentPane-.< c".a!!-Bor!erLayout.%GYTM, t6t.< c".a!!-tabs.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Tabbe!Pane(-., ),', ''.< A A ///3>
In Java, the use o" so#e sort o" !tabbed %anel$ #echanis# is Auite i#%ortant because in a%%let %rogra##ing the use o" %o%'u% dialogs is discouraged by auto#atically adding a little warning to any dialog that %o%s u% out o" an a%%let. RFSURFSTIJLT+(6PTE5MLTIM??U :hen you run the %rogra# you ll see that the JTabbe'#ane auto#atically stacks the tabs i" there are too #any o" the# to "it on one row. /ou can see this by resi1ing the window when you run the %rogra# "ro# the console co##and line. RFSURFSTIJLT+(6PTE5MLTIM?HU

Message bo0es
:indowing environ#ents co##only contain a standard set o" #essage bo&es that allow you to Auickly %ost in"or#ation to the user or to ca%ture in"or#ation "ro# the user. In Swing, these #essage bo&es are contained in J.ption#ane. /ou have #any di""erent %ossibilities *so#e Auite so%histicated,, but the ones you ll #ost co##only use are %robably the

Cha ter 13! Creating Bindo,s & "

lets

8:5

#essage dialog and con"ir#ation dialog, invoked using the static J.ption#ane!sho(1essage ialogA B and J.ption#ane! sho(-onfirm ialogA B. The "ollowing e&a#%le shows a subset o" the #essage bo&es available with J.ption#ane=

//3 c()3JessageBo6es.Hava // De#onstrates Jo"tionPane. // Pa""let co!e?JessageBo6es // :i!th? '' height?(,'Q P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.event.B< i#"ort Hava.a:t.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class JessageBo6es e6ten!s J0""let @ JButtonNO b ? @ ne: JButton-80lert8., ne: JButton-8;es/&o8., ne: JButton-8Color8., ne: JButton-8$n"ut8., ne: JButton-8) Wals8. A< JTe6tLiel! t6t ? ne: JTe6tLiel!-(,.< 0ctionListener al ? ne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e.@ %tring i! ? --JButton.e.get%ource-...getTe6t-.< if-i!.e=uals-80lert8.. JG"tionPane.sho:JessageDialog-null, 8There2s a bug on you48, 8Mey48, JG"tionPane.E55G5bJE%%0aE.< else if-i!.e=uals-8;es/&o8.. JG"tionPane.sho:Confir#Dialog-null, 8or no8, 8choose yes8, JG"tionPane.;E%b&GbGPT$G&.< else if-i!.e=uals-8Color8.. @ GbHectNO o"tions ? @ 85e!8, 8areen8 A< int sel ? JG"tionPane.sho:G"tionDialognull, 8Choose a Color48, 8\arning8, JG"tionPane.DEL0YLTbGPT$G&, JG"tionPane.\05&$&abJE%%0aE, null, o"tions, o"tionsN'O.< if-sel 4? JG"tionPane.CLG%EDbGPT$G&. t6t.setTe6t-

8:7

8Color %electe!3 8 K o"tionsNselO.< A else if-i!.e=uals-8$n"ut8.. @ %tring val ? JG"tionPane.sho:$n"utDialog8Mo: #any fingers !o you see[8.< t6t.setTe6t-val.< A else if-i!.e=uals-8) Wals8.. @ GbHectNO selections ? @ 8Lirst8, 8%econ!8, 8Thir!8 A< GbHect val ? JG"tionPane.sho:$n"utDialognull, 8Choose one8, 8$n"ut8, JG"tionPane.$&LG5J0T$G&bJE%%0aE, null, selections, selectionsN'O.< if-val 4? null. t6t.setTe6tval.to%tring-..< A A A< "ublic voi! init-. @ Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< for-int i ? '< i P b.length< iKK. @ bNiO.a!!0ctionListener-al.< c".a!!-bNiO.< A c".a!!-t6t.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: JessageBo6es-., '', ''.< A A ///3>
To be able to write a single Action+istener, I ve used the so#ewhat risky a%%roach o" checking the )tring labels on the buttons. The %roble# with this is that it s easy to get the label a little bit wrong, ty%ically in ca%itali1ation, and this bug can be hard to s%ot. RFSURF STIJLT+(6PTE5MLTIM?3U Cote that sho(.ption ialogA B and sho(Inp*t ialogA B %rovide return ob0ects that contain the value entered by the user. RFSURF STIJLT+(6PTE5MLTIM?GU

Cha ter 13! Creating Bindo,s & "

lets

8:8

Menus
Each co#%onent ca%able o" holding a #enu, including JApplet, JFrame, J ialog, and their descendants, has a setJ1en*2arA B #ethod that acce%ts a J1en*2ar *you can have only one J1en*2ar on a %articular co#%onent,. /ou add J1en*s to the J1en*2ar, and J1en*Items to the J1en*s. Each J1en*Item can have an Action+istener attached to it, to be "ired when that #enu ite# is selected. RFSURFSTIJLT+(6PTE5MLTIM?IU

4nlike a syste# that uses resources, with Java and Swing you #ust hand asse#ble all the #enus in source code. (ere is a very si#%le #enu e&a#%le= //3 c()3%i#"leJenus.Hava // Pa""let co!e?%i#"leJenus // :i!th? '' height?*,Q P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.event.B< i#"ort Hava.a:t.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class %i#"leJenus e6ten!s J0""let @ JTe6tLiel! t ? ne: JTe6tLiel!-(,.< 0ctionListener al ? ne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e.@ t.setTe6t--JJenu$te#.e.get%ource-...getTe6t-..< A A< JJenuNO #enus ? @ ne: JJenu-8\inken8., ne: JJenu-8Blinken8., ne: JJenu-8&o!8. A< JJenu$te#NO ite#s ? @ ne: JJenu$te#-8Lee8., ne: JJenu$te#-8Li8., ne: JJenu$te#-8Lo8., ne: JJenu$te#-8Ti"8., ne: JJenu$te#-8Ta"8., ne: JJenu$te#-8Tot8., ne: JJenu$te#-8Glly8., ne: JJenu$te#-8G6en8., ne: JJenu$te#-8Lree8. A< "ublic voi! init-. @ for-int i ? '< i P ite#s.length< iKK. @ ite#sNiO.a!!0ctionListener-al.<

8::

#enusNiV)O.a!!-ite#sNiO.< A JJenuBar #b ? ne: JJenuBar-.< for-int i ? '< i P #enus.length< iKK. #b.a!!-#enusNiO.< setJJenuBar-#b.< Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< c".a!!-t.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: %i#"leJenus-., '', *,.< A A ///3>
The use o" the #odulus o%erator in ! iSJ$ distributes the #enu ite#s a#ong the three J1en*s. Each J1en*Item #ust have an Action+istener attached to it; here, the sa#e Action+istener is used everywhere but you ll usually need an individual one "or each J1en*Item. RFSURFSTIJLT+(6PTE5MLTIM?2U

J1en*Item inherits Abstract2*tton, so it has so#e buttonlike behaviors. By itsel", it %rovides an ite# that can be %laced on a dro%'down #enu. There are also three ty%es inherited "ro# J1en*Item= J1en* to hold other J1en*Items *so you can have cascading #enus,, J-heck2o41en*Item, which %roduces a check#ark to indicate whether that #enu ite# is selected, and J$a'io2*tton1en*Item, which contains a radio button. RFSURFSTIJLT+(6PTE5MLTIMH@U
6s a #ore so%histicated e&a#%le, here are the ice crea# "lavors again, used to create #enus. This e&a#%le also shows cascading #enus, keyboard #ne#onics, J-heck2o41en*Items, and the way you can dyna#ically change #enus=

//3 c()3Jenus.Hava // %ub#enus, checkbo6 #enu ite#s, s:a""ing #enus, // #ne#onics -shortcuts. an! action co##an!s. // Pa""let co!e?Jenus :i!th?)'' // height?(''Q P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B<

Cha ter 13! Creating Bindo,s & "

lets

8:;

i#"ort Hava.a:t.event.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Jenus e6ten!s J0""let @ %tringNO flavors ? @ 8Chocolate8, 8%tra:berry8, 8Wanilla Lu!ge %:irl8, 8Jint Chi"8, 8Jocha 0l#on! Lu!ge8, 85u# 5aisin8, 8Praline Crea#8, 8Ju! Pie8 A< JTe6tLiel! t ? ne: JTe6tLiel!-8&o flavor8, )'.< JJenuBar #b( ? ne: JJenuBar-.< JJenu f ? ne: JJenu-8Lile8., # ? ne: JJenu-8Llavors8., s ? ne: JJenu-8%afety8.< // 0lternative a""roach3 JCheckBo6Jenu$te#NO safety ? @ ne: JCheckBo6Jenu$te#-8auar!8., ne: JCheckBo6Jenu$te#-8Mi!e8. A< JJenu$te#NO file ? @ ne: JJenu$te#-8G"en8., A< // 0 secon! #enu bar to s:a" to3 JJenuBar #b ? ne: JJenuBar-.< JJenu fooBar ? ne: JJenu-8fooBar8.< JJenu$te#NO other ? @ // 0!!ing a #enu shortcut -#ne#onic. is very // si#"le, but only JJenu$te#s can have the# // in their constructors3 ne: JJenu$te#-8Loo8, `eyEvent.W`bL., ne: JJenu$te#-8Bar8, `eyEvent.W`b0., // &o shortcut3 ne: JJenu$te#-8BaU8., A< JButton b ? ne: JButton-8%:a" Jenus8.< class BL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ JJenuBar # ? getJJenuBar-.< setJJenuBar-# ?? #b( [ #b 3 #b(.< vali!ate-.< // 5efresh the fra#e A

8;=

A class JL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ JJenu$te# target ? -JJenu$te#.e.get%ource-.< %tring actionCo##an! ? target.get0ctionCo##an!-.< if-actionCo##an!.e=uals-8G"en8.. @ %tring s ? t.getTe6t-.< boolean chosen ? false< for-int i ? '< i P flavors.length< iKK. if-s.e=uals-flavorsNiO.. chosen ? true< if-4chosen. t.setTe6t-8Choose a flavor first48.< else t.setTe6t-8G"ening 8K s K8. J##, ##48.< A A A class LL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ JJenu$te# target ? -JJenu$te#.e.get%ource-.< t.setTe6t-target.getTe6t-..< A A // 0lternatively, you can create a !ifferent // class for each !ifferent Jenu$te#. Then you // Don2t have to figure out :hich one it is3 class LooL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ t.setTe6t-8Loo selecte!8.< A A class BarL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ t.setTe6t-8Bar selecte!8.< A A class BaUL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ t.setTe6t-8BaU selecte!8.< A

Cha ter 13! Creating Bindo,s & "

lets

8;1

A class CJ$L i#"le#ents $te#Listener @ "ublic voi! ite#%tateChange!-$te#Event e. @ JCheckBo6Jenu$te# target ? -JCheckBo6Jenu$te#.e.get%ource-.< %tring actionCo##an! ? target.get0ctionCo##an!-.< if-actionCo##an!.e=uals-8auar!8.. t.setTe6t-8auar! the $ce Crea#4 8 K 8auar!ing is 8 K target.get%tate-..< else if-actionCo##an!.e=uals-8Mi!e8.. t.setTe6t-8Mi!e the $ce Crea#4 8 K 8$s it col![ 8 K target.get%tate-..< A A "ublic voi! init-. @ JL #l ? ne: JL-.< CJ$L c#il ? ne: CJ$L-.< safetyN'O.set0ctionCo##an!-8auar!8.< safetyN'O.setJne#onic-`eyEvent.W`ba.< safetyN'O.a!!$te#Listener-c#il.< safetyN(O.set0ctionCo##an!-8Mi!e8.< safetyN'(O.setJne#onic-`eyEvent.W`bM.< safetyN(O.a!!$te#Listener-c#il.< otherN'O.a!!0ctionListener-ne: LooL-..< otherN(O.a!!0ctionListener-ne: BarL-..< otherN O.a!!0ctionListener-ne: BaUL-..< LL fl ? ne: LL-.< for-int i ? '< i P flavors.length< iKK. @ JJenu$te# #i ? ne: JJenu$te#-flavorsNiO.< #i.a!!0ctionListener-fl.< #.a!!-#i.< // 0!! se"arators at intervals3 if--iK(. V ) ?? '. #.a!!%e"arator-.< A for-int i ? '< i P safety.length< iKK. s.a!!-safetyNiO.< s.setJne#onic-`eyEvent.W`b0.< f.a!!-s.< f.setJne#onic-`eyEvent.W`bL.<

8;2

for-int i ? '< i P file.length< iKK. @ fileNiO.a!!0ctionListener-fl.< f.a!!-fileNiO.< A #b(.a!!-f.< #b(.a!!-#.< setJJenuBar-#b(.< t.setE!itable-false.< Container c" ? getContentPane-.< c".a!!-t, Bor!erLayout.CE&TE5.< // %et u" the syste# for s:a""ing #enus3 b.a!!0ctionListener-ne: BL-..< b.setJne#onic-`eyEvent.W`b%.< c".a!!-b, Bor!erLayout.&G5TM.< for-int i ? '< i P other.length< iKK. fooBar.a!!-otherNiO.< fooBar.setJne#onic-`eyEvent.W`bB.< #b .a!!-fooBar.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Jenus-., )'', (''.< A A ///3>
In this %rogra# I %laced the #enu ite#s into arrays and then ste%%ed through each array calling a''A B "or each J1en*Item. This #akes adding or subtracting a #enu ite# so#ewhat less tedious. RFSURF STIJLT+(6PTE5MLTIMHMU This %rogra# creates not one but two J1en*2ars to de#onstrate that #enu bars can be actively swa%%ed while the %rogra# is running. /ou can see how a J1en*2ar is #ade u% o" J1en*s, and each J1en* is #ade u% o" J1en*Items, J-heck2o41en*Items, or even other J1en*s *which %roduce sub#enus,. :hen a J1en*2ar is asse#bled it can be installed into the current %rogra# with the setJ1en*2arA B #ethod. Cote that when the button is %ressed, it checks to see which #enu is currently installed by calling getJ1en*2arA B, then it %uts the other #enu bar in its %lace. RFSURFSTIJLT+(6PTE5MLTIMHKU :hen testing "or !)%en,$ notice that s%elling and ca%itali1ation are critical, but Java signals no error i" there is no #atch with !)%en.$ This

Cha ter 13! Creating Bindo,s & "

lets

8;3

kind o" string co#%arison is a source o" %rogra##ing errors. RFSURF STIJLT+(6PTE5MLTIMHLU The checking and unchecking o" the #enu ite#s is taken care o" auto#atically. The code handling the J-heck2o41en*Items shows two di""erent ways to deter#ine what was checked= string #atching *which, as #entioned above, isn t a very sa"e a%%roach although you ll see it used, and #atching on the event target ob0ect. 6s shown, the get)tate A B #ethod can be used to reveal the state. /ou can also change the state o" a J-heck2o41en*Item with set)tateA B. RFSURF STIJLT+(6PTE5MLTIMH?U The events "or #enus are a bit inconsistent and can lead to con"usion= J1en*Items use Action+isteners, but J-heckbo41en*Items use Item+isteners. The J1en* ob0ects can also su%%ort Action+isteners, but that s not usually hel%"ul. In general, you ll attach listeners to each J1en*Item, J-heck2o41en*Item, or J$a'io2*tton1en*Item, but the e&a#%le shows Item+isteners and Action+isteners attached to the various #enu co#%onents. RFSURF STIJLT+(6PTE5MLTIMHHU Swing su%%orts #ne#onics, or !keyboard shortcuts,$ so you can select anything derived "ro# Abstract2*tton *button, #enu ite#, etc., using the keyboard instead o" the #ouse. These are Auite si#%le= "or J1en*Item you can use the overloaded constructor that takes as a second argu#ent the identi"ier "or the key. (owever, #ost Abstract2*ttons do not have constructors like this so the #ore general way to solve the %roble# is to use the set1nemonicA B #ethod. The e&a#%le above adds #ne#onics to the button and so#e o" the #enu ite#s; shortcut indicators auto#atically a%%ear on the co#%onents. RF SURFSTIJLT+(6PTE5MLTIMH3U /ou can also see the use o" setAction-omman'A B. This see#s a bit strange because in each case the !action co##and$ is e&actly the sa#e as the label on the #enu co#%onent. :hy not 0ust use the label instead o" this alternative stringO The %roble# is internationali1ation. I" you retarget this %rogra# to another language, you want to change only the label in the #enu, and not change the code *which would no doubt introduce new errors,. So to #ake this easy "or code that checks the te&t

8;4

string associated with a #enu co#%onent, the !action co##and$ can be i##utable while the #enu label can change. 6ll the code works with the !action co##and,$ so it s una""ected by changes to the #enu labels. Cote that in this %rogra#, not all the #enu co#%onents are e&a#ined "or their action co##ands, so those that aren t don t have their action co##and set. RFSURFSTIJLT+(6PTE5MLTIMHGU The bulk o" the work ha%%ens in the listeners. 2+ %er"or#s the J1en*2ar swa%%ing. In 1+, the !"igure out who rang$ a%%roach is taken by getting the source o" the Action&vent and casting it to a J1en*Item, then getting the action co##and string to %ass it through a cascaded if state#ent. RFSURFSTIJLT+(6PTE5MLTIMHIU The F+ listener is si#%le even though it s handling all the di""erent "lavors in the "lavor #enu. This a%%roach is use"ul i" you have enough si#%licity in your logic, but in general, you ll want to take the a%%roach used with Foo+, 2ar+, and 2a7+, in which they are each attached to only a single #enu co#%onent so no e&tra detection logic is necessary and you know e&actly who called the listener. Even with the %ro"usion o" classes generated this way, the code inside tends to be s#aller and the %rocess is #ore "ool%roo". RFSURFSTIJLT+(6PTE5MLTIMH2U /ou can see that #enu code Auickly gets long'winded and #essy. This is another case where the use o" a 84I builder is the a%%ro%riate solution. 6 good tool will also handle the #aintenance o" the #enus. RFSURF STIJLT+(6PTE5MLTIM3@U

o.@u. menus
The #ost straight"orward way to i#%le#ent a J#op*p1en* is to create an inner class that e&tends 1o*seA'apter, then add an ob0ect o" that inner class to each co#%onent that you want to %roduce %o%'u% behavior=

//3 c()3Po"u".Hava // Creating "o"u" #enus :ith %:ing. // Pa""let co!e?Po"u" // :i!th?)'' height? ''QP/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B<

Cha ter 13! Creating Bindo,s & "

lets

8;5

i#"ort co#.bruceeckel.s:ing.B< "ublic class Po"u" e6ten!s J0""let @ JPo"u"Jenu "o"u" ? ne: JPo"u"Jenu-.< JTe6tLiel! t ? ne: JTe6tLiel!-('.< "ublic voi! init-. @ Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< c".a!!-t.< 0ctionListener al ? ne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e.@ t.setTe6t--JJenu$te#.e.get%ource-...getTe6t-..< A A< JJenu$te# # ? ne: JJenu$te#-8Mither8.< #.a!!0ctionListener-al.< "o"u".a!!-#.< # ? ne: JJenu$te#-8;on8.< #.a!!0ctionListener-al.< "o"u".a!!-#.< # ? ne: JJenu$te#-80far8.< #.a!!0ctionListener-al.< "o"u".a!!-#.< "o"u".a!!%e"arator-.< # ? ne: JJenu$te#-8%tay Mere8.< #.a!!0ctionListener-al.< "o"u".a!!-#.< Po"u"Listener "l ? ne: Po"u"Listener-.< a!!JouseListener-"l.< t.a!!JouseListener-"l.< A class Po"u"Listener e6ten!s Jouse0!a"ter @ "ublic voi! #ousePresse!-JouseEvent e. @ #aybe%ho:Po"u"-e.< A "ublic voi! #ouse5elease!-JouseEvent e. @ #aybe%ho:Po"u"-e.< A "rivate voi! #aybe%ho:Po"u"-JouseEvent e. @ if-e.isPo"u"Trigger-.. @

8;7

"o"u".sho:e.getCo#"onent-., e.get9-., e.get;-..< A A A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Po"u"-., )'', ''.< A A ///3>
The sa#e Action+istener is added to each J1en*Item, so that it "etches the te&t "ro# the #enu label and inserts it into the JTe4tFiel'. RFSURFSTIJLT+(6PTE5MLTIM3MU

Drawing
In a good 84I "ra#ework, drawing should be reasonably easy9and it is, in the Swing library. The %roble# with any drawing e&a#%le is that the calculations that deter#ine where things go are ty%ically a lot #ore co#%licated that the calls to the drawing routines, and these calculations are o"ten #i&ed together with the drawing calls so it can see# that the inter"ace is #ore co#%licated than it actually is. RFSURF STIJLT+(6PTE5MLTIM3KU Eor si#%licity, consider the %roble# o" re%resenting data on the screen9 here, the data will be %rovided by the built'in 1ath!sinA B #ethod which is a #athe#atical sine "unction. To #ake things a little #ore interesting, and to "urther de#onstrate how easy it is to use Swing co#%onents, a slider will be %laced at the botto# o" the "or# to dyna#ically control the nu#ber o" sine wave cycles that are dis%layed. In addition, i" you resi1e the window, you ll see that the sine wave re"its itsel" to the new window si1e. RFSURFSTIJLT+(6PTE5MLTIM3LU 6lthough any J-omponent #ay be %ainted and thus used as a canvas, i" you 0ust want a straight"orward drawing sur"ace you will ty%ically inherit "ro# a J#anel. The only #ethod you need to override is paint-omponentA B, which is called whenever that co#%onent #ust be re%ainted *you nor#ally don t need to worry about this, as the decision is #anaged by Swing,. :hen it is called, Swing %asses a "raphics ob0ect to

Cha ter 13! Creating Bindo,s & "

lets

8;8

the #ethod, and you can then use this ob0ect to draw or %aint on the sur"ace. RFSURFSTIJLT+(6PTE5MLTIM3?U In the "ollowing e&a#%le, all the intelligence concerning %ainting is in the

)ine ra( class; the )ine0ave class si#%ly con"igures the %rogra# and the slider control. Inside )ine ra(, the set-yclesA B #ethod
%rovides a hook to allow another ob0ect9the slider control, in this case9 to control the nu#ber o" cycles.

//3 c()3%ine\ave.Hava // Dra:ing :ith %:ing, using a J%li!er. // Pa""let co!e?%ine\ave // :i!th?*'' height?I''QP/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava6.s:ing.event.B< i#"ort Hava.a:t.B< i#"ort co#.bruceeckel.s:ing.B< class %ineDra: e6ten!s JPanel @ static final int %C0LEL0CTG5 ? ''< int cycles< int "oints< !oubleNO sines< intNO "ts< %ineDra:-. @ setCycles-,.< A "ublic voi! setCycles-int ne:Cycles. @ cycles ? ne:Cycles< "oints ? %C0LEL0CTG5 B cycles B < sines ? ne: !oubleN"ointsO< "ts ? ne: intN"ointsO< for-int i ? '< i P "oints< iKK. @ !ouble ra!ians ? -Jath.P$/%C0LEL0CTG5. B i< sinesNiO ? Jath.sin-ra!ians.< A re"aint-.< A "ublic voi! "aintCo#"onent-ara"hics g. @ su"er."aintCo#"onent-g.< int #a6\i!th ? get\i!th-.< !ouble hste" ? -!ouble.#a6\i!th/-!ouble."oints< int #a6Meight ? getMeight-.<

8;:

"ts ? ne: intN"ointsO< for-int i ? '< i P "oints< iKK. "tsNiO ? -int.-sinesNiO B #a6Meight/ K #a6Meight/ .< g.setColor-Color.re!.< for-int i ? (< i P "oints< iKK. @ int 6( ? -int.--i - (. B hste".< int 6 ? -int.-i B hste".< int y( ? "tsNi-(O< int y ? "tsNiO< g.!ra:Line-6(, y(, 6 , y .< A A A

B .C,

"ublic class %ine\ave e6ten!s J0""let @ %ineDra: sines ? ne: %ineDra:-.< J%li!er cycles a!HustCycles ? ne: J%li!er-(, )', ,.< "ublic voi! init-. @ Container c" ? getContentPane-.< c".a!!-sines.< a!HustCyclescycles.a!!ChangeListenerne: ChangeListener-.@ "ublic voi! stateChange!-ChangeEvent e. @ sines.setCycles--J%li!er.e.get%ource-...getWalue-..< A A.< c".a!!-Bor!erLayout.%GYTM, cyclesa!HustCycles.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: %ine\ave-., *'', I''.< A A ///3> 6ll o" the data #e#bers and arrays are used in the calculation o" the sine wave %oints= cycles indicates the nu#ber o" co#%lete sine waves desired, points contains the total nu#ber o" %oints that will be gra%hed, sines contains the sine "unction values, and pts contains the y'coordinates o" the %oints that will be drawn on the J#anel. The set-yclesA B #ethod

Cha ter 13! Creating Bindo,s & "

lets

8;;

creates the arrays according to the nu#ber o" %oints needed and "ills the sines array with nu#bers. By calling repaintA B , set-yclesA B "orces paint-omponentA B to be called so the rest o" the calculation and redraw will take %lace. RFSURFSTIJLT+(6PTE5MLTIM3HU The "irst thing you #ust do when you override paint-omponentA B is to call the base'class version o" the #ethod. Then you are "ree to do whatever you like; nor#ally, this #eans using the "raphics #ethods that you can "ind in the docu#entation "or 8ava!a(t!"raphics *in the (TMD docu#entation "ro# >ava'sun'com, to draw and %aint %i&els onto the J#anel. (ere, you can see that al#ost all the code is involved in %er"or#ing the calculations; the only two #ethod calls that actually #ani%ulate the screen are set-olorA B and 'ra(+ineA B. /ou will %robably have a si#ilar e&%erience when creating your own %rogra# that dis%lays gra%hical data9you ll s%end #ost o" your ti#e "iguring out what it is you want to draw, but the actual drawing %rocess will be Auite si#%le. RFSURFSTIJLT+(6PTE5MLTIM33U :hen I created this %rogra#, the bulk o" #y ti#e was s%ent in getting the sine wave to dis%lay. )nce I did that, I thought it would be nice to be able to dyna#ically change the nu#ber o" cycles. My %rogra##ing e&%eriences when trying to do such things in other languages #ade #e a bit reluctant to try this, but it turned out to be the easiest %art o" the %ro0ect. I created a J)li'er *the argu#ents are the le"t'#ost value o" the J)li'er, the right'#ost value, and the starting value, res%ectively, but there are other constructors as well, and dro%%ed it into the JApplet. Then I looked at the (TMD docu#entation and noticed that the only listener was the a''-hange+istener, which was triggered whenever the slider was changed enough "or it to %roduce a di""erent value. The only #ethod "or this was the obviously na#ed state-hange'A B, which %rovided a -hange&vent ob0ect so that I could look backward to the source o" the change and "ind the new value. By calling the sines ob0ect s set-yclesA B, the new value was incor%orated and the J#anel redrawn. RFSURFSTIJLT+(6PTE5MLTIM3GU In general, you will "ind that #ost o" your Swing %roble#s can be solved by "ollowing a si#ilar %rocess, and you ll "ind that it s generally Auite si#%le, even i" you haven t used a %articular co#%onent be"ore. RFSURF STIJLT+(6PTE5MLTIM3IU

:==

I" your %roble# is #ore co#%le&, there are other #ore so%histicated alternatives "or drawing, including third'%arty JavaBeans co#%onents and the Java K7 6PI. These solutions are beyond the sco%e o" this book, but you should look the# u% i" your drawing code beco#es too onerous. RFSURFSTIJLT+(6PTE5MLTIM32U

Dialog ;o0es
6 dialog bo& is a window that %o%s u% out o" another window. Its %ur%ose is to deal with so#e s%eci"ic issue without cluttering the original window with those details. 7ialog bo&es are heavily used in windowed %rogra##ing environ#ents, but less "reAuently used in a%%lets. RFSURF STIJLT+(6PTE5MLTIMG@U To create a dialog bo&, you inherit "ro# J ialog, which is 0ust another kind o" 0in'o(, like a JFrame. 6 J ialog has a layout #anager *which de"aults to 2or'er+ayo*t, and you add event listeners to deal with events. )ne signi"icant di""erence when (in'o(-losingA B is called is that you don t want to shut down the a%%lication. Instead, you release the resources used by the dialog s window by calling 'isposeA B. (ere s a very si#%le e&a#%le=

//3 c()3Dialogs.Hava // Creating an! using Dialog Bo6es. // Pa""let co!e?Dialogs :i!th?( , height?*,Q // P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.event.B< i#"ort Hava.a:t.B< i#"ort co#.bruceeckel.s:ing.B< class JyDialog e6ten!s JDialog @ "ublic JyDialog-JLra#e "arent. @ su"er-"arent, 8Jy !ialog8, true.< Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< c".a!!-ne: JLabel-8Mere is #y !ialog8..< JButton ok ? ne: JButton-8G`8.< ok.a!!0ctionListener-ne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e.@

Cha ter 13! Creating Bindo,s & "

lets

:=1

!is"ose-.< // Closes the !ialog A A.< c".a!!-ok.< set%iUe-(,',( ,.< A A "ublic class Dialogs e6ten!s J0""let @ JButton b( ? ne: JButton-8Dialog Bo68.< JyDialog !lg ? ne: JyDialog-null.< "ublic voi! init-. @ b(.a!!0ctionListener-ne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e.@ !lg.sho:-.< A A.< getContentPane-..a!!-b(.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Dialogs-., ( ,, *,.< A A ///3>
)nce the J ialog is created, the sho(A B #ethod #ust be called to dis%lay and activate it. Eor the dialog to close, it #ust call 'isposeA B. RF SURFSTIJLT+(6PTE5MLTIMGMU /ou ll see that anything that %o%s u% out o" an a%%let, including dialog bo&es, is !untrusted.$ That is, you get a warning in the window that s been %o%%ed u%. This is because, in theory, it would be %ossible to "ool the user into thinking that they re dealing with a regular native a%%lication and to get the# to ty%e in their credit card nu#ber, which then goes across the :eb. 6n a%%let is always attached to a :eb %age and visible within your :eb browser, while a dialog bo& is detached9so in theory, it could be %ossible. 6s a result it is not so co##on to see an a%%let that uses a dialog bo&. RFSURFSTIJLT+(6PTE5MLTIMGKU The "ollowing e&a#%le is #ore co#%le&; the dialog bo& is #ade u% o" a grid *using "ri'+ayo*t, o" a s%ecial kind o" button that is de"ined here as class Toe2*tton. This button draws a "ra#e around itsel" and,

:=2

de%ending on its state, a blank, an !&,$ or an !o$ in the #iddle. It starts out blank, and then de%ending on whose turn it is, changes to an !&$ or an !o.$ (owever, it will also "li% back and "orth between !&$ and !o$ when you click on the button. *This #akes the tic'tac'toe conce%t only slightly #ore annoying than it already is., In addition, the dialog bo& can be set u% "or any nu#ber o" rows and colu#ns by changing nu#bers in the #ain a%%lication window.

//3 c()3TicTacToe.Hava // De#onstration of !ialog bo6es // an! creating your o:n co#"onents. // Pa""let co!e?TicTacToe // :i!th? '' height?(''QP/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class TicTacToe e6ten!s J0""let @ JTe6tLiel! ro:s ? ne: JTe6tLiel!-8)8., cols ? ne: JTe6tLiel!-8)8.< static final int BL0&` ? ', 99 ? (, GG ? < class ToeDialog e6ten!s JDialog @ int turn ? 99< // %tart :ith 62s turn // : ? nu#ber of cells :i!e // h ? nu#ber of cells high "ublic ToeDialog-int :, int h. @ setTitle-8The ga#e itself8.< Container c" ? getContentPane-.< c".setLayout-ne: ari!Layout-:, h..< for-int i ? '< i P : B h< iKK. c".a!!-ne: ToeButton-..< set%iUe-: B ,', h B ,'.< // JD` (.) close !ialog3 //SsetDefaultCloseG"eration//S D$%PG%EbG&bCLG%E.< // JD` (. close !ialog3 a!!\in!o:Listener-ne: \in!o:0!a"ter-. @ "ublic voi! :in!o:Closing-\in!o:Event e.@ !is"ose-.<

Cha ter 13! Creating Bindo,s & "

lets

:=3

A A.< A class ToeButton e6ten!s JPanel @ int state ? BL0&`< "ublic ToeButton-. @ a!!JouseListener-ne: JL-..< A "ublic voi! "aintCo#"onent-ara"hics g. @ su"er."aintCo#"onent-g.< int 6( ? '< int y( ? '< int 6 ? get%iUe-..:i!th - (< int y ? get%iUe-..height - (< g.!ra:5ect-6(, y(, 6 , y .< 6( ? 6 /I< y( ? y /I< int :i!e ? 6 / < int high ? y / < if-state ?? 99. @ g.!ra:Line-6(, y(, 6( K :i!e, y( K high.< g.!ra:Line-6(, y( K high, 6( K :i!e, y(.< A if-state ?? GG. @ g.!ra:Gval-6(, y(, 6( K :i!e/ , y( K high/ .< A A class JL e6ten!s Jouse0!a"ter @ "ublic voi! #ousePresse!-JouseEvent e. @ if-state ?? BL0&`. @ state ? turn< turn ? -turn ?? 99 [ GG 3 99.< A else state ? -state ?? 99 [ GG 3 99.< re"aint-.< A A

:=4

A A class BL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ JDialog ! ? ne: ToeDialog$nteger."arse$nt-ro:s.getTe6t-.., $nteger."arse$nt-cols.getTe6t-...< !.setWisible-true.< A A "ublic voi! init-. @ JPanel " ? ne: JPanel-.< ".setLayout-ne: ari!Layout- , ..< ".a!!-ne: JLabel-85o:s8, JLabel.CE&TE5..< ".a!!-ro:s.< ".a!!-ne: JLabel-8Colu#ns8, JLabel.CE&TE5..< ".a!!-cols.< Container c" ? getContentPane-.< c".a!!-", Bor!erLayout.&G5TM.< JButton b ? ne: JButton-8go8.< b.a!!0ctionListener-ne: BL-..< c".a!!-b, Bor!erLayout.%GYTM.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: TicTacToe-., '', (''.< A A ///3>
Because statics can only be at the outer level o" the class, inner classes cannot have static data or static inner classes. RFSURF STIJLT+(6PTE5MLTIMGLU The paint-omponentA B #ethod draws the sAuare around the %anel, and the !&$ or the !o.$ This is "ull o" tedious calculations, but it s straight"orward. RFSURFSTIJLT+(6PTE5MLTIMG?U 6 #ouse click is ca%tured by the 1o*se+istener, which "irst checks to see i" the %anel has anything written on it. I" not, the %arent window is Aueried to "ind out whose turn it is and that is used to establish the state o" the Toe2*tton. Via the inner class #echanis#, the Toe2*tton then reaches back into the %arent and changes the turn. I" the button is already

Cha ter 13! Creating Bindo,s & "

lets

:=5

dis%laying an !&$ or an !o$ then that is "lo%%ed. /ou can see in these calculations the convenient use o" the ternary i"'else described in +ha%ter L. 6"ter a state change, the Toe2*tton is re%ainted. RFSURF STIJLT+(6PTE5MLTIMGHU The constructor "or Toe ialog is Auite si#%le= it adds into a "ri'+ayo*t as #any buttons as you reAuest, then resi1es it "or H@ %i&els on a side "or each button. RFSURFSTIJLT+(6PTE5MLTIMG3U

TicTacToe sets u% the whole a%%lication by creating the JTe4tFiel's *"or in%utting the rows and colu#ns o" the button grid, and the !go$ button with its Action+istener. :hen the button is %ressed, the data in the JTe4tFiel's #ust be "etched, and, since they are in )tring "or#, turned into ints using the static Integer!parseIntA B #ethod. RFSURF STIJLT+(6PTE5MLTIMGGU

<ile dialogs
So#e o%erating syste#s have a nu#ber o" s%ecial built'in dialog bo&es to handle the selection o" things such as "onts, colors, %rinters, and the like. Virtually all gra%hical o%erating syste#s su%%ort the o%ening and saving o" "iles, however, and so Java s JFile-hooser enca%sulates these "or easy use. RFSURFSTIJLT+(6PTE5MLTIMGIU The "ollowing a%%lication e&ercises two "or#s o" JFile-hooser dialogs, one "or o%ening and one "or saving. Most o" the code should by now be "a#iliar, and all the interesting activities ha%%en in the action listeners "or the two di""erent button clicks=

//3 c()3LileChooserTest.Hava // De#onstration of Lile !ialog bo6es. i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class LileChooserTest e6ten!s JLra#e @ JTe6tLiel! filena#e ? ne: JTe6tLiel!-., !ir ? ne: JTe6tLiel!-.<

:=7

JButton o"en ? ne: JButton-8G"en8., save ? ne: JButton-8%ave8.< "ublic LileChooserTest-. @ JPanel " ? ne: JPanel-.< o"en.a!!0ctionListener-ne: G"enL-..< ".a!!-o"en.< save.a!!0ctionListener-ne: %aveL-..< ".a!!-save.< Container c" ? getContentPane-.< c".a!!-", Bor!erLayout.%GYTM.< !ir.setE!itable-false.< filena#e.setE!itable-false.< " ? ne: JPanel-.< ".setLayout-ne: ari!Layout- ,(..< ".a!!-filena#e.< ".a!!-!ir.< c".a!!-", Bor!erLayout.&G5TM.< A class G"enL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ JLileChooser c ? ne: JLileChooser-.< // De#onstrate 8G"en8 !ialog3 int rWal ? c.sho:G"enDialog-LileChooserTest.this.< if-rWal ?? JLileChooser.0PP5GWEbGPT$G&. @ filena#e.setTe6tc.get%electe!Lile-..get&a#e-..< !ir.setTe6tc.getCurrentDirectory-..to%tring-..< A if-rWal ?? JLileChooser.C0&CELbGPT$G&. @ filena#e.setTe6t-8;ou "resse! cancel8.< !ir.setTe6t-88.< A A A class %aveL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ JLileChooser c ? ne: JLileChooser-.< // De#onstrate 8%ave8 !ialog3

Cha ter 13! Creating Bindo,s & "

lets

:=8

int rWal ? c.sho:%aveDialog-LileChooserTest.this.< if-rWal ?? JLileChooser.0PP5GWEbGPT$G&. @ filena#e.setTe6tc.get%electe!Lile-..get&a#e-..< !ir.setTe6tc.getCurrentDirectory-..to%tring-..< A if-rWal ?? JLileChooser.C0&CELbGPT$G&. @ filena#e.setTe6t-8;ou "resse! cancel8.< !ir.setTe6t-88.< A A A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: LileChooserTest-., ,', (('.< A A ///3>
Cote that there are #any variations you can a%%ly to JFile-hooser, including "ilters to narrow the "ile na#es that you will allow. RFSURF STIJLT+(6PTE5MLTIMG2U Eor an !o%en "ile$ dialog, you call sho(.pen ialogA B, and "or a !save "ile$ dialog you call sho()ave ialogA B. These co##ands don t return until the dialog is closed. The JFile-hooser ob0ect still e&ists, so you can read data "ro# it. The #ethods get)electe'FileA B and get-*rrent irectoryA B are two ways you can interrogate the results o" the o%eration. I" these return n*ll it #eans the user canceled out o" the dialog. RFSURFSTIJLT+(6PTE5MLTIMI@U

>#M& on 1wing com.onents


6ny co#%onent that can take te&t can also take (TMD te&t, which it will re"or#at according to (TMD rules. This #eans you can very easily add "ancy te&t to a Swing co#%onent. Eor e&a#%le,

//3 c()3MTJLButton.Hava // Putting MTJL te6t on %:ing co#"onents. // Pa""let co!e?MTJLButton :i!th? '' height?,''Q // P/a""letQ

:=:

i#"ort i#"ort i#"ort i#"ort

Hava6.s:ing.B< Hava.a:t.event.B< Hava.a:t.B< co#.bruceeckel.s:ing.B<

"ublic class MTJLButton e6ten!s J0""let @ JButton b ? ne: JButton-8Pht#lQPbQPfont siUe?K Q8 K 8PcenterQMello4PbrQPiQPress #e no:48.< "ublic voi! init-. @ b.a!!0ctionListener-ne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e.@ getContentPane-..a!!-ne: JLabel-8Pht#lQ8K 8PiQPfont siUe?KIQ`a"o:48..< // Lorce a re-layout to // inclu!e the ne: label3 vali!ate-.< A A.< Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< c".a!!-b.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: MTJLButton-., '', ,''.< A A ///3>
/ou #ust start the te&t with !Rht#lU,$ and then you can use nor#al (TMD tags. Cote that you are not "orced to include the nor#al closing tags. RFSURFSTIJLT+(6PTE5MLTIMIMU The Action+istener adds a new J+abel to the "or#, which also contains (TMD te&t. (owever, this label is not added during initA B so you #ust call the container s vali'ateA B #ethod in order to "orce a re' layout o" the co#%onents *and thus the dis%lay o" the new label,. RFSURF STIJLT+(6PTE5MLTIMIKU /ou can also use (TMD te&t "or JTabbe'#ane, J1en*Item, JToolTip, J$a'io2*tton and J-heck2o4. RFSURF STIJLT+(6PTE5MLTIMILU

Cha ter 13! Creating Bindo,s & "

lets

:=;

1liders and .rogress bars


6 slider *which has already been used in the sine wave e&a#%le, allows the user to in%ut data by #oving a %oint back and "orth, which is intuitive in so#e situations *volu#e controls, "or e&a#%le,. 6 %rogress bar dis%lays data in a relative "ashion "ro# !"ull$ to !e#%ty$ so the user gets a %ers%ective. My "avorite e&a#%le "or these is to si#%ly hook the slider to the %rogress bar so when you #ove the slider the %rogress bar changes accordingly=

//3 c()3Progress.Hava // Ysing "rogress bars an! sli!ers. // Pa""let co!e?Progress // :i!th?)'' height? ''QP/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort Hava6.s:ing.event.B< i#"ort Hava6.s:ing.bor!er.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Progress e6ten!s J0""let @ JProgressBar "b ? ne: JProgressBar-.< J%li!er sb ? ne: J%li!er-J%li!er.MG5$TG&T0L, ', ('', +'.< "ublic voi! init-. @ Container c" ? getContentPane-.< c".setLayout-ne: ari!Layout- ,(..< c".a!!-"b.< sb.setWalue-'.< sb.setPaintTicks-true.< sb.setJaHorTick%"acing- '.< sb.setJinorTick%"acing-,.< sb.setBor!er-ne: Title!Bor!er-8%li!e Je8..< "b.setJo!el-sb.getJo!el-..< // %hare #o!el c".a!!-sb.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Progress-., )'', ''.< A A ///3>

:1=

The key to hooking the two co#%onents together is in sharing their #odel, in the line= RFSURFSTIJLT+(6PTE5MLTIMI?U

"b.setJo!el-sb.getJo!el-..< )" course, you could also control the two using a listener, but this is #ore straight"orward "or si#%le situations.
The J#rogress2ar is "airly straight"orward, but the J)li'er has a lot o" o%tions, such as the orientation and #a0or and #inor tick #arks. Cotice how straight"orward it is to add a titled border. N5WON5

WTIJJX-HA#T&$>JXI>Y@O

#rees
4sing a JTree can be as si#%le as saying=

a!!-ne: JTreene: GbHectNO @8this8, 8that8, 8other8A..<


This dis%lays a %ri#itive tree. The 6PI "or trees is vast, however9 certainly one o" the largest in Swing. It a%%ears that you can do 0ust about anything with trees, but #ore so%histicated tasks #ight reAuire Auite a bit o" research and e&%eri#entation. RFSURFSTIJLT+(6PTE5MLTIMI3U Eortunately, there is a #iddle ground %rovided in the library= the !de"ault$ tree co#%onents, which generally do what you need. So #ost o" the ti#e you can use these co#%onents, and only in s%ecial cases will you need to delve in and understand trees #ore dee%ly. RFSURF STIJLT+(6PTE5MLTIMIGU The "ollowing e&a#%le uses the !de"ault$ tree co#%onents to dis%lay a tree in an a%%let. :hen you %ress the button, a new subtree is added under the currently selected node *i" no node is selected, the root node is used,= RFSURFSTIJLT+(6PTE5MLTIMIIU

//3 c()3Trees.Hava // %i#"le %:ing tree e6a#"le. Trees can // be #a!e vastly #ore co#"le6 than this. // Pa""let co!e?Trees // :i!th? ,' height? ,'QP/a""letQ

Cha ter 13! Creating Bindo,s & "

lets

:11

i#"ort i#"ort i#"ort i#"ort i#"ort

Hava6.s:ing.B< Hava.a:t.B< Hava.a:t.event.B< Hava6.s:ing.tree.B< co#.bruceeckel.s:ing.B<

// Takes an array of %trings an! #akes the first // ele#ent a no!e an! the rest leaves3 class Branch @ DefaultJutableTree&o!e r< "ublic Branch-%tringNO !ata. @ r ? ne: DefaultJutableTree&o!e-!ataN'O.< for-int i ? (< i P !ata.length< iKK. r.a!!-ne: DefaultJutableTree&o!e-!ataNiO..< A "ublic DefaultJutableTree&o!e no!e-. @ return r< A A "ublic class Trees e6ten!s J0""let @ %tringNONO !ata ? @ @ 8Colors8, 85e!8, 8Blue8, 8areen8 A, @ 8Llavors8, 8Tart8, 8%:eet8, 8Blan!8 A, @ 8Length8, 8%hort8, 8Je!iu#8, 8Long8 A, @ 8Wolu#e8, 8Migh8, 8Je!iu#8, 8Lo:8 A, @ 8Te#"erature8, 8Migh8, 8Je!iu#8, 8Lo:8 A, @ 8$ntensity8, 8Migh8, 8Je!iu#8, 8Lo:8 A, A< static int i ? '< DefaultJutableTree&o!e root, chil!, chosen< JTree tree< DefaultTreeJo!el #o!el< "ublic voi! init-. @ Container c" ? getContentPane-.< root ? ne: DefaultJutableTree&o!e-8root8.< tree ? ne: JTree-root.< // 0!! it an! #ake it take care of scrolling3 c".a!!-ne: J%crollPane-tree., Bor!erLayout.CE&TE5.< // Ca"ture the tree2s #o!el3

:12

#o!el ?-DefaultTreeJo!el.tree.getJo!el-.< JButton test ? ne: JButton-8Press #e8.< test.a!!0ctionListener-ne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e.@ if-i P !ata.length. @ chil! ? ne: Branch-!ataNiKKO..no!e-.< // \hat2s the last one you clicke![ chosen ? -DefaultJutableTree&o!e. tree.getLast%electe!PathCo#"onent-.< if-chosen ?? null. chosen ? root< // The #o!el :ill create the // a""ro"riate event. $n res"onse, the // tree :ill u"!ate itself3 #o!el.insert&o!e$nto-chil!, chosen, '.< // This "uts the ne: no!e on the // currently chosen no!e. A A A.< // Change the button2s colors3 test.setBackgroun!-Color.blue.< test.setLoregroun!-Color.:hite.< JPanel " ? ne: JPanel-.< ".a!!-test.< c".a!!-", Bor!erLayout.%GYTM.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Trees-., ,', ,'.< A A ///3>
The "irst class, 2ranch, is a tool to take an array o" )tring and build a efa*lt1*tableTree/o'e with the "irst )tring as the root and the rest o" the )trings in the array as leaves. Then no'eA B can be called to %roduce the root o" this !branch.$ RFSURFSTIJLT+(6PTE5MLTIMI2U The Trees class contains a two'di#ensional array o" )trings "ro# which 2ranches can be #ade and a static int i to count through this array. The efa*lt1*tableTree/o'e ob0ects hold the nodes, but the %hysical re%resentation on screen is controlled by the JTree and its associated #odel, the efa*ltTree1o'el. Cote that when the JTree is

Cha ter 13! Creating Bindo,s & "

lets

:13

added to the a%%let, it is wra%%ed in a J)croll#ane9this is all it takes to %rovide auto#atic scrolling. RFSURFSTIJLT+(6PTE5MLTIM2@U The JTree is controlled through its model. :hen you #ake a change to the #odel, the #odel generates an event that causes the JTree to %er"or# any necessary u%dates to the visible re%resentation o" the tree. In initA B, the #odel is ca%tured by calling get1o'elA B. :hen the button is %ressed, a new !branch$ is created. Then the currently selected co#%onent is "ound *or the root is used i" nothing is selected, and the #odel s insert/o'eIntoA B #ethod does all the work o" changing the tree and causing it to be u%dated. RFSURFSTIJLT+(6PTE5MLTIM2MU 6n e&a#%le like the one above #ay give you what you need in a tree. (owever, trees have the %ower to do 0ust about anything you can i#agine 9everywhere you see the word !de"ault$ in the e&a#%le above, you can substitute your own class to get di""erent behavior. But beware= al#ost all o" these classes have a large inter"ace, so you could s%end a lot o" ti#e struggling to understand the intricacies o" trees. 7es%ite this, it s a good design and the alternatives are usually #uch worse. RFSURF STIJLT+(6PTE5MLTIM2KU

#ables
Dike trees, tables in Swing are vast and %ower"ul. They are %ri#arily intended to be the %o%ular !grid$ inter"ace to databases via Java 7atabase +onnectivity *J7B+, discussed in +ha%ter MH, and thus they have a tre#endous a#ount o" "le&ibility, which you %ay "or in co#%le&ity. There s easily enough here to be the basis o" a "ull'blown s%readsheet and could %robably 0usti"y an entire book. (owever, it is also %ossible to create a relatively si#%le JTable i" you understand the basics. RFSURF STIJLT+(6PTE5MLTIM2LU The JTable controls how the data is dis%layed, but the Table1o'el controls the data itsel". So to create a JTable you ll ty%ically create a Table1o'el "irst. /ou can "ully i#%le#ent the Table1o'el inter"ace, but it s usually si#%ler to inherit "ro# the hel%er class AbstractTable1o'el=

//3 c()3Table.Hava // %i#"le !e#onstration of JTable.

:14

// Pa""let co!e?Table // :i!th?),' height? ''QP/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort Hava6.s:ing.table.B< i#"ort Hava6.s:ing.event.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Table e6ten!s J0""let @ JTe6t0rea t6t ? ne: JTe6t0rea-I, '.< // The TableJo!el controls all the !ata3 class DataJo!el e6ten!s 0bstractTableJo!el @ GbHectNONO !ata ? @ @8one8, 8t:o8, 8three8, 8four8A, @8five8, 8si68, 8seven8, 8eight8A, @8nine8, 8ten8, 8eleven8, 8t:elve8A, A< // Prints !ata :hen table changes3 class TJL i#"le#ents TableJo!elListener @ "ublic voi! tableChange!-TableJo!elEvent e.@ t6t.setTe6t-88.< // Clear it for-int i ? '< i P !ata.length< iKK. @ for-int H ? '< H P !ataN'O.length< HKK. t6t.a""en!-!ataNiONHO K 8 8.< t6t.a""en!-8_n8.< A A A "ublic DataJo!el-. @ a!!TableJo!elListener-ne: TJL-..< A "ublic int getColu#nCount-. @ return !ataN'O.length< A "ublic int get5o:Count-. @ return !ata.length< A "ublic GbHect getWalue0t-int ro:, int col. @ return !ataNro:ONcolO< A

Cha ter 13! Creating Bindo,s & "

lets

:15

"ublic voi! setWalue0t-GbHect val, int ro:, int col. @ !ataNro:ONcolO ? val< // $n!icate the change has ha""ene!3 fireTableDataChange!-.< A "ublic boolean isCellE!itable-int ro:, int col. @ return true< A A "ublic voi! init-. @ Container c" ? getContentPane-.< JTable table ? ne: JTable-ne: DataJo!el-..< c".a!!-ne: J%crollPane-table..< c".a!!-Bor!erLayout.%GYTM, t6t.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Table-., ),', ''.< A A ///3> ata1o'el contains an array o" data, but you could also get the data "ro# so#e other source such as a database. The constructor adds a Table1o'el+istener that %rints the array every ti#e the table is changed. The rest o" the #ethods "ollow the Beans na#ing convention, and are used by JTable when it wants to %resent the in"or#ation in ata1o'el. AbstractTable1o'el %rovides de"ault #ethods "or setVal*eAtA B and is-ell&'itableA B that %revent changes to the data, so i" you want to be able to edit the data, you #ust override these #ethods. RFSURFSTIJLT+(6PTE5MLTIM2?U
)nce you have a Table1o'el, you only need to hand it to the JTable constructor. 6ll the details o" dis%laying, editing, and u%dating will be taken care o" "or you. This e&a#%le also %uts the JTable in a J)croll#ane. RFSURFSTIJLT+(6PTE5MLTIM2HU

:17

1electing &ook L <eel


)ne o" the very interesting as%ects o" Swing is the !Pluggable Dook N Eeel. $ This allows your %rogra# to e#ulate the look and "eel o" various o%erating environ#ents. /ou can even do all sorts o" "ancy things like dyna#ically changing the look and "eel while the %rogra# is e&ecuting. (owever, you generally 0ust want to do one o" two things, either select the !cross %lat"or#$ look and "eel *which is Swing s !#etal$,, or select the look and "eel "or the syste# you are currently on, so your Java %rogra# looks like it was created s%eci"ically "or that syste#. The code to select either o" these behaviors is Auite si#%le9but you #ust e&ecute it be$ore you create any visual co#%onents, because the co#%onents will be #ade based on the current look and "eel and will not be changed 0ust because you ha%%en to change the look and "eel #idway during the %rogra# *that %rocess is #ore co#%licated and unco##on, and is relegated to Swing' s%eci"ic books,. RFSURFSTIJLT+(6PTE5MLTIM23U 6ctually, i" you want to use the cross'%lat"or# *!#etal$, look and "eel that is characteristic o" Swing %rogra#s, you don t have to do anything9it s the de"ault. But i" you want instead to use the current o%erating environ#ent s look and "eel, you 0ust insert the "ollowing code, ty%ically at the beginning o" your mainA B but so#ehow be"ore any co#%onents are added=

try @ Y$Janager.setLook0n!Leel-Y$Janager. get%yste#Look0n!LeelClass&a#e-..< A catch-E6ce"tion e. @A


/ou don t need anything in the catch clause because the UI1anager will de"ault to the cross'%lat"or# look and "eel i" your atte#%ts to set u% any o" the alternatives "ail. (owever, during debugging the e&ce%tion can be Auite use"ul so you #ay at least want to %ut a %rint state#ent in the catch clause. RFSURFSTIJLT+(6PTE5MLTIM2GU (ere is a %rogra# that takes a co##and'line argu#ent to select a look and "eel, and shows how several di""erent co#%onents look under the chosen look and "eel=

//3 c()3Look0n!Leel.Hava

Cha ter 13! Creating Bindo,s & "

lets

:18

// %electing !ifferent looks D feels. i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort Hava.util.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Look0n!Leel e6ten!s JLra#e @ %tringNO choices ? @ 8eeny8, 8#eeny8, 8#inie8, 8#oe8, 8toe8, 8you8 A< Co#"onentNO sa#"les ? @ ne: JButton-8JButton8., ne: JTe6tLiel!-8JTe6tLiel!8., ne: JLabel-8JLabel8., ne: JCheckBo6-8JCheckBo68., ne: J5a!ioButton-85a!io8., ne: JCo#boBo6-choices., ne: JList-choices., A< "ublic Look0n!Leel-. @ su"er-8Look 0n! Leel8.< Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< for-int i ? '< i P sa#"les.length< iKK. c".a!!-sa#"lesNiO.< A "rivate static voi! usageError-. @ %yste#.out."rintln8Ysage3Look0n!Leel NcrossXsyste#X#otifO8.< %yste#.e6it-(.< A "ublic static voi! #ain-%tringNO args. @ if-args.length ?? '. usageError-.< if-argsN'O.e=uals-8cross8.. @ try @ Y$Janager.setLook0n!Leel-Y$Janager. getCrossPlatfor#Look0n!LeelClass&a#e-..< A catch-E6ce"tion e. @ e."rint%tackTrace-%yste#.err.< A

:1:

A else if-argsN'O.e=uals-8syste#8.. @ try @ Y$Janager.setLook0n!Leel-Y$Janager. get%yste#Look0n!LeelClass&a#e-..< A catch-E6ce"tion e. @ e."rint%tackTrace-%yste#.err.< A A else if-argsN'O.e=uals-8#otif8.. @ try @ Y$Janager.setLook0n!Leel-8co#.sun.Hava.8K 8s:ing."laf.#otif.JotifLook0n!Leel8.< A catch-E6ce"tion e. @ e."rint%tackTrace-%yste#.err.< A A else usageError-.< // &ote the look D feel #ust be set before // any co#"onents are create!. Console.run-ne: Look0n!Leel-., )'', ''.< A A ///3>
/ou can see that one o%tion is to e&%licitly s%eci"y a string "or a look and "eel, as seen with 1otif+ookAn'Feel. (owever, that one and the de"ault !#etal$ look and "eel are the only ones that can legally be used on any %lat"or#; even though there are strings "or :indows and Macintosh look and "eels, those can only be used on their res%ective %lat"or#s *these are %roduced when you call get)ystem+ookAn'Feel-lass/ameA B and you re on that %articular %lat"or#,. RFSURF STIJLT+(6PTE5MLTIM2IU It is also %ossible to create a custo# look and "eel %ackage, "or e&a#%le, i" you are building a "ra#ework "or a co#%any that wants a distinctive a%%earance. This is a big 0ob and is "ar beyond the sco%e o" this book *in "act, you ll discover it is beyond the sco%e o" #any dedicated Swing books.,. RFSURFSTIJLT+(6PTE5MLTIM22U

#he cli.board
The JE+ su%%orts li#ited o%erations with the syste# cli%board *in the

8ava!a(t!'atatransfer %ackage,. /ou can co%y )tring ob0ects to the

Cha ter 13! Creating Bindo,s & "

lets

:1;

cli%board as te&t, and you can %aste te&t "ro# the cli%board into )tring ob0ects. )" course, the cli%board is designed to hold any ty%e o" data, but how this data is re%resented on the cli%board is u% to the %rogra# doing the cutting and %asting. The Java cli%board 6PI %rovides "or e&tensibility through the conce%t o" a !"lavor.$ :hen data co#es o"" the cli%board, it has an associated set o" "lavors that it can be converted to *"or e&a#%le, a gra%h #ight be re%resented as a string o" nu#bers or as an i#age, and you can see i" that %articular cli%board data su%%orts the "lavor you re interested in. RFSURFSTIJLT+(6PTE5MLTIK@@U The "ollowing %rogra# is a si#%le de#onstration o" cut, co%y, and %aste with )tring data in a JTe4tArea. )ne thing you ll notice is that the keyboard seAuences you nor#ally use "or cutting, co%ying, and %asting also work. But i" you look at any JTe4tFiel' or JTe4tArea in any other %rogra# you ll "ind that they also auto#atically su%%ort the cli%board key seAuences. This e&a#%le si#%ly adds %rogra##atic control o" the cli%board, and you could use these techniAues i" you want to ca%ture cli%board te&t into so#ething other than a JTe4t-omponent.

//3 c()3Cut0n!Paste.Hava // Ysing the cli"boar!. i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort Hava.a:t.!atatransfer.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Cut0n!Paste e6ten!s JLra#e @ JJenuBar #b ? ne: JJenuBar-.< JJenu e!it ? ne: JJenu-8E!it8.< JJenu$te# cut ? ne: JJenu$te#-8Cut8., co"y ? ne: JJenu$te#-8Co"y8., "aste ? ne: JJenu$te#-8Paste8.< JTe6t0rea te6t ? ne: JTe6t0rea- ', '.< Cli"boar! cli"b! ? getToolkit-..get%yste#Cli"boar!-.< "ublic Cut0n!Paste-. @ cut.a!!0ctionListener-ne: CutL-..< co"y.a!!0ctionListener-ne: Co"yL-..<

:2=

"aste.a!!0ctionListener-ne: PasteL-..< e!it.a!!-cut.< e!it.a!!-co"y.< e!it.a!!-"aste.< #b.a!!-e!it.< setJJenuBar-#b.< getContentPane-..a!!-te6t.< A class Co"yL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ %tring selection ? te6t.get%electe!Te6t-.< if -selection ?? null. return< %tring%election cli"%tring ? ne: %tring%election-selection.< cli"b!.setContents-cli"%tring,cli"%tring.< A A class CutL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ %tring selection ? te6t.get%electe!Te6t-.< if -selection ?? null. return< %tring%election cli"%tring ? ne: %tring%election-selection.< cli"b!.setContents-cli"%tring, cli"%tring.< te6t.re"lace5ange-88, te6t.get%election%tart-., te6t.get%electionEn!-..< A A class PasteL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ Transferable cli"Data ? cli"b!.getContents-Cut0n!Paste.this.< try @ %tring cli"%tring ? -%tring.cli"Data. getTransferDataDataLlavor.stringLlavor.< te6t.re"lace5ange-cli"%tring,

Cha ter 13! Creating Bindo,s & "

lets

:21

te6t.get%election%tart-., te6t.get%electionEn!-..< A catch-E6ce"tion e6. @ %yste#.err."rintln-8&ot %tring flavor8.< A A A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Cut0n!Paste-., )'', ''.< A A ///3>
The creation and addition o" the #enu and JTe4tArea should by now see# a %edestrian activity. :hat s di""erent is the creation o" the -lipboar' "ield clipb', which is done through the Toolkit. RFSURF STIJLT+(6PTE5MLTIK@MU 6ll the action takes %lace in the listeners. The -opy+ and -*t+ listeners are the sa#e e&ce%t "or the last line o" -*t+, which erases the line that s been co%ied. The s%ecial two lines are the creation o" a )tring)election ob0ect "ro# the )tring and the call to set-ontentsA B with this )tring)election. That s all there is to %utting a )tring on the cli%board. RFSURFSTIJLT+(6PTE5MLTIK@KU In #aste+, data is %ulled o"" the cli%board using get-ontentsA B. :hat co#es back is a "airly anony#ous Transferable ob0ect, and you don t really know what it contains. )ne way to "ind out is to call getTransfer ataFlavorsA B, which returns an array o" ataFlavor ob0ects indicating which "lavors are su%%orted by this %articular ob0ect. /ou can also ask it directly with is ataFlavor)*pporte'A B, %assing in the "lavor you re interested in. (ere, however, the bold a%%roach is taken= getTransfer ataA B is called assu#ing that the contents su%%orts the )tring "lavor, and i" it doesn t the %roble# is sorted out in the e&ce%tion handler. RFSURFSTIJLT+(6PTE5MLTIK@LU In the "uture you can e&%ect #ore data "lavors to be su%%orted.

:22

ackaging an a..let into a "A$ file


6n i#%ortant use o" the J65 utility is to o%ti#i1e a%%let loading. In Java M.@, %eo%le tended to try to cra# all their code into a single a%%let class so the client would need only a single server hit to download the a%%let code. Cot only did this result in #essy, hard to read *and #aintain, %rogra#s, but the !class "ile was still unco#%ressed so downloading wasn t as "ast as it could have been. RFSURFSTIJLT+(6PTE5MLTIK@?U J65 "iles solve the %roble# by co#%ressing all o" your !class "iles into a single "ile that is downloaded by the browser. Cow you can create the right design without worrying about how #any !class "iles it will generate, and the user will get a #uch "aster download ti#e. RFSURF STIJLT+(6PTE5MLTIK@HU +onsider TicTacToe!8ava. It looks like a single class, but in "act it contains "ive inner classes, so that s si& in all. )nce you ve co#%iled the %rogra#, you %ackage it into a J65 "ile with the line=

Har cf TicTacToe.Har B.class


This assu#es that the only !class "iles in the current directory are the ones "ro# TicTacToe!8ava *otherwise you ll get e&tra baggage,. RFSURF STIJLT+(6PTE5MLTIK@3U Cow you can create an (TMD %age with the new archive tag to indicate the na#e o" the J65 "ile. (ere is the tag using the old "or# o" the (TMD tag, as an illustration=

Phea!QPtitleQTicTacToe E6a#"le 0""let P/titleQP/hea!Q Pbo!yQ Pa""let co!e?TicTacToe.class archive?TicTacToe.Har :i!th? '' height?(''Q P/a""letQ P/bo!yQ

Cha ter 13! Creating Bindo,s & "

lets

:23

/ou ll need to %ut it into the new *#essy, co#%licated, "or# shown earlier in the cha%ter in order to get it to work.

rogramming techni%ues
Because 84I %rogra##ing in Java has been an evolving technology with so#e very signi"icant changes between Java M.@FM.M and the Swing library in Java K, there have been so#e old %rogra##ing idio#s that have see%ed through to e&a#%les that you #ight see given "or Swing. In addition, Swing allows you to %rogra# in #ore and better ways than were allowed by the old #odels. In this section, so#e o" these issues will be de#onstrated by introducing and e&a#ining so#e %rogra##ing idio#s. RFSURFSTIJLT+(6PTE5MLTIK@GU

;inding events d:namicall:


)ne o" the bene"its o" the Swing event #odel is "le&ibility. /ou can add and re#ove event behavior with single #ethod calls. The "ollowing e&a#%le de#onstrates this=

//3 c()3Dyna#icEvents.Hava // ;ou can change event behavior !yna#ically. // 0lso sho:s #ulti"le actions for an event. // Pa""let co!e?Dyna#icEvents // :i!th? ,' height?I''QP/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort Hava.util.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Dyna#icEvents e6ten!s J0""let @ 0rrayList v ? ne: 0rrayList-.< int i ? '< JButton b( ? ne: JButton-8Button(8., b ? ne: JButton-8Button 8.<

:24

JTe6t0rea t6t ? ne: JTe6t0rea-.< class B i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ t6t.a""en!-80 button :as "resse!_n8.< A A class CountListener i#"le#ents 0ctionListener @ int in!e6< "ublic CountListener-int i. @ in!e6 ? i< A "ublic voi! actionPerfor#e!-0ctionEvent e. @ t6t.a""en!-8Counte! Listener 8Kin!e6K8_n8.< A A class B( i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ t6t.a""en!-8Button ( "resse!_n8.< 0ctionListener a ? ne: CountListener-iKK.< v.a!!-a.< b .a!!0ctionListener-a.< A A class B i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ t6t.a""en!-8Button "resse!_n8.< int en! ? v.siUe-. - (< if-en! Q? '. @ b .re#ove0ctionListener-0ctionListener.v.get-en!..< v.re#ove-en!.< A A A "ublic voi! init-. @ Container c" ? getContentPane-.< b(.a!!0ctionListener-ne: B-..< b(.a!!0ctionListener-ne: B(-..< b .a!!0ctionListener-ne: B-..< b .a!!0ctionListener-ne: B -..< JPanel " ? ne: JPanel-.< ".a!!-b(.< ".a!!-b .<

Cha ter 13! Creating Bindo,s & "

lets

:25

c".a!!-Bor!erLayout.&G5TM, ".< c".a!!-ne: J%crollPane-t6t..< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Dyna#icEvents-., ,', I''.< A A ///3>
The new twists in this e&a#%le are= RFSURFSTIJLT+(6PTE5MLTIK@IU

(!6) There is #ore than one listener attached to each 2*tton. 4sually, co#%onents handle events as multicast, #eaning that you can
register #any listeners "or a single event. In the s%ecial co#%onents in which an event is handled as unicast, you ll get a Too1any+isteners&4ception. RFSURF STIJLT+(6PTE5MLTIK@2U

(*7) 7uring the e&ecution o" the %rogra#, listeners are dyna#ically added and re#oved "ro# the 2*tton bI. 6dding is acco#%lished
in the way you ve seen be"ore, but each co#%onent also has a removeXXX+istenerA B #ethod to re#ove each ty%e o" listener. RFSURFSTIJLT+(6PTE5MLTIKM@U This kind o" "le&ibility %rovides #uch greater %ower in your %rogra##ing. RFSURFSTIJLT+(6PTE5MLTIKMMU /ou should notice that event listeners are not guaranteed to be called in the order they are added *although #ost i#%le#entations do in "act work that way,. RFSURFSTIJLT+(6PTE5MLTIKMKU

1e.arating business logic from CI logic


In general you ll want to design your classes so that each one does !only one thing.$ This is %articularly i#%ortant when user'inter"ace code is concerned, since it s easy to tie u% !what you re doing$ with !how you re dis%laying it.$ This kind o" cou%ling %revents code reuse. It s #uch #ore desirable to se%arate your !business logic$ "ro# the 84I. This way, you can not only reuse the business logic #ore easily, it s also easier to reuse the 84I.

:27

6nother issue is multitiered syste#s, where the !business ob0ects$ reside on a co#%letely se%arate #achine. This central location o" the business rules allows changes to be instantly e""ective "or all new transactions, and is thus a co#%elling way to set u% a syste#. (owever, these business ob0ects can be used in #any di""erent a%%lications and so should not be tied to any %articular #ode o" dis%lay. They should 0ust %er"or# the business o%erations and nothing #ore. RFSURF STIJLT+(6PTE5MLTIKMLU The "ollowing e&a#%le shows how easy it is to se%arate the business logic "ro# the 84I code=

//3 c()3%e"aration.Hava // %e"arating aY$ logic an! business obHects. // Pa""let co!e?%e"aration // :i!th? ,' height?(,'Q P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava6.s:ing.event.B< i#"ort Hava.a:t.event.B< i#"ort Hava.a""let.B< i#"ort co#.bruceeckel.s:ing.B< class BusinessLogic @ "rivate int #o!ifier< "ublic BusinessLogic-int #o!. @ #o!ifier ? #o!< A "ublic voi! setJo!ifier-int #o!. @ #o!ifier ? #o!< A "ublic int getJo!ifier-. @ return #o!ifier< A // %o#e business o"erations3 "ublic int calculation(-int arg. @ return arg B #o!ifier< A "ublic int calculation -int arg. @ return arg K #o!ifier< A

Cha ter 13! Creating Bindo,s & "

lets

:28

A "ublic class %e"aration e6ten!s J0""let @ JTe6tLiel! t ? ne: JTe6tLiel!-(,., #o! ? ne: JTe6tLiel!-(,.< BusinessLogic bl ? ne: BusinessLogic- .< JButton calc( ? ne: JButton-8Calculation (8., calc ? ne: JButton-8Calculation 8.< static int getWalue-JTe6tLiel! tf. @ try @ return $nteger."arse$nt-tf.getTe6t-..< A catch-&u#berLor#atE6ce"tion e. @ return '< A A class Calc(L i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ t.setTe6t-$nteger.to%tringbl.calculation(-getWalue-t....< A A class Calc L i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ t.setTe6t-$nteger.to%tringbl.calculation -getWalue-t....< A A // $f you :ant so#ething to ha""en :henever // a JTe6tLiel! changes, a!! this listener3 class Jo!L i#"le#ents Docu#entListener @ "ublic voi! change!Y"!ate-Docu#entEvent e. @A "ublic voi! insertY"!ate-Docu#entEvent e. @ bl.setJo!ifier-getWalue-#o!..< A "ublic voi! re#oveY"!ate-Docu#entEvent e. @ bl.setJo!ifier-getWalue-#o!..< A A "ublic voi! init-. @

:2:

Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< c".a!!-t.< calc(.a!!0ctionListener-ne: Calc(L-..< calc .a!!0ctionListener-ne: Calc L-..< JPanel "( ? ne: JPanel-.< "(.a!!-calc(.< "(.a!!-calc .< c".a!!-"(.< #o!.getDocu#ent-.. a!!Docu#entListener-ne: Jo!L-..< JPanel " ? ne: JPanel-.< " .a!!-ne: JLabel-8Jo!ifier38..< " .a!!-#o!.< c".a!!-" .< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: %e"aration-., ,', (''.< A A ///3>
/ou can see that 2*siness+ogic is a straight"orward class that %er"or#s its o%erations without even a hint that it #ight be used in a 84I environ#ent. It 0ust does its 0ob. RFSURFSTIJLT+(6PTE5MLTIKM?U

)eparation kee%s track o" all the 4I details, and it talks to 2*siness+ogic only through its p*blic inter"ace. 6ll the o%erations are
centered around getting in"or#ation back and "orth through the 4I and the 2*siness+ogic ob0ect. So )eparation, in turn, 0ust does its 0ob. Since )eparation knows only that it s talking to a 2*siness+ogic ob0ect *that is, it isn t highly cou%led,, it could be #assaged into talking to other ty%es o" ob0ects without #uch trouble. RFSURF STIJLT+(6PTE5MLTIKMHU Thinking in ter#s o" se%arating 4I "ro# business logic also #akes li"e easier when you re ada%ting legacy code to work with Java. RFSURF STIJLT+(6PTE5MLTIKM3U

Cha ter 13! Creating Bindo,s & "

lets

:2;

A canonical form
Inner classes, the Swing event #odel, and the "act that the old event #odel is still su%%orted along with new library "eatures that rely on old' style %rogra##ing has added a new ele#ent o" con"usion to the code design %rocess. Cow there are even #ore di""erent ways "or %eo%le to write un%leasant code. RFSURFSTIJLT+(6PTE5MLTIKMGU E&ce%t in e&tenuating circu#stances you can always use the si#%lest and clearest a%%roach= listener classes *ty%ically written as inner classes, to solve your event'handling needs. This is the "or# used in #ost o" the e&a#%les in this cha%ter. RFSURFSTIJLT+(6PTE5MLTIKMIU By "ollowing this #odel you should be able to reduce the state#ents in your %rogra#s that say= !I wonder what caused this event.$ Each %iece o" code is concerned with doing, not ty%e'checking. This is the best way to write your code; not only is it easier to conce%tuali1e, but #uch easier to read and #aintain. RFSURFSTIJLT+(6PTE5MLTIKM2U

=isual .rogramming and ;eans


So "ar in this book you ve seen how valuable Java is "or creating reusable %ieces o" code. The !#ost reusable$ unit o" code has been the class, since it co#%rises a cohesive unit o" characteristics *"ields, and behaviors *#ethods, that can be reused either directly via co#%osition or through inheritance. RFSURFSTIJLT+(6PTE5MLTIKK@U Inheritance and %oly#or%his# are essential %arts o" ob0ect'oriented %rogra##ing, but in the #a0ority o" cases when you re %utting together an a%%lication, what you really want is co#%onents that do e&actly what you need. /ou d like to dro% these %arts into your design like the electronic engineer %uts together chi%s on a circuit board. It see#s, too, that there should be so#e way to accelerate this !#odular asse#bly$ style o" %rogra##ing. RFSURFSTIJLT+(6PTE5MLTIKKMU

:3=

!Visual %rogra##ing$ "irst beca#e success"ul9 ver) success"ul9with Microso"t s Visual Basic *VB,, "ollowed by a second'generation design in Borland s 7el%hi *the %ri#ary ins%iration "or the JavaBeans design,. :ith these %rogra##ing tools the co#%onents are re%resented visually, which #akes sense since they usually dis%lay so#e kind o" visual co#%onent such as a button or a te&t "ield. The visual re%resentation, in "act, is o"ten e&actly the way the co#%onent will look in the running %rogra#. So %art o" the %rocess o" visual %rogra##ing involves dragging a co#%onent "ro# a %alette and dro%%ing it onto your "or#. The a%%lication builder tool writes code as you do this, and that code will cause the co#%onent to be created in the running %rogra#. RFSURF STIJLT+(6PTE5MLTIKKKU Si#%ly dro%%ing the co#%onent onto a "or# is usually not enough to co#%lete the %rogra#. )"ten, you #ust change the characteristics o" a co#%onent, such as what color it is, what te&t is on it, what database it s connected to, etc. +haracteristics that can be #odi"ied at design ti#e are re"erred to as ro erties. /ou can #ani%ulate the %ro%erties o" your co#%onent inside the a%%lication builder tool, and when you create the %rogra# this con"iguration data is saved so that it can be re0uvenated when the %rogra# is started. RFSURFSTIJLT+(6PTE5MLTIKKLU By now you re %robably used to the idea that an ob0ect is #ore than characteristics; it s also a set o" behaviors. 6t design'ti#e, the behaviors o" a visual co#%onent are %artially re%resented by events, #eaning !(ere s so#ething that can ha%%en to the co#%onent.$ )rdinarily, you decide what you want to ha%%en when an event occurs by tying code to that event. RFSURFSTIJLT+(6PTE5MLTIKK?U (ere s the critical %art= the a%%lication builder tool uses re"lection to dyna#ically interrogate the co#%onent and "ind out which %ro%erties and events the co#%onent su%%orts. )nce it knows what they are, it can dis%lay the %ro%erties and allow you to change those *saving the state when you build the %rogra#,, and also dis%lay the events. In general, you do so#ething like double'clicking on an event and the a%%lication builder tool creates a code body and ties it to that %articular event. 6ll you have to do at that %oint is write the code that e&ecutes when the event occurs. RF SURFSTIJLT+(6PTE5MLTIKKHU

Cha ter 13! Creating Bindo,s & "

lets

:31

6ll this adds u% to a lot o" work that s done "or you by the a%%lication builder tool. 6s a result you can "ocus on what the %rogra# looks like and what it is su%%osed to do, and rely on the a%%lication builder tool to #anage the connection details "or you. The reason that visual %rogra##ing tools have been so success"ul is that they dra#atically s%eed u% the %rocess o" building an a%%lication9certainly the user inter"ace, but o"ten other %ortions o" the a%%lication as well. RFSURF STIJLT+(6PTE5MLTIKK3U

What is a ;eanA
6"ter the dust settles, then, a co#%onent is really 0ust a block o" code, ty%ically e#bodied in a class. The key issue is the ability "or the a%%lication builder tool to discover the %ro%erties and events "or that co#%onent. To create a VB co#%onent, the %rogra##er had to write a "airly co#%licated %iece o" code "ollowing certain conventions to e&%ose the %ro%erties and events. 7el%hi was a second'generation visual %rogra##ing tool and the language was actively designed around visual %rogra##ing so it is #uch easier to create a visual co#%onent. (owever, Java has brought the creation o" visual co#%onents to its #ost advanced state with JavaBeans, because a Bean is 0ust a class. /ou don t have to write any e&tra code or use s%ecial language e&tensions in order to #ake so#ething a Bean. The only thing you need to do, in "act, is slightly #odi"y the way that you na#e your #ethods. It is the #ethod na#e that tells the a%%lication builder tool whether this is a %ro%erty, an event, or 0ust an ordinary #ethod. RFSURFSTIJLT+(6PTE5MLTIKKGU In the Java docu#entation, this na#ing convention is #istakenly ter#ed a !design %attern.$ This is un"ortunate, since design %atterns *see Thinking in Patterns ,ith Java, downloadable at ,,,'0ruceEckel'com, are challenging enough without this sort o" con"usion. It s not a design %attern, it s 0ust a na#ing convention and it s "airly si#%le=

(*() Eor a %ro%erty na#ed 444, you ty%ically create two #ethods= getX44A B and setX44A B. Cote that the "irst letter a"ter !get$ or
!set$ is auto#atically lowercased to %roduce the %ro%erty na#e. The ty%e %roduced by the !get$ #ethod is the sa#e as the ty%e o" the argu#ent to the !set$ #ethod. The na#e o" the %ro%erty and

:32

the ty%e "or the !get$ and !set$ are not related. RFSURF STIJLT+(6PTE5MLTIKKIU

(*!) Eor a boolean %ro%erty, you can use the !get$ and !set$ a%%roach
above, but you can also use !is$ instead o" !get.$ RFSURF STIJLT+(6PTE5MLTIKK2U

(**) )rdinary #ethods o" the Bean don t con"or# to the above na#ing convention, but they re p*blic. RFSURF
STIJLT+(6PTE5MLTIKL@U

(*+) Eor events, you use the Swing !listener$ a%%roach. It s e&actly the sa#e as you ve been seeing= a''Foo2ar+istener AFoo2ar+istenerB and removeFoo2ar+istener AFoo2ar+istenerB to handle a Foo2ar&vent. Most o" the ti#e
the built'in events and listeners will satis"y your needs, but you can also create your own events and listener inter"aces. RFSURF STIJLT+(6PTE5MLTIKLMU Point M above answers a Auestion about so#ething you #ight have noticed when looking at older code vs. newer code= a nu#ber o" #ethod na#es have had s#all, a%%arently #eaningless na#e changes. Cow you can see that #ost o" those changes had to do with ada%ting to the !get$ and !set$ na#ing conventions in order to #ake that %articular co#%onent into a Bean. RFSURFSTIJLT+(6PTE5MLTIKLKU

:e can use these guidelines to create a si#%le Bean= //3 frogbean3Lrog.Hava // 0 trivial JavaBean. "ackage frogbean< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< class %"ots @A "ublic class Lrog @ "rivate int Hu#"s< "rivate Color color< "rivate %"ots s"ots< "rivate boolean H#"r<

Cha ter 13! Creating Bindo,s & "

lets

:33

"ublic int getJu#"s-. @ return Hu#"s< A "ublic voi! setJu#"s-int ne:Ju#"s. @ Hu#"s ? ne:Ju#"s< A "ublic Color getColor-. @ return color< A "ublic voi! setColor-Color ne:Color. @ color ? ne:Color< A "ublic %"ots get%"ots-. @ return s"ots< A "ublic voi! set%"ots-%"ots ne:%"ots. @ s"ots ? ne:%"ots< A "ublic boolean isJu#"er-. @ return H#"r< A "ublic voi! setJu#"er-boolean H. @ H#"r ? H< A "ublic voi! a!!0ctionListener0ctionListener l. @ //... A "ublic voi! re#ove0ctionListener0ctionListener l. @ // ... A "ublic voi! a!!`eyListener-`eyListener l. @ // ... A "ublic voi! re#ove`eyListener-`eyListener l. @ // ... A // 0n 8or!inary8 "ublic #etho!3 "ublic voi! croak-. @ %yste#.out."rintln-85ibbet48.< A A ///3>
Eirst, you can see that it s 0ust a class. 4sually, all your "ields will be

private, and accessible only through #ethods. Eollowing the na#ing convention, the %ro%erties are 8*mps, color, spots, and 8*mper
*notice the case change o" the "irst letter in the %ro%erty na#e,. 6lthough the na#e o" the internal identi"ier is the sa#e as the na#e o" the %ro%erty in the "irst three cases, in 8*mper you can see that the %ro%erty na#e does not "orce you to use any %articular identi"ier "or internal variables

:34

*or, indeed, to even have any internal variables "or that %ro%erty,. RF SURFSTIJLT+(6PTE5MLTIKLLU The events this Bean handles are Action&vent and %ey&vent, based on the na#ing o" the !add$ and !re#ove$ #ethods "or the associated listener. Einally, you can see that the ordinary #ethod croakA B is still %art o" the Bean si#%ly because it s a p*blic #ethod, not because it con"or#s to any na#ing sche#e. RFSURFSTIJLT+(6PTE5MLTIKL?U

/0tracting Bean7n!o with the 7ntros ector


)ne o" the #ost critical %arts o" the Bean sche#e occurs when you drag a Bean o"" a %alette and %lo% it onto a "or#. The a%%lication builder tool #ust be able to create the Bean *which it can do i" there s a de"ault constructor, and then, without access to the Bean s source code, e&tract all the necessary in"or#ation to create the %ro%erty sheet and event handlers. RFSURFSTIJLT+(6PTE5MLTIKLHU Part o" the solution is already evident "ro# the end o" +ha%ter MK= Java re$lection allows all the #ethods o" an anony#ous class to be discovered. This is %er"ect "or solving the Bean %roble# without reAuiring you to use any e&tra language keywords like those reAuired in other visual %rogra##ing languages. In "act, one o" the %ri#e reasons that re"lection was added to Java was to su%%ort Beans *although re"lection also su%%orts ob0ect seriali1ation and re#ote #ethod invocation,. So you #ight e&%ect that the creator o" the a%%lication builder tool would have to re"lect each Bean and hunt through its #ethods to "ind the %ro%erties and events "or that Bean. RFSURFSTIJLT+(6PTE5MLTIKL3U This is certainly %ossible, but the Java designers wanted to %rovide a standard tool, not only to #ake Beans si#%ler to use but also to %rovide a standard gateway to the creation o" #ore co#%le& Beans. This tool is the Introspector class, and the #ost i#%ortant #ethod in this class is the static get2eanInfoA B. /ou %ass a -lass re"erence to this #ethod and it "ully interrogates that class and returns a 2eanInfo ob0ect that you can then dissect to "ind %ro%erties, #ethods, and events. RFSURF STIJLT+(6PTE5MLTIKLGU

Cha ter 13! Creating Bindo,s & "

lets

:35

4sually you won t care about any o" this9you ll %robably get #ost o" your Beans o"" the shel" "ro# vendors, and you don t need to know all the #agic that s going on underneath. /ou ll si#%ly drag your Beans onto your "or#, then con"igure their %ro%erties and write handlers "or the events you re interested in. (owever, it s an interesting and educational e&ercise to use the Introspector to dis%lay in"or#ation about a Bean, so here s a tool that does it=

//3 c()3BeanDu#"er.Hava // $ntros"ecting a Bean. // Pa""let co!e?BeanDu#"er :i!th?+'' height?,''Q // P/a""letQ i#"ort Hava.beans.B< i#"ort Hava.lang.reflect.B< i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class BeanDu#"er e6ten!s J0""let @ JTe6tLiel! =uery ? ne: JTe6tLiel!- '.< JTe6t0rea results ? ne: JTe6t0rea-.< "ublic voi! "rt-%tring s. @ results.a""en!-s K 8_n8.< A "ublic voi! !u#"-Class bean.@ results.setTe6t-88.< Bean$nfo bi ? null< try @ bi ? $ntros"ector.getBean$nfobean, Hava.lang.GbHect.class.< A catch-$ntros"ectionE6ce"tion e. @ "rt-8Coul!n2t intros"ect 8 K bean.get&a#e-..< return< A Pro"ertyDescri"torNO "ro"erties ? bi.getPro"ertyDescri"tors-.< for-int i ? '< i P "ro"erties.length< iKK. @ Class " ? "ro"ertiesNiO.getPro"ertyTy"e-.<

:37

"rt-8Pro"erty ty"e3_n 8 K ".get&a#e-. K 8Pro"erty na#e3_n 8 K "ro"ertiesNiO.get&a#e-..< Jetho! rea!Jetho! ? "ro"ertiesNiO.get5ea!Jetho!-.< if-rea!Jetho! 4? null. "rt-85ea! #etho!3_n 8 K rea!Jetho!.< Jetho! :riteJetho! ? "ro"ertiesNiO.get\riteJetho!-.< if-:riteJetho! 4? null. "rt-8\rite #etho!3_n 8 K :riteJetho!.< "rt-8????????????????????8.< A "rt-8Public #etho!s38.< Jetho!Descri"torNO #etho!s ? bi.getJetho!Descri"tors-.< for-int i ? '< i P #etho!s.length< iKK. "rt-#etho!sNiO.getJetho!-..to%tring-..< "rt-8??????????????????????8.< "rt-8Event su""ort38.< Event%etDescri"torNO events ? bi.getEvent%etDescri"tors-.< for-int i ? '< i P events.length< iKK. @ "rt-8Listener ty"e3_n 8 K eventsNiO.getListenerTy"e-..get&a#e-..< Jetho!NO l# ? eventsNiO.getListenerJetho!s-.< for-int H ? '< H P l#.length< HKK. "rt-8Listener #etho!3_n 8 K l#NHO.get&a#e-..< Jetho!Descri"torNO l#! ? eventsNiO.getListenerJetho!Descri"tors-.< for-int H ? '< H P l#!.length< HKK. "rt-8Jetho! !escri"tor3_n 8 K l#!NHO.getJetho!-..< Jetho! a!!Listener ? eventsNiO.get0!!ListenerJetho!-.< "rt-80!! Listener Jetho!3_n 8 K a!!Listener.< Jetho! re#oveListener ? eventsNiO.get5e#oveListenerJetho!-.<

Cha ter 13! Creating Bindo,s & "

lets

:38

"rt-85e#ove Listener Jetho!3_n re#oveListener.< "rt-8????????????????????8.<

8 K

A A class Du#"er i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ %tring na#e ? =uery.getTe6t-.< Class c ? null< try @ c ? Class.for&a#e-na#e.< A catch-Class&otLoun!E6ce"tion e6. @ results.setTe6t-8Coul!n2t fin! 8 K na#e.< return< A !u#"-c.< A A "ublic voi! init-. @ Container c" ? getContentPane-.< JPanel " ? ne: JPanel-.< ".setLayout-ne: Llo:Layout-..< ".a!!-ne: JLabel-8/ualifie! bean na#e38..< ".a!!-=uery.< c".a!!-Bor!erLayout.&G5TM, ".< c".a!!-ne: J%crollPane-results..< Du#"er !#"r ? ne: Du#"er-.< =uery.a!!0ctionListener-!#"r.< =uery.setTe6t-8frogbean.Lrog8.< // Lorce evaluation !#"r.actionPerfor#e!ne: 0ctionEvent-!#"r, ', 88..< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: BeanDu#"er-., +'', ,''.< A A ///3> 2ean *mper!'*mpA B is the #ethod that does all the work. Eirst it tries to create a 2eanInfo ob0ect, and i" success"ul calls the #ethods o" 2eanInfo that %roduce in"or#ation about %ro%erties, #ethods, and

:3:

events. In Introspector!get2eanInfoA B, you ll see there is a second argu#ent. This tells the Introspector where to sto% in the inheritance hierarchy. (ere, it sto%s be"ore it %arses all the #ethods "ro# .b8ect, since we re not interested in seeing those. RFSURF STIJLT+(6PTE5MLTIKLIU Eor %ro%erties, get#roperty escriptorsA B returns an array o" #roperty escriptors. Eor each #roperty escriptor you can call get#ropertyTypeA B to "ind the class o" ob0ect that is %assed in and out via the %ro%erty #ethods. Then, "or each %ro%erty you can get its %seudony# *e&tracted "ro# the #ethod na#es, with get/ameA B, the #ethod "or reading with get$ea'1etho'A B, and the #ethod "or writing with get0rite1etho'A B. These last two #ethods return a 1etho' ob0ect that can actually be used to invoke the corres%onding #ethod on the ob0ect *this is %art o" re"lection,. RFSURF STIJLT+(6PTE5MLTIKL2U Eor the p*blic #ethods *including the %ro%erty #ethods,, get1etho' escriptorsA B returns an array o" 1etho' escriptors. Eor each one you can get the associated 1etho' ob0ect and %rint its na#e. RFSURFSTIJLT+(6PTE5MLTIK?@U Eor the events, get&vent)et escriptorsA B returns an array o" *what elseO, &vent)et escriptors. Each o" these can be Aueried to "ind out the class o" the listener, the #ethods o" that listener class, and the add' and re#ove'listener #ethods. The 2ean *mper %rogra# %rints out all o" this in"or#ation. RFSURFSTIJLT+(6PTE5MLTIK?MU 4%on startu%, the %rogra# "orces the evaluation o" frogbean!Frog. The out%ut, a"ter re#oving e&tra details that are unnecessary here, is=

class na#e3 Lrog Pro"erty ty"e3 Color Pro"erty na#e3 color 5ea! #etho!3 "ublic Color getColor-. \rite #etho!3 "ublic voi! setColor-Color. ????????????????????

Cha ter 13! Creating Bindo,s & "

lets

:3;

Pro"erty ty"e3 %"ots Pro"erty na#e3 s"ots 5ea! #etho!3 "ublic %"ots get%"ots-. \rite #etho!3 "ublic voi! set%"ots-%"ots. ???????????????????? Pro"erty ty"e3 boolean Pro"erty na#e3 Hu#"er 5ea! #etho!3 "ublic boolean isJu#"er-. \rite #etho!3 "ublic voi! setJu#"er-boolean. ???????????????????? Pro"erty ty"e3 int Pro"erty na#e3 Hu#"s 5ea! #etho!3 "ublic int getJu#"s-. \rite #etho!3 "ublic voi! setJu#"s-int. ???????????????????? Public #etho!s3 "ublic voi! setJu#"s-int. "ublic voi! croak-. "ublic voi! re#ove0ctionListener-0ctionListener. "ublic voi! a!!0ctionListener-0ctionListener. "ublic int getJu#"s-. "ublic voi! setColor-Color. "ublic voi! set%"ots-%"ots. "ublic voi! setJu#"er-boolean. "ublic boolean isJu#"er-. "ublic voi! a!!`eyListener-`eyListener. "ublic Color getColor-. "ublic voi! re#ove`eyListener-`eyListener. "ublic %"ots get%"ots-.

:4=

?????????????????????? Event su""ort3 Listener ty"e3 `eyListener Listener #etho!3 keyTy"e! Listener #etho!3 keyPresse! Listener #etho!3 key5elease! Jetho! !escri"tor3 "ublic voi! keyTy"e!-`eyEvent. Jetho! !escri"tor3 "ublic voi! keyPresse!-`eyEvent. Jetho! !escri"tor3 "ublic voi! key5elease!-`eyEvent. 0!! Listener Jetho!3 "ublic voi! a!!`eyListener-`eyListener. 5e#ove Listener Jetho!3 "ublic voi! re#ove`eyListener-`eyListener. ???????????????????? Listener ty"e3 0ctionListener Listener #etho!3 actionPerfor#e! Jetho! !escri"tor3 "ublic voi! actionPerfor#e!-0ctionEvent. 0!! Listener Jetho!3 "ublic voi! a!!0ctionListener-0ctionListener. 5e#ove Listener Jetho!3 "ublic voi! re#ove0ctionListener-0ctionListener. ????????????????????
This reveals #ost o" what the Introspector sees as it %roduces a 2eanInfo ob0ect "ro# your Bean. /ou can see that the ty%e o" the %ro%erty and its na#e are inde%endent. Cotice the lowercasing o" the %ro%erty na#e. *The only ti#e this doesn t occur is when the %ro%erty na#e begins with #ore than one ca%ital letter in a row., 6nd re#e#ber that the #ethod na#es you re seeing here *such as the read and write #ethods, are actually %roduced "ro# a 1etho' ob0ect that can be used

Cha ter 13! Creating Bindo,s & "

lets

:41

to invoke the associated #ethod on the ob0ect. RFSURF STIJLT+(6PTE5MLTIK?KU The p*blic #ethod list includes the #ethods that are not associated with a %ro%erty or event, such as croakA B, as well as those that are. These are all the #ethods that you can call %rogra##atically "or a Bean, and the a%%lication builder tool can choose to list all o" these while you re #aking #ethod calls, to ease your task. RFSURFSTIJLT+(6PTE5MLTIK?LU Einally, you can see that the events are "ully %arsed out into the listener, its #ethods, and the add' and re#ove'listener #ethods. Basically, once you have the 2eanInfo, you can "ind out everything o" i#%ortance "or the Bean. /ou can also call the #ethods "or that Bean, even though you don t have any other in"or#ation e&ce%t the ob0ect *again, a "eature o" re"lection,. RFSURFSTIJLT+(6PTE5MLTIK??U

A more so.histicated ;ean


This ne&t e&a#%le is slightly #ore so%histicated, albeit "rivolous. It s a J#anel that draws a little circle around the #ouse whenever the #ouse is #oved. :hen you %ress the #ouse, the word !Bang.$ a%%ears in the #iddle o" the screen, and an action listener is "ired. RFSURF STIJLT+(6PTE5MLTIK?HU The %ro%erties you can change are the si1e o" the circle as well as the color, si1e, and te&t o" the word that is dis%layed when you %ress the #ouse. 6 2ang2ean also has its own a''Action+istenerA B and removeAction+istenerA B so you can attach your own listener that will be "ired when the user clicks on the 2ang2ean. /ou should be able to recogni1e the %ro%erty and event su%%ort=

//3 bangbean3BangBean.Hava // 0 gra"hical Bean. "ackage bangbean< i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort Hava.io.B< i#"ort Hava.util.B< i#"ort co#.bruceeckel.s:ing.B<

:42

"ublic class BangBean e6ten!s JPanel i#"le#ents %erialiUable @ "rotecte! int 6#, y#< "rotecte! int c%iUe ? '< // Circle siUe "rotecte! %tring te6t ? 8Bang48< "rotecte! int font%iUe ? I1< "rotecte! Color tColor ? Color.re!< "rotecte! 0ctionListener actionListener< "ublic BangBean-. @ a!!JouseListener-ne: JL-..< a!!JouseJotionListener-ne: JJL-..< A "ublic int getCircle%iUe-. @ return c%iUe< A "ublic voi! setCircle%iUe-int ne:%iUe. @ c%iUe ? ne:%iUe< A "ublic %tring getBangTe6t-. @ return te6t< A "ublic voi! setBangTe6t-%tring ne:Te6t. @ te6t ? ne:Te6t< A "ublic int getLont%iUe-. @ return font%iUe< A "ublic voi! setLont%iUe-int ne:%iUe. @ font%iUe ? ne:%iUe< A "ublic Color getTe6tColor-. @ return tColor< A "ublic voi! setTe6tColor-Color ne:Color. @ tColor ? ne:Color< A "ublic voi! "aintCo#"onent-ara"hics g. @ su"er."aintCo#"onent-g.< g.setColor-Color.black.< g.!ra:Gval-6# - c%iUe/ , y# - c%iUe/ , c%iUe, c%iUe.< A // This is a unicast listener, :hich is // the si#"lest for# of listener #anage#ent3 "ublic voi! a!!0ctionListener 0ctionListener l. thro:s TooJanyListenersE6ce"tion @ if-actionListener 4? null.

Cha ter 13! Creating Bindo,s & "

lets

:43

thro: ne: TooJanyListenersE6ce"tion-.< actionListener ? l< A "ublic voi! re#ove0ctionListener0ctionListener l. @ actionListener ? null< A class JL e6ten!s Jouse0!a"ter @ "ublic voi! #ousePresse!-JouseEvent e. @ ara"hics g ? getara"hics-.< g.setColor-tColor.< g.setLontne: Lont8Ti#es5o#an8, Lont.BGLD, font%iUe..< int :i!th ? g.getLontJetrics-..string\i!th-te6t.< g.!ra:%tring-te6t, -get%iUe-..:i!th - :i!th. / , get%iUe-..height/ .< g.!is"ose-.< // Call the listener2s #etho!3 if-actionListener 4? null. actionListener.actionPerfor#e!ne: 0ctionEvent-BangBean.this, 0ctionEvent.0CT$G&bPE5LG5JED, null..< A A class JJL e6ten!s JouseJotion0!a"ter @ "ublic voi! #ouseJove!-JouseEvent e. @ 6# ? e.get9-.< y# ? e.get;-.< re"aint-.< A A "ublic Di#ension getPreferre!%iUe-. @ return ne: Di#ension- '', ''.< A A ///3>
The "irst thing you ll notice is that 2ang2ean i#%le#ents the )eriali7able inter"ace. This #eans that the a%%lication builder tool can

:44

!%ickle$ all the in"or#ation "or the 2ang2ean using seriali1ation a"ter the %rogra# designer has ad0usted the values o" the %ro%erties. :hen the Bean is created as %art o" the running a%%lication, these !%ickled$ %ro%erties are restored so that you get e&actly what you designed. RFSURF STIJLT+(6PTE5MLTIK?3U /ou can see that all the "ields are private, which is what you ll usually do with a Bean9allow access only through #ethods, usually using the !%ro%erty$ sche#e. RFSURFSTIJLT+(6PTE5MLTIK?GU :hen you look at the signature "or a''Action+istenerA B, you ll see that it can throw a Too1any+isteners&4ception. This indicates that it is unicast, which #eans it noti"ies only one listener when the event occurs. )rdinarily, you ll use multicast events so that #any listeners can be noti"ied o" an event. (owever, that runs into issues that you won t be ready "or until the ne&t cha%ter, so it will be revisited there *under the heading !JavaBeans revisited$,. 6 unicast event sideste%s the %roble#. RF SURFSTIJLT+(6PTE5MLTIK?IU :hen you click the #ouse, the te&t is %ut in the #iddle o" the 2ang2ean, and i" the action+istener "ield is not n*ll, its action#erforme'A B is called, creating a new Action&vent ob0ect in the %rocess. :henever the #ouse is #oved, its new coordinates are ca%tured and the canvas is re%ainted *erasing any te&t that s on the canvas, as you ll see,. RFSURFSTIJLT+(6PTE5MLTIK?2U (ere is the 2ang2eanTest class to allow you to test the bean as either an a%%let or an a%%lication=

//3 c()3BangBeanTest.Hava // Pa""let co!e?BangBeanTest // :i!th?I'' height?,''QP/a""letQ i#"ort bangbean.B< i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort Hava.util.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class BangBeanTest e6ten!s J0""let @ JTe6tLiel! t6t ? ne: JTe6tLiel!- '.<

Cha ter 13! Creating Bindo,s & "

lets

:45

// During testing, re"ort actions3 class BBL i#"le#ents 0ctionListener @ int count ? '< "ublic voi! actionPerfor#e!-0ctionEvent e.@ t6t.setTe6t-8BangBean action 8K countKK.< A A "ublic voi! init-. @ BangBean bb ? ne: BangBean-.< try @ bb.a!!0ctionListener-ne: BBL-..< A catch-TooJanyListenersE6ce"tion e. @ t6t.setTe6t-8Too #any listeners8.< A Container c" ? getContentPane-.< c".a!!-bb.< c".a!!-Bor!erLayout.%GYTM, t6t.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: BangBeanTest-., I'', ,''.< A A ///3>
:hen a Bean is in a develo%#ent environ#ent, this class will not be used, but it s hel%"ul to %rovide a ra%id testing #ethod "or each o" your Beans. 2ang2eanTest %laces a 2ang2ean within the a%%let, attaching a si#%le Action+istener to the 2ang2ean to %rint an event count to the JTe4tFiel' whenever an Action&vent occurs. 4sually, o" course, the a%%lication builder tool would create #ost o" the code that uses the Bean. RFSURFSTIJLT+(6PTE5MLTIKH@U :hen you run the 2ang2ean through 2ean *mper or %ut the 2ang2ean inside a Bean'enabled develo%#ent environ#ent, you ll notice that there are #any #ore %ro%erties and actions than are evident "ro# the above code. That s because 2ang2ean is inherited "ro# J#anel, and J#anel is also Bean, so you re seeing its %ro%erties and events as well. RFSURFSTIJLT+(6PTE5MLTIKHMU

:47

ackaging a ;ean
Be"ore you can bring a Bean into a Bean'enabled visual builder tool, it #ust be %ut into the standard Bean container, which is a J65 "ile that includes all the Bean classes as well as a !#ani"est$ "ile that says !This is a Bean.$ 6 #ani"est "ile is si#%ly a te&t "ile that "ollows a %articular "or#. Eor the 2ang2ean, the #ani"est "ile looks like this *without the "irst and last lines,=

//34 3BangBean.#f Janifest-Wersion3 (.' &a#e3 bangbean/BangBean.class Java-Bean3 True ///3>


The "irst line indicates the version o" the #ani"est sche#e, which until "urther notice "ro# Sun is M.@. The second line *e#%ty lines are ignored, na#es the 2ang2ean!class "ile, and the third says, !It s a Bean.$ :ithout the third line, the %rogra# builder tool will not recogni1e the class as a Bean. RFSURFSTIJLT+(6PTE5MLTIKHKU The only tricky %art is that you #ust #ake sure that you get the %ro%er %ath in the !Ca#e=$ "ield. I" you look back at 2ang2ean!8ava, you ll see it s in package bangbean *and thus in a subdirectory called !bangbean$ that s o"" o" the class%ath,, and the na#e in the #ani"est "ile #ust include this %ackage in"or#ation. In addition, you #ust %lace the #ani"est "ile in the directory above the root o" your %ackage %ath, which in this case #eans %lacing the "ile in the directory above the !bangbean$ subdirectory. Then you #ust invoke 8ar "ro# the sa#e directory as the #ani"est "ile, as "ollows=

Har cf# BangBean.Har BangBean.#f bangbean


This assu#es that you want the resulting J65 "ile to be na#ed

2ang2ean!8ar and that you ve %ut the #ani"est in a "ile called 2ang2ean!mf. RFSURFSTIJLT+(6PTE5MLTIKHLU
/ou #ight wonder !:hat about all the other classes that were generated when I co#%iled 2ang2ean!8avaO$ :ell, they all ended u% inside the bangbean subdirectory, and you ll see that the last argu#ent "or the

Cha ter 13! Creating Bindo,s & "

lets

:48

above 8ar co##and line is the bangbean subdirectory. :hen you give 8ar the na#e o" a subdirectory, it %ackages that entire subdirectory into the 0ar "ile *including, in this case, the original 2ang2ean!8ava source' code "ile9you #ight not choose to include the source with your own Beans,. In addition, i" you turn around and un%ack the J65 "ile you ve 0ust created, you ll discover that your #ani"est "ile isn t inside, but that 8ar has created its own #ani"est "ile *based %artly on yours, called 1A/IF&)T!1F and %laced it inside the subdirectory 1&TA6I/F *"or !#eta'in"or#ation$,. I" you o%en this #ani"est "ile you ll also notice that digital signature in"or#ation has been added by 8ar "or each "ile, o" the "or#=

Digest-0lgorith#s3 %M0 JD, %M0-Digest3 "D"E0aC&aeC61aLt=P$Iu!%9/G'? JD,-Digest3 GI&c%(hE)%#nUl" hH+=eg??


In general, you don t need to worry about any o" this, and i" you #ake changes you can 0ust #odi"y your original #ani"est "ile and reinvoke 8ar to create a new J65 "ile "or your Bean. /ou can also add other Beans to the J65 "ile si#%ly by adding their in"or#ation to your #ani"est. RFSURF STIJLT+(6PTE5MLTIKH?U )ne thing to notice is that you ll %robably want to %ut each Bean in its own subdirectory, since when you create a J65 "ile you hand the 8ar utility the na#e o" a subdirectory and it %uts everything in that subdirectory into the J65 "ile. /ou can see that both Frog and 2ang2ean are in their own subdirectories. RFSURF STIJLT+(6PTE5MLTIKHHU )nce you have your Bean %ro%erly inside a J65 "ile you can bring it into a Beans'enabled %rogra#'builder environ#ent. The way you do this varies "ro# one tool to the ne&t, but Sun %rovides a "reely available test bed "or JavaBeans in their !Beans 7evelo%#ent >it$ *B7>, called the !beanbo&. $ *7ownload the B7> "ro# >ava'sun'com/beans., To %lace your Bean in the beanbo&, co%y the J65 "ile into the B7> s !0ars$ subdirectory be"ore you start u% the beanbo&. RFSURFSTIJLT+(6PTE5MLTIKH3U

:4:

More com.le0 ;ean su..ort


/ou can see how re#arkably si#%le it is to #ake a Bean. But you aren t li#ited to what you ve seen here. The JavaBeans architecture %rovides a si#%le %oint o" entry but can also scale to #ore co#%le& situations. These situations are beyond the sco%e o" this book, but they will be brie"ly introduced here. /ou can "ind #ore details at >ava'sun'com/beans. RF SURFSTIJLT+(6PTE5MLTIKHGU )ne %lace where you can add so%histication is with %ro%erties. The e&a#%les above have shown only single %ro%erties, but it s also %ossible to re%resent #ulti%le %ro%erties in an array. This is called an inde*ed ro ert). /ou si#%ly %rovide the a%%ro%riate #ethods *again "ollowing a na#ing convention "or the #ethod na#es, and the Introspector recogni1es an inde&ed %ro%erty so your a%%lication builder tool can res%ond a%%ro%riately. RFSURFSTIJLT+(6PTE5MLTIKHIU Pro%erties can be bound, which #eans that they will noti"y other ob0ects via a #roperty-hange&vent. The other ob0ects can then choose to change the#selves based on the change to the Bean. RFSURF STIJLT+(6PTE5MLTIKH2U Pro%erties can be constrained, which #eans that other ob0ects can veto a change to that %ro%erty i" it is unacce%table. The other ob0ects are noti"ied using a #roperty-hange&vent, and they can throw a #ropertyVeto&4ception to %revent the change "ro# ha%%ening and to restore the old values. RFSURFSTIJLT+(6PTE5MLTIK3@U /ou can also change the way your Bean is re%resented at design ti#e= RF SURFSTIJLT+(6PTE5MLTIK3MU

(*,) /ou can %rovide a custo# %ro%erty sheet "or your %articular Bean.
The ordinary %ro%erty sheet will be used "or all other Beans, but yours is auto#atically invoked when your Bean is selected. RFSURF STIJLT+(6PTE5MLTIK3KU

(*-) /ou can create a custo# editor "or a %articular %ro%erty, so the
ordinary %ro%erty sheet is used, but when your s%ecial %ro%erty is being edited, your editor will auto#atically be invoked. RFSURF STIJLT+(6PTE5MLTIK3LU

Cha ter 13! Creating Bindo,s & "

lets

:4;

(*4) /ou can %rovide a custo# 2eanInfo class "or your Bean that
%roduces in"or#ation that s di""erent "ro# the de"ault created by the Introspector. RFSURFSTIJLT+(6PTE5MLTIK3?U

(*5) It s also %ossible to turn !e&%ert$ #ode on and o"" in all Feat*re escriptors to distinguish between basic "eatures and
#ore co#%licated ones. RFSURFSTIJLT+(6PTE5MLTIK3HU

More to ;eans
There s another issue that couldn t be addressed here. :henever you create a Bean, you should e&%ect that it will be run in a #ultithreaded environ#ent. This #eans that you #ust understand the issues o" threading, which will be introduced in +ha%ter M?. /ou ll "ind a section there called !JavaBeans revisited$ that will look at the %roble# and its solution. RFSURFSTIJLT+(6PTE5MLTIK33U There are a nu#ber o" books about JavaBeans; "or e&a#%le, Java0eans by Elliotte 5usty (arold *I78, M22I,. RFSURFSTIJLT+(6PTE5MLTIK3GU

1ummar:
)" all the libraries in Java, the 84I library has seen the #ost dra#atic changes "ro# Java M.@ to Java K. The Java M.@ 6:T was roundly critici1ed as being one o" the worst designs seen, and while it would allow you to create %ortable %rogra#s, the resulting 84I was !eAually #ediocre on all %lat"or#s.$ It was also li#iting, awkward, and un%leasant to use co#%ared with the native a%%lication develo%#ent tools available on a %articular %lat"or#. RFSURFSTIJLT+(6PTE5MLTIK3IU :hen Java M.M introduced the new event #odel and JavaBeans, the stage was set9now it was %ossible to create 84I co#%onents that could be easily dragged and dro%%ed inside visual a%%lication builder tools. In addition, the design o" the event #odel and Beans clearly shows strong consideration "or ease o" %rogra##ing and #aintainable code *so#ething that was not evident in the M.@ 6:T,. But it wasn t until the JE+FSwing classes a%%eared that the 0ob was "inished. :ith the Swing

:5=

co#%onents, cross'%lat"or# 84I %rogra##ing can be a civili1ed e&%erience. RFSURFSTIJLT+(6PTE5MLTIK32U 6ctually, the only thing that s #issing is the a%%lication builder tool, and this is where the real revolution lies. Microso"t s Visual Basic and Visual +<< reAuire Microso"t s a%%lication builder tools, as does Borland s 7el%hi and +<< Builder. I" you want the a%%lication builder tool to get better, you have to cross your "ingers and ho%e the vendor will give you what you want. But Java is an o%en environ#ent, and so not only does it allow "or co#%eting a%%lication builder environ#ents, it encourages the#. 6nd "or these tools to be taken seriously, they #ust su%%ort JavaBeans. This #eans a leveled %laying "ield= i" a better a%%lication builder tool co#es along, you re not tied to the one you ve been using9 you can %ick u% and #ove to the new one and increase your %roductivity. This kind o" co#%etitive environ#ent "or 84I a%%lication builder tools has not been seen be"ore, and the resulting #arket%lace can generate only %ositive results "or the %roductivity o" the %rogra##er. RFSURF STIJLT+(6PTE5MLTIKG@U

This cha%ter was #eant only to give you an introduction to the %ower o" Swing and to get you started so you could see how relatively si#%le it is to "eel your way through the libraries. :hat you ve seen so "ar will %robably su""ice "or a good %ortion o" your 4I design needs. (owever, there s a lot #ore to Swing9it s intended to be a "ully %owered 4I design tool kit. There s %robably a way to acco#%lish 0ust about everything you can i#agine.
I" you don t see what you need here, delve into the online docu#entation "ro# Sun and search the :eb, and i" that s not enough then "ind a dedicated Swing book9a good %lace to start is The J9C S,ing Tutorial, by :alrath N +a#%ione *6ddison :esley, M222,. RFSURF STIJLT+(6PTE5MLTIKGMU

/0ercises
Solutions to selected e&ercises can be "ound in the electronic docu#entThe Thinking in Java "nnotated Solution @uide, available "or a s#all "ee "ro# ,,,'0ruceEckel'com.

Cha ter 13! Creating Bindo,s & "

lets

:51

!!!) +reate an a%%letFa%%lication using the -onsole class as shown


in this cha%ter. Include a te&t "ield and three buttons. :hen you %ress each button, #ake so#e di""erent te&t a%%ear in the te&t "ield. RFSURFSTIJLT+(6PTE5MLTIKGKU

!!*) 6dd a check bo& to the a%%let created in E&ercise M, ca%ture the
event, and insert di""erent te&t into the te&t "ield. RFSURF STIJLT+(6PTE5MLTIKGLU

!!+) +reate an a%%letFa%%lication using -onsole. In the (TMD


docu#entation "ro# >ava'sun'com, "ind the J#ass(or'Fiel' and add this to the %rogra#. I" the user ty%es in the correct %assword, use Joptionpane to %rovide a success #essage to the user. RFSURFSTIJLT+(6PTE5MLTIKG?U

!!,) +reate an a%%letFa%%lication using -onsole, and add all the


Swing co#%onents that have an a''Action+istenerA B #ethod. *Dook these u% in the (TMD docu#entation "ro# >ava'sun'com.
(int= use the inde&., +a%ture their events and dis%lay an a%%ro%riate #essage "or each inside a te&t "ield. RFSURF STIJLT+(6PTE5MLTIKGHU

!!-) +reate an a%%letFa%%lication using -onsole, with a J2*tton


and a JTe4tFiel'. :rite and attach the a%%ro%riate listener so that i" the button has the "ocus, characters ty%ed into it will a%%ear in the JTe4tFiel'. RFSURFSTIJLT+(6PTE5MLTIKG3U

!!4) +reate an a%%letFa%%lication using -onsole. 6dd to the #ain


"ra#e all the co#%onents described in this cha%ter, including #enus and a dialog bo&. RFSURFSTIJLT+(6PTE5MLTIKGGU

!!5) Modi"y Te4tFiel's!8ava so that the characters in tI retain the


original case that they were ty%ed in, instead o" auto#atically being "orced to u%%er case. RFSURFSTIJLT+(6PTE5MLTIKGIU

!!6) Docate and download one or #ore o" the "ree 84I builder
develo%#ent environ#ents available on the Internet, or buy a co##ercial %roduct. 7iscover what is necessary to add 2ang2ean to this environ#ent and to use it. RFSURF STIJLT+(6PTE5MLTIKG2U

:52

!*7) 6dd Frog!class to the #ani"est "ile as shown in this cha%ter


and run 8ar to create a J65 "ile containing both Frog and 2ang2ean. Cow either download and install the B7> "ro# Sun or use your own Beans'enabled %rogra# builder tool and add the J65 "ile to your environ#ent so you can test the two Beans. RF SURFSTIJLT+(6PTE5MLTIKI@U

!*() +reate your own JavaBean called Valve that contains two
%ro%erties= a boolean called !on$ and an int called !level.$ +reate a #ani"est "ile, use 8ar to %ackage your Bean, then load it into the beanbo& or into a Beans'enabled %rogra# builder tool so that you can test it. RFSURFSTIJLT+(6PTE5MLTIKIMU

!*!) Modi"y 1essage2o4es!8ava so that it has an individual


Action+istener "or each button *instead o" #atching the button
te&t,. RFSURFSTIJLT+(6PTE5MLTIKIKU

!**) Monitor a new ty%e o" event in Track&vent!8ava by adding


the new event handling code. /ou ll need to discover on your own the ty%e o" event that you want to #onitor. RFSURF STIJLT+(6PTE5MLTIKILU

!*+) Inherit a new ty%e o" button "ro# J2*tton. Each ti#e you
%ress this button, it should change its color to a rando#ly'selected value. See -olor2o4es!8ava in +ha%ter M? "or an e&a#%le o" how to generate a rando# color value. RFSURF STIJLT+(6PTE5MLTIKI?U

!*,) Modi"y Te4t#ane!8ava to use a JTe4tArea instead o" a


JTe4t#ane. RFSURFSTIJLT+(6PTE5MLTIKIHU

!*-) Modi"y 1en*s!8ava to use radio buttons instead o" check


bo&es on the #enus. RFSURFSTIJLT+(6PTE5MLTIKI3U

!*4) Si#%li"y +ist!8ava by %assing the array to the constructor and


eli#inating the dyna#ic addition o" ele#ents to the list. RFSURF STIJLT+(6PTE5MLTIKIGU

!*5) Modi"y )ine0ave!8ava to turn )ine ra( into a JavaBean by


adding !getter$ and !setter$ #ethods. RFSURF STIJLT+(6PTE5MLTIKIIU

Cha ter 13! Creating Bindo,s & "

lets

:53

!*6) 5e#e#ber the !sketching bo&$ toy with two knobs, one that
controls the vertical #ove#ent o" the drawing %oint, and one that controls the hori1ontal #ove#entO +reate one o" those, using )ine0ave!8ava to get you started. Instead o" knobs, use sliders. 6dd a button that will erase the entire sketch. RFSURF STIJLT+(6PTE5MLTIKI2U

!+7) +reate an !asy#%totic %rogress indicator$ that gets slower and


slower as it a%%roaches the "inish %oint. 6dd rando# erratic behavior so it will %eriodically look like it s starting to s%eed u%. RF SURFSTIJLT+(6PTE5MLTIK2@U

!+() Modi"y #rogress!8ava so that it does not share #odels, but


instead uses a listener to connect the slider and %rogress bar. RF SURFSTIJLT+(6PTE5MLTIK2MU

!+!) Eollow the instructions in the section titled !Packaging an


a%%let into a J65 "ile$ to %lace TicTacToe!8ava into a J65 "ile. +reate an (TMD %age with the *#essy, co#%licated, version o" the a%%let tag, and #odi"y it to use the archive tag so as to use the J65 "ile. *(int= start with the (TMD %age "or TicTacToe!8ava that co#es with this book s source'code distribution., RFSURF STIJLT+(6PTE5MLTIK2KU

!+*) +reate an a%%letFa%%lication using -onsole. This should have


three sliders, one each "or the red, green, and blue values in 8ava! a(t!-olor. The rest o" the "or# should be a J#anel that dis%lays the color deter#ined by the three sliders. 6lso include non' editable te&t "ields that show the current 58B values. RFSURF STIJLT+(6PTE5MLTIK2LU

!++) In the (TMD docu#entation "or 8ava4!s(ing, look u% the


J-olor-hooser. :rite a %rogra# with a button that brings u%
the color chooser as a dialog. RFSURFSTIJLT+(6PTE5MLTIK2?U

!+,) 6l#ost every Swing co#%onent is derived "ro# -omponent,


which has a set-*rsorA B #ethod. Dook this u% in the Java (TMD docu#entation. +reate an a%%let and change the cursor to one o" the stock cursors in the -*rsor class. RFSURF STIJLT+(6PTE5MLTIK2HU

:54

!+-) Starting with )ho(A''+isteners!8ava, create a %rogra#


with the "ull "unctionality o" )ho(1etho's-lean!8ava "ro# +ha%ter MK. RFSU

Cha ter 13! Creating Bindo,s & "

lets

:55

(+: Multi.le #hreads


RFSTIJLT+(6PTE5M?TI@U)b0ects %rovide a way to divide a %rogra# into inde%endent sections. )"ten, you also need to turn a %rogra# into se%arate, inde%endently running subtasks.
Each o" these inde%endent subtasks is called a thread, and you %rogra# as i" each thread runs by itsel" and has the +P4 to itsel". So#e underlying #echanis# is actually dividing u% the +P4 ti#e "or you, but in general, you don t have to think about it, which #akes %rogra##ing with #ulti%le threads a #uch easier task. RFSURFSTIJLT+(6PTE5M?TIMU 6 rocess is a sel"'contained running %rogra# with its own address s%ace. 6 multitasking o%erating syste# is ca%able o" running #ore than one %rocess *%rogra#, at a ti#e, while #aking it look like each one is chugging along on its own, by %eriodically %roviding +P4 cycles to each %rocess. 6 thread is a single seAuential "low o" control within a %rocess. 6 single %rocess can thus have #ulti%le concurrently e&ecuting threads. RF SURFSTIJLT+(6PTE5M?TIKU There are #any %ossible uses "or #ultithreading, but in general, you ll have so#e %art o" your %rogra# tied to a %articular event or resource, and you don t want to hang u% the rest o" your %rogra# because o" that. So you create a thread associated with that event or resource and let it run inde%endently o" the #ain %rogra#. 6 good e&a#%le is a !Auit$ button9 you don t want to be "orced to %oll the Auit button in every %iece o" code you write in your %rogra# and yet you want the Auit button to be res%onsive, as i" you ,ere checking it regularly. In "act, one o" the #ost i##ediately co#%elling reasons "or #ultithreading is to %roduce a res%onsive user inter"ace. RFSURFSTIJLT+(6PTE5M?TILU

:57

$es.onsive user interfaces


6s a starting %oint, consider a %rogra# that %er"or#s so#e +P4' intensive o%eration and thus ends u% ignoring user in%ut and being unres%onsive. This one, a co#bined a%%letFa%%lication, will si#%ly dis%lay the result o" a running counter=

//3 c(I3Counter(.Hava // 0 non-res"onsive user interface. // Pa""let co!e?Counter( :i!th?)'' height?(''Q // P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.event.B< i#"ort Hava.a:t.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Counter( e6ten!s J0""let @ "rivate int count ? '< "rivate JButton start ? ne: JButton-8%tart8., onGff ? ne: JButton-8Toggle8.< "rivate JTe6tLiel! t ? ne: JTe6tLiel!-('.< "rivate boolean runLlag ? true< "ublic voi! init-. @ Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< c".a!!-t.< start.a!!0ctionListener-ne: %tartL-..< c".a!!-start.< onGff.a!!0ctionListener-ne: GnGffL-..< c".a!!-onGff.< A "ublic voi! go-. @ :hile -true. @ try @ Threa!.slee"-(''.< A catch-$nterru"te!E6ce"tion e. @ %yste#.err."rintln-8$nterru"te!8.<

Cha ter 14! Multi le Threads

:58

A if -runLlag. t.setTe6t-$nteger.to%tring-countKK..< A A class %tartL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ go-.< A A class GnGffL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ runLlag ? 4runLlag< A A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Counter(-., )'', (''.< A A ///3>
6t this %oint, the Swing and a%%let code should be reasonably "a#iliar "ro# +ha%ter ML. The goA B #ethod is where the %rogra# stays busy= it %uts the current value o" co*nt into the JTe4tFiel' t, then incre#ents co*nt. RFSURFSTIJLT+(6PTE5M?TI?U Part o" the in"inite loo% inside goA B is to call sleepA B. sleepA B #ust be associated with a Threa' ob0ect, and it turns out that every a%%lication has some thread associated with it. *Indeed, Java is based on threads and there are always so#e running along with your a%%lication., So regardless o" whether you re e&%licitly using threads, you can %roduce the current thread used by your %rogra# with Threa' and the static sleepA B #ethod. RFSURFSTIJLT+(6PTE5M?TIHU Cote that sleepA B can throw an Interr*pte'&4ception, although throwing such an e&ce%tion is considered a hostile way to break "ro# a thread and should be discouraged. *)nce again, e&ce%tions are "or e&ce%tional conditions, not nor#al "low o" control., Interru%ting a slee%ing thread is included to su%%ort a "uture language "eature. RFSURF STIJLT+(6PTE5M?TI3U

:5:

:hen the start button is %ressed, goA B is invoked. )n e&a#ining goA B, you #ight naively think *as I did, that it should allow #ultithreading because it goes to slee%. That is, while the #ethod is aslee%, it see#s like the +P4 could be busy #onitoring other button %resses. But it turns out that the real %roble# is that goA B never returns, since it s in an in"inite loo%, and this #eans that action#erforme'A B never returns. Since you re stuck inside action#erforme'A B "or the "irst key%ress, the %rogra# can t handle any other events. *To get out, you #ust so#ehow kill the %rocess; the easiest way to do this is to %ress +ontrol'+ in the console window, i" you started it "ro# the console. I" you start it via the browser, you have to kill the browser window., RFSURF STIJLT+(6PTE5M?TIGU The basic %roble# here is that goA B needs to continue %er"or#ing its o%erations, and at the sa#e ti#e it needs to return so that action#erforme'A B can co#%lete and the user inter"ace can continue res%onding to the user. But in a conventional #ethod like goA B it cannot continue and at the sa#e ti#e return control to the rest o" the %rogra#. This sounds like an i#%ossible thing to acco#%lish, as i" the +P4 #ust be in two %laces at once, but this is %recisely the illusion that threading %rovides. RFSURFSTIJLT+(6PTE5M?TIIU The thread #odel *and its %rogra##ing su%%ort in Java, is a %rogra##ing convenience to si#%li"y 0uggling several o%erations at the sa#e ti#e within a single %rogra#. :ith threads, the +P4 will %o% around and give each thread so#e o" its ti#e. Each thread has the consciousness o" constantly having the +P4 to itsel", but the +P4 s ti#e is actually sliced between all the threads. The e&ce%tion to this is i" your %rogra# is running on #ulti%le +P4s. But one o" the great things about threading is that you are abstracted away "ro# this layer, so your code does not need to know whether it is actually running on a single +P4 or #any. Thus, threads are a way to create trans%arently scalable %rogra#s. RFSURFSTIJLT+(6PTE5M?TI2U Threading reduces co#%uting e""iciency so#ewhat, but the net i#%rove#ent in %rogra# design, resource balancing, and user convenience is o"ten Auite valuable. )" course, i" you have #ore than one +P4, then the o%erating syste# can dedicate each +P4 to a set o" threads or even a single thread and the whole %rogra# can run #uch "aster.

Cha ter 14! Multi le Threads

:5;

Multitasking and #ultithreading tend to be the #ost reasonable ways to utili1e #ulti%rocessor syste#s. RFSURFSTIJLT+(6PTE5M?TIM@U

Inheriting from &hread


The si#%lest way to create a thread is to inherit "ro# class Threa', which has all the wiring necessary to create and run threads. The #ost i#%ortant #ethod "or Threa' is r*nA B, which you #ust override to #ake the thread do your bidding. Thus, r*nA B is the code that will be e&ecuted !si#ultaneously$ with the other threads in a %rogra#. RFSURF STIJLT+(6PTE5M?TIMMU The "ollowing e&a#%le creates any nu#ber o" threads that it kee%s track o" by assigning each thread a uniAue nu#ber, generated with a static variable. The Threa' s r*nA B #ethod is overridden to count down each ti#e it %asses through its loo% and to "inish when the count is 1ero *at the %oint when r*nA B returns, the thread is ter#inated,.

//3 c(I3%i#"leThrea!.Hava // Wery si#"le Threa!ing e6a#"le. "ublic class %i#"leThrea! e6ten!s Threa! @ "rivate int countDo:n ? ,< "rivate static int threa!Count ? '< "rivate int threa!&u#ber ? KKthrea!Count< "ublic %i#"leThrea!-. @ %yste#.out."rintln-8Jaking 8 K threa!&u#ber.< A "ublic voi! run-. @ :hile-true. @ %yste#.out."rintln-8Threa! 8 K threa!&u#ber K 8-8 K countDo:n K 8.8.< if---countDo:n ?? '. return< A A "ublic static voi! #ain-%tringNO args. @ for-int i ? '< i P ,< iKK. ne: %i#"leThrea!-..start-.< %yste#.out."rintln-80ll Threa!s %tarte!8.< A

:7=

A ///3>
6 r*nA B #ethod virtually always has so#e kind o" loo% that continues until the thread is no longer necessary, so you #ust establish the condition on which to break out o" this loo% *or, in the case above, si#%ly ret*rn "ro# r*nA B,. )"ten, r*nA B is cast in the "or# o" an in"inite loo%, which #eans that, barring so#e e&ternal "actor that causes r*nA B to ter#inate, it will continue "orever. RFSURFSTIJLT+(6PTE5M?TIMKU In mainA B you can see a nu#ber o" threads being created and run. The startA B #ethod in the Threa' class %er"or#s s%ecial initiali1ation "or the thread and then calls r*nA B. So the ste%s are= the constructor is called to build the ob0ect, then startA B con"igures the thread and calls r*nA B. I" you don t call startA B *which you can do in the constructor, i" that s a%%ro%riate, the thread will never be started. RFSURF STIJLT+(6PTE5M?TIMLU The out%ut "or one run o" this %rogra# *it will be di""erent "ro# one run to another, is=

Jaking ( Jaking Jaking ) Jaking I Jaking , Threa! (-,. Threa! (-I. Threa! (-). Threa! (- . Threa! -,. Threa! -I. Threa! -). Threa! - . Threa! -(. Threa! (-(. 0ll Threa!s %tarte! Threa! )-,. Threa! I-,. Threa! I-I. Threa! I-). Threa! I- .

Cha ter 14! Multi le Threads

:71

Threa! Threa! Threa! Threa! Threa! Threa! Threa! Threa! Threa! Threa!

I-(. ,-,. ,-I. ,-). ,- . ,-(. )-I. )-). )- . )-(.

/ou ll notice that nowhere in this e&a#%le is sleepA B called, and yet the out%ut indicates that each thread gets a %ortion o" the +P4 s ti#e in which to e&ecute. This shows that sleepA B, while it relies on the e&istence o" a thread in order to e&ecute, is not involved with either enabling or disabling threading. It s si#%ly another #ethod. RFSURF STIJLT+(6PTE5M?TIM?U /ou can also see that the threads are not run in the order that they re created. In "act, the order that the +P4 attends to an e&isting set o" threads is indeter#inate, unless you go in and ad0ust the %riorities using Threa' s set#riorityA B #ethod. RFSURFSTIJLT+(6PTE5M?TIMHU :hen mainA B creates the Threa' ob0ects it isn t ca%turing the re"erences "or any o" the#. 6n ordinary ob0ect would be "air ga#e "or garbage collection, but not a Threa'. Each Threa' !registers$ itsel" so there is actually a re"erence to it so#e%lace and the garbage collector can t clean it u%. RFSURFSTIJLT+(6PTE5M?TIM3U

#hreading for a res.onsive interface


Cow it s %ossible to solve the %roble# in -o*nter>!8ava with a thread. The trick is to %lace the subtask9that is, the loo% that s inside goA B9 inside the r*nA B #ethod o" a thread. :hen the user %resses the start button, the thread is started, but then the creation o" the thread co#%letes, so even though the thread is running, the #ain 0ob o" the %rogra# *watching "or and res%onding to user'inter"ace events, can continue. (ere s the solution=

:72

//3 c(I3Counter .Hava // 0 res"onsive user interface :ith threa!s. // Pa""let co!e?Counter :i!th?)'' height?(''Q // P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Counter e6ten!s J0""let @ "rivate class %e"arate%ubTask e6ten!s Threa! @ "rivate int count ? '< "rivate boolean runLlag ? true< %e"arate%ubTask-. @ su"er.start-.< A voi! invertLlag-. @ runLlag ? 4runLlag< A "ublic voi! run-. @ :hile -true. @ try @ slee"-(''.< A catch-$nterru"te!E6ce"tion e. @ %yste#.err."rintln-8$nterru"te!8.< A if-runLlag. t.setTe6t-$nteger.to%tring-countKK..< A A A "rivate %e"arate%ubTask s" ? null< "rivate JTe6tLiel! t ? ne: JTe6tLiel!-('.< "rivate JButton start ? ne: JButton-8%tart8., onGff ? ne: JButton-8Toggle8.< class %tartL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ if-s" ?? null. s" ? ne: %e"arate%ubTask-.< A A class GnGffL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ if-s" 4? null.

Cha ter 14! Multi le Threads

:73

s".invertLlag-.< A A "ublic voi! init-. @ Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< c".a!!-t.< start.a!!0ctionListener-ne: %tartL-..< c".a!!-start.< onGff.a!!0ctionListener-ne: GnGffL-..< c".a!!-onGff.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Counter -., )'', (''.< A A ///3> -o*nterI is a straight"orward %rogra#, whose only 0ob is to set u% and #aintain the user inter"ace. But now, when the user %resses the start
button, the event'handling code does not call a #ethod. Instead a thread o" class )eparate)*bTask is created, and then the -o*nterI event loo% continues. RFSURFSTIJLT+(6PTE5M?TIMGU The class )eparate)*bTask is a si#%le e&tension o" Threa' with a constructor that runs the thread by calling startA B, and a r*nA B that essentially contains the ! goA B$ code "ro# -o*nter>!8ava. RFSURF STIJLT+(6PTE5M?TIMIU Because )eparate)*bTask is an inner class, it can directly access the JTe4tFiel' t in -o*nterI; you can see this ha%%ening inside r*nA B. The t "ield in the outer class is private since )eparate)*bTask can access it without getting any s%ecial %er#ission9and it s always good to #ake "ields !as private as %ossible$ so they cannot be accidentally changed by "orces outside your class. RFSURFSTIJLT+(6PTE5M?TIM2U :hen you %ress the on.ff button it toggles the r*nFlag inside the )eparate)*bTask ob0ect. That thread *when it looks at the "lag, can then start and sto% itsel". Pressing the on.ff button %roduces an a%%arently instant res%onse. )" course, the res%onse isn t really instant, not like that o" a syste# that s driven by interru%ts. The counter sto%s

:74

only when the thread has the +P4 and notices that the "lag has changed. RFSURFSTIJLT+(6PTE5M?TIK@U /ou can see that the inner class )eparate)*bTask is private, which #eans that its "ields and #ethods can be given de"ault access *e&ce%t "or r*nA B, which #ust be p*blic since it is p*blic in the base class,. The private inner class is not accessible to anyone but -o*nterI, and the two classes are tightly cou%led. 6nyti#e you notice classes that a%%ear to have high cou%ling with each other, consider the coding and #aintenance i#%rove#ents you #ight get by using inner classes. RFSURF STIJLT+(6PTE5M?TIKMU

Combining the thread with the main class


In the e&a#%le above you can see that the thread class is se%arate "ro# the %rogra# s #ain class. This #akes a lot o" sense and is relatively easy to understand. There is, however, an alternate "or# that you will o"ten see used that is not so clear but is usually #ore concise *which %robably accounts "or its %o%ularity,. This "or# co#bines the #ain %rogra# class with the thread class by #aking the #ain %rogra# class a thread. Since "or a 84I %rogra# the #ain %rogra# class #ust be inherited "ro# either Frame or Applet, an inter"ace #ust be used to %aste on the additional "unctionality. This inter"ace is called $*nnable, and it contains the sa#e basic #ethod that Threa' does. In "act, Threa' also i#%le#ents $*nnable, which s%eci"ies only that there be a r*nA B #ethod. RFSURF STIJLT+(6PTE5M?TIKKU The use o" the co#bined %rogra#Fthread is not Auite so obvious. :hen you start the %rogra#, you create an ob0ect that s $*nnable, but you don t start the thread. This #ust be done e&%licitly. /ou can see this in the "ollowing %rogra#, which re%roduces the "unctionality o" -o*nterI=

//3 c(I3Counter).Hava // Ysing the 5unnable interface to turn the // #ain class into a threa!. // Pa""let co!e?Counter) :i!th?)'' height?(''Q // P/a""letQ i#"ort Hava6.s:ing.B<

Cha ter 14! Multi le Threads

:75

i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Counter) e6ten!s J0""let i#"le#ents 5unnable @ "rivate int count ? '< "rivate boolean runLlag ? true< "rivate Threa! selfThrea! ? null< "rivate JButton start ? ne: JButton-8%tart8., onGff ? ne: JButton-8Toggle8.< "rivate JTe6tLiel! t ? ne: JTe6tLiel!-('.< "ublic voi! run-. @ :hile -true. @ try @ selfThrea!.slee"-(''.< A catch-$nterru"te!E6ce"tion e. @ %yste#.err."rintln-8$nterru"te!8.< A if-runLlag. t.setTe6t-$nteger.to%tring-countKK..< A A class %tartL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ if-selfThrea! ?? null. @ selfThrea! ? ne: Threa!-Counter).this.< selfThrea!.start-.< A A A class GnGffL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ runLlag ? 4runLlag< A A "ublic voi! init-. @ Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< c".a!!-t.<

:77

start.a!!0ctionListener-ne: %tartL-..< c".a!!-start.< onGff.a!!0ctionListener-ne: GnGffL-..< c".a!!-onGff.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Counter)-., )'', (''.< A A ///3>
Cow the r*nA B is inside the class, but it s still dor#ant a"ter initA B co#%letes. :hen you %ress the start button, the thread is created *i" it doesn t already e&ist, in the so#ewhat obscure e&%ression= RFSURF STIJLT+(6PTE5M?TIKLU

ne: Threa!-Counter).this.<
:hen so#ething has a $*nnable inter"ace, it si#%ly #eans that it has a r*nA B #ethod, but there s nothing s%ecial about that9it doesn t %roduce any innate threading abilities, like those o" a class inherited "ro# Threa'. So to %roduce a thread "ro# a $*nnable ob0ect, you #ust create a se%arate Threa' ob0ect as shown above, handing the $*nnable ob0ect to the s%ecial Threa' constructor. /ou can then call startA B "or that thread= RFSURFSTIJLT+(6PTE5M?TIK?U

selfThrea!.start-.<
This %er"or#s the usual initiali1ation and then calls r*nA B. RFSURF STIJLT+(6PTE5M?TIKHU The convenient as%ect about the $*nnable interface is that everything belongs to the sa#e class. I" you need to access so#ething, you si#%ly do it without going through a se%arate ob0ect. (owever, as you saw in the %revious e&a#%le, this access is 0ust as easy using an inner class @. RFSURF STIJLT+(6PTE5M?TIK3U

@ $*nnable was in Java M.@, while inner classes were not introduced until Java M.M, which

#ay %artially account "or the e&istence o" $*nnable. 6lso, traditional #ultithreading architectures "ocused on a "unction to be run rather than an ob0ect. My %re"erence is always to inherit "ro# Threa' i" I can; it see#s cleaner and #ore "le&ible to #e.

Cha ter 14! Multi le Threads

:78

Making man: threads


+onsider the creation o" #any di""erent threads. /ou can t do this with the %revious e&a#%le, so you #ust go back to having se%arate classes inherited "ro# Threa' to enca%sulate the r*nA B. But this is a #ore general solution and easier to understand, so while the %revious e&a#%le shows a coding style you ll o"ten see, I can t reco##end it "or #ost cases because it s 0ust a little bit #ore con"using and less "le&ible. RFSURF STIJLT+(6PTE5M?TIKGU The "ollowing e&a#%le re%eats the "or# o" the e&a#%les above with counters and toggle buttons. But now all the in"or#ation "or a %articular counter, including the button and te&t "ield, is inside its own ob0ect that is inherited "ro# Threa'. 6ll the "ields in Ticker are private, which #eans that the Ticker i#%le#entation can be changed at will, including the Auantity and ty%e o" data co#%onents to acAuire and dis%lay in"or#ation. :hen a Ticker ob0ect is created, the constructor adds its visual co#%onents to the content %ane o" the outer ob0ect=

//3 c(I3CounterI.Hava // By kee"ing your threa! as a !istinct class, // you can have as #any threa!s as you :ant. // Pa""let co!e?CounterI :i!th? '' height?+''Q // P"ara# na#e?siUe value?8( 8QP/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class CounterI e6ten!s J0""let @ "rivate JButton start ? ne: JButton-8%tart8.< "rivate boolean starte! ? false< "rivate TickerNO s< "rivate boolean is0""let ? true< "rivate int siUe ? ( < class Ticker e6ten!s Threa! @ "rivate JButton b ? ne: JButton-8Toggle8.< "rivate JTe6tLiel! t ? ne: JTe6tLiel!-('.< "rivate int count ? '< "rivate boolean runLlag ? true<

:7:

"ublic Ticker-. @ b.a!!0ctionListener-ne: ToggleL-..< JPanel " ? ne: JPanel-.< ".a!!-t.< ".a!!-b.< // Calls J0""let.getContentPane-..a!!-.3 getContentPane-..a!!-".< A class ToggleL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ runLlag ? 4runLlag< A A "ublic voi! run-. @ :hile -true. @ if -runLlag. t.setTe6t-$nteger.to%tring-countKK..< try @ slee"-(''.< A catch-$nterru"te!E6ce"tion e. @ %yste#.err."rintln-8$nterru"te!8.< A A A A class %tartL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ if-4starte!. @ starte! ? true< for -int i ? '< i P s.length< iKK. sNiO.start-.< A A A "ublic voi! init-. @ Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< // aet "ara#eter 8siUe8 fro# \eb "age3 if -is0""let. @ %tring sU ? getPara#eter-8siUe8.< if-sU 4? null.

Cha ter 14! Multi le Threads

:7;

siUe ? $nteger."arse$nt-sU.< A s ? ne: TickerNsiUeO< for -int i ? '< i P s.length< iKK. sNiO ? ne: Ticker-.< start.a!!0ctionListener-ne: %tartL-..< c".a!!-start.< A "ublic static voi! #ain-%tringNO args. @ CounterI a""let ? ne: CounterI-.< // This isn2t an a""let, so set the flag an! // "ro!uce the "ara#eter values fro# args3 a""let.is0""let ? false< if-args.length 4? '. a""let.siUe ? $nteger."arse$nt-argsN'O.< Console.run-a""let, '', a""let.siUe B ,'.< A A ///3> Ticker contains not only its threading eAui%#ent but also the way to control and dis%lay the thread. /ou can create as #any threads as you want without e&%licitly creating the windowing co#%onents. RFSURF STIJLT+(6PTE5M?TIKIU
In -o*nterQ there s an array o" Ticker ob0ects called s. Eor #a&i#u# "le&ibility, the si1e o" this array is initiali1ed by reaching out into the :eb %age using a%%let %ara#eters. (ere s what the si1e %ara#eter looks like on the %age, e#bedded inside the a%%let tag=

P"ara# na#e?siUe value?8 '8Q


The param, name, and val*e are all (TMD keywords. name is what you ll be re"erring to in your %rogra#, and val*e can be any string, not 0ust so#ething that resolves to a nu#ber. RFSURF STIJLT+(6PTE5M?TIK2U /ou ll notice that the deter#ination o" the si1e o" the array s is done inside initA B, and not as %art o" an inline de"inition o" s. That is, you cannot say as %art o" the class de"inition *outside o" any #ethods,=

int siUe ? $nteger."arse$nt-getPara#eter-8siUe8..< TickerNO s ? ne: TickerNsiUeO<

:8=

/ou can co#%ile this, but you ll get a strange !null'%ointer e&ce%tion$ at run'ti#e. It works "ine i" you #ove the get#arameterA B initiali1ation inside o" initA B. The a%%let "ra#ework %er"or#s the necessary startu% to grab the %ara#eters be"ore entering initA B. RFSURF STIJLT+(6PTE5M?TIL@U In addition, this code is set u% to be either an a%%let or an a%%lication. :hen it s an a%%lication the si7e argu#ent is e&tracted "ro# the co##and line *or a de"ault value is %rovided,. RFSURF STIJLT+(6PTE5M?TILMU )nce the si1e o" the array is established, new Ticker ob0ects are created; as %art o" the Ticker constructor the button and te&t "ield "or each Ticker is added to the a%%let. RFSURFSTIJLT+(6PTE5M?TILKU Pressing the start button #eans loo%ing through the entire array o" Tickers and calling startA B "or each one. 5e#e#ber, startA B %er"or#s necessary thread initiali1ation and then calls r*nA B "or that thread. RF SURFSTIJLT+(6PTE5M?TILLU The Toggle+ listener si#%ly inverts the "lag in Ticker and when the associated thread ne&t takes note it can react accordingly. RFSURF STIJLT+(6PTE5M?TIL?U )ne value o" this e&a#%le is that it allows you to easily create large sets o" inde%endent subtasks and to #onitor their behavior. In this case, you ll see that as the nu#ber o" subtasks gets larger, your #achine will %robably show #ore divergence in the dis%layed nu#bers because o" the way that the threads are served. RFSURFSTIJLT+(6PTE5M?TILHU /ou can also e&%eri#ent to discover how i#%ortant the sleepA>DDB is inside Ticker!r*nA B. I" you re#ove the sleepA B, things will work "ine until you %ress a toggle button. Then that %articular thread has a "alse r*nFlag and the r*nA B is 0ust tied u% in a tight in"inite loo%, which a%%ears di""icult to break during #ultithreading, so the res%onsiveness and s%eed o" the %rogra# really bogs down. RFSURF STIJLT+(6PTE5M?TIL3U

Cha ter 14! Multi le Threads

:81

Daemon threads
6 !dae#on$ thread is one that is su%%osed to %rovide a general service in the background as long as the %rogra# is running, but is not %art o" the essence o" the %rogra#. Thus, when all o" the non'dae#on threads co#%lete, the %rogra# is ter#inated. +onversely, i" there are any non' dae#on threads still running, the %rogra# doesn t ter#inate. *There is, "or instance, a thread that runs mainA B., RFSURF STIJLT+(6PTE5M?TILGU /ou can "ind out i" a thread is a dae#on by calling is aemonA B, and you can turn the !dae#onhood$ o" a thread on and o"" with set aemonA B. I" a thread is a dae#on, then any threads it creates will auto#atically be dae#ons. RFSURFSTIJLT+(6PTE5M?TILIU The "ollowing e&a#%le de#onstrates dae#on threads=

//3 c(I3Dae#ons.Hava // Dae#onic behavior. i#"ort Hava.io.B< class Dae#on e6ten!s Threa! @ "rivate static final int %$TE ? ('< "rivate Threa!NO t ? ne: Threa!N%$TEO< "ublic Dae#on-. @ setDae#on-true.< start-.< A "ublic voi! run-. @ for-int i ? '< i P %$TE< iKK. tNiO ? ne: Dae#on%"a:n-i.< for-int i ? '< i P %$TE< iKK. %yste#.out."rintln8tN8 K i K 8O.isDae#on-. ? 8 K tNiO.isDae#on-..< :hile-true. yiel!-.< A A class Dae#on%"a:n e6ten!s Threa! @

:82

"ublic Dae#on%"a:n-int i. @ %yste#.out."rintln8Dae#on%"a:n 8 K i K 8 starte!8.< start-.< A "ublic voi! run-. @ :hile-true. yiel!-.< A A "ublic class Dae#ons @ "ublic static voi! #ain-%tringNO args. thro:s $GE6ce"tion @ Threa! ! ? ne: Dae#on-.< %yste#.out."rintln8!.isDae#on-. ? 8 K !.isDae#on-..< // 0llo: the !ae#on threa!s to // finish their startu" "rocesses3 %yste#.out."rintln-8Press any key8.< %yste#.in.rea!-.< A A ///3>
The aemon thread sets its dae#on "lag to !true$ and then s%awns a bunch o" other threads to show that they are also dae#ons. Then it goes into an in"inite loo% that calls yiel'A B to give u% control to the other %rocesses. In an earlier version o" this %rogra#, the in"inite loo%s would incre#ent int counters, but this see#ed to bring the whole %rogra# to a sto%. 4sing yiel'A B #akes the %rogra# Auite %e%%y. RFSURF STIJLT+(6PTE5M?TIL2U There s nothing to kee% the %rogra# "ro# ter#inating once mainA B "inishes its 0ob, since there are nothing but dae#on threads running. So that you can see the results o" starting all the dae#on threads, )ystem! in is set u% to read so the %rogra# waits "or a key%ress be"ore ter#inating. :ithout this you see only so#e o" the results "ro# the creation o" the dae#on threads. *Try re%lacing the rea'A B code with sleepA B calls o" various lengths to see this behavior., RFSURF STIJLT+(6PTE5M?TI?@U

Cha ter 14! Multi le Threads

:83

1haring limited resources


/ou can think o" a single'threaded %rogra# as one lonely entity #oving around through your %roble# s%ace and doing one thing at a ti#e. Because there s only one entity, you never have to think about the %roble# o" two entities trying to use the sa#e resource at the sa#e ti#e, like two %eo%le trying to %ark in the sa#e s%ace, walk through a door at the sa#e ti#e, or even talk at the sa#e ti#e. RFSURF STIJLT+(6PTE5M?TI?MU :ith #ultithreading, things aren t lonely any#ore, but you now have the %ossibility o" two or #ore threads trying to use the sa#e li#ited resource at once. +olliding over a resource #ust be %revented or else you ll have two threads trying to access the sa#e bank account at the sa#e ti#e, %rint to the sa#e %rinter, or ad0ust the sa#e valve, etc. RFSURF STIJLT+(6PTE5M?TI?KU

Im.ro.erl: accessing resources


+onsider a variation on the counters that have been used so "ar in this cha%ter. In the "ollowing e&a#%le, each thread contains two counters that are incre#ented and dis%layed inside r*nA B. In addition, there s another thread o" class 0atcher that is watching the counters to see i" they re always eAuivalent. This see#s like a needless activity, since looking at the code it a%%ears obvious that the counters will always be the sa#e. But that s where the sur%rise co#es in. (ere s the "irst version o" the %rogra#=

//3 c(I3%haring(.Hava // Proble#s :ith resource sharing :hile threa!ing. // Pa""let co!e?%haring( :i!th?),' height?,''Q // P"ara# na#e?siUe value?8( 8Q // P"ara# na#e?:atchers value?8(,8Q // P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B<

:84

i#"ort Hava.a:t.event.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class %haring( e6ten!s J0""let @ "rivate static int accessCount ? '< "rivate static JTe6tLiel! aCount ? ne: JTe6tLiel!-8'8, *.< "ublic static voi! incre#ent0ccess-. @ accessCountKK< aCount.setTe6t-$nteger.to%tring-accessCount..< A "rivate JButton start ? ne: JButton-8%tart8., :atcher ? ne: JButton-8\atch8.< "rivate boolean is0""let ? true< "rivate int nu#Counters ? ( < "rivate int nu#\atchers ? (,< "rivate T:oCounterNO s< class T:oCounter e6ten!s Threa! @ "rivate boolean starte! ? false< "rivate JTe6tLiel! t( ? ne: JTe6tLiel!-,., t ? ne: JTe6tLiel!-,.< "rivate JLabel l ? ne: JLabel-8count( ?? count 8.< "rivate int count( ? ', count ? '< // 0!! the !is"lay co#"onents as a "anel3 "ublic T:oCounter-. @ JPanel " ? ne: JPanel-.< ".a!!-t(.< ".a!!-t .< ".a!!-l.< getContentPane-..a!!-".< A "ublic voi! start-. @ if-4starte!. @ starte! ? true< su"er.start-.< A A "ublic voi! run-. @

Cha ter 14! Multi le Threads

:85

:hile -true. @ t(.setTe6t-$nteger.to%tring-count(KK..< t .setTe6t-$nteger.to%tring-count KK..< try @ slee"-,''.< A catch-$nterru"te!E6ce"tion e. @ %yste#.err."rintln-8$nterru"te!8.< A A A "ublic voi! synchTest-. @ incre#ent0ccess-.< if-count( 4? count . l.setTe6t-8Ynsynche!8.< A A class \atcher e6ten!s Threa! @ "ublic \atcher-. @ su"er.start-.< A "ublic voi! run-. @ :hile-true. @ for-int i ? '< i P s.length< iKK. sNiO.synchTest-.< try @ slee"-,''.< A catch-$nterru"te!E6ce"tion e. @ %yste#.err."rintln-8$nterru"te!8.< A A A A class %tartL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ for-int i ? '< i P s.length< iKK. sNiO.start-.< A A class \atcherL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ for-int i ? '< i P nu#\atchers< iKK. ne: \atcher-.< A

:87

A "ublic voi! init-. @ if-is0""let. @ %tring counters ? getPara#eter-8siUe8.< if-counters 4? null. nu#Counters ? $nteger."arse$nt-counters.< %tring :atchers ? getPara#eter-8:atchers8.< if-:atchers 4? null. nu#\atchers ? $nteger."arse$nt-:atchers.< A s ? ne: T:oCounterNnu#CountersO< Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< for-int i ? '< i P s.length< iKK. sNiO ? ne: T:oCounter-.< JPanel " ? ne: JPanel-.< start.a!!0ctionListener-ne: %tartL-..< ".a!!-start.< :atcher.a!!0ctionListener-ne: \atcherL-..< ".a!!-:atcher.< ".a!!-ne: JLabel-80ccess Count8..< ".a!!-aCount.< c".a!!-".< A "ublic static voi! #ain-%tringNO args. @ %haring( a""let ? ne: %haring(-.< // This isn2t an a""let, so set the flag an! // "ro!uce the "ara#eter values fro# args3 a""let.is0""let ? false< a""let.nu#Counters ? -args.length ?? ' [ ( 3 $nteger."arse$nt-argsN'O..< a""let.nu#\atchers ? -args.length P [ (, 3 $nteger."arse$nt-argsN(O..< Console.run-a""let, ),', a""let.nu#Counters B ,'.< A A ///3>

Cha ter 14! Multi le Threads

:88

6s be"ore, each counter contains its own dis%lay co#%onents= two te&t "ields and a label that initially indicates that the counts are eAuivalent. These co#%onents are added to the content %ane o" the outer class ob0ect in the T(o-o*nter constructor. RFSURFSTIJLT+(6PTE5M?TI?LU Because a T(o-o*nter thread is started via a key%ress by the user, it s %ossible that startA B could be called #ore than once. It s illegal "or Threa'!startA B to be called #ore than once "or a thread *an e&ce%tion is thrown,. /ou can see the #achinery to %revent this in the starte' "lag and the overridden startA B #ethod. RFSURFSTIJLT+(6PTE5M?TI??U In r*nA B, co*nt> and co*ntI are incre#ented and dis%layed in a #anner that would see# to kee% the# identical. Then sleepA B is called; without this call the %rogra# balks because it beco#es hard "or the +P4 to swa% tasks. RFSURFSTIJLT+(6PTE5M?TI?HU The synchTestA B #ethod %er"or#s the a%%arently useless activity o" checking to see i" co*nt> is eAuivalent to co*ntI; i" they are not eAuivalent it sets the label to !4nsynched$ to indicate this. But "irst, it calls a static #e#ber o" the class )haring> that incre#ents and dis%lays an access counter to show how #any ti#es this check has occurred success"ully. *The reason "or this will beco#e a%%arent in later variations o" this e&a#%le., RFSURFSTIJLT+(6PTE5M?TI?3U The 0atcher class is a thread whose 0ob is to call synchTestA B "or all o" the T(o-o*nter ob0ects that are active. It does this by ste%%ing through the array that s ke%t in the )haring> ob0ect. /ou can think o" the 0atcher as constantly %eeking over the shoulders o" the T(o-o*nter ob0ects. RFSURFSTIJLT+(6PTE5M?TI?GU

)haring> contains an array o" T(o-o*nter ob0ects that it initiali1es in initA B and starts as threads when you %ress the !start$ button. Dater,
when you %ress the !:atch$ button, one or #ore watchers are created and "reed u%on the unsus%ecting T(o-o*nter threads. RFSURF STIJLT+(6PTE5M?TI?IU Cote that to run this as an a%%let in a browser, your a%%let tag will need to contain the lines=

P"ara# na#e?siUe value?8 '8Q P"ara# na#e?:atchers value?8(8Q

:8:

/ou can e&%eri#ent by changing the width, height, and %ara#eters to suit your tastes. By changing the si7e and (atchers you ll change the behavior o" the %rogra#. This %rogra# is set u% to run as a stand'alone a%%lication by %ulling the argu#ents "ro# the co##and line *or %roviding de"aults,. RFSURFSTIJLT+(6PTE5M?TI?2U (ere s the sur%rising %art. In T(o-o*nter!r*nA B, the in"inite loo% is 0ust re%eatedly %assing over the ad0acent lines=

t(.setTe6t-$nteger.to%tring-count(KK..< t .setTe6t-$nteger.to%tring-count KK..<


*as well as slee%ing, but that s not i#%ortant here,. :hen you run the %rogra#, however, you ll discover that co*nt> and co*ntI will be observed *by the 0atchers, to be uneAual at ti#es. This is because o" the nature o" threads9they can be sus%ended at any ti#e. So at ti#es, the sus%ension occurs bet,een the e&ecution o" the above two lines, and the 0atcher thread ha%%ens to co#e along and %er"or# the co#%arison at 0ust this #o#ent, thus "inding the two counters to be di""erent. RFSURF STIJLT+(6PTE5M?TIH@U This e&a#%le shows a "unda#ental %roble# with using threads. /ou never know when a thread #ight be run. I#agine sitting at a table with a "ork, about to s%ear the last %iece o" "ood on your %late and as your "ork reaches "or it, the "ood suddenly vanishes *because your thread was sus%ended and another thread ca#e in and stole the "ood,. That s the %roble# that you re dealing with. RFSURFSTIJLT+(6PTE5M?TIHMU So#eti#es you don t care i" a resource is being accessed at the sa#e ti#e you re trying to use it *the "ood is on so#e other %late,. But "or #ultithreading to work, you need so#e way to %revent two threads "ro# accessing the sa#e resource, at least during critical %eriods. RFSURF STIJLT+(6PTE5M?TIHKU Preventing this kind o" collision is si#%ly a #atter o" %utting a lock on a resource when one thread is using it. The "irst thread that accesses a resource locks it, and then the other threads cannot access that resource until it is unlocked, at which ti#e another thread locks and uses it, etc. I" the "ront seat o" the car is the li#ited resource, the child who shouts !7ibs.$ asserts the lock. RFSURFSTIJLT+(6PTE5M?TIHLU

Cha ter 14! Multi le Threads

:8;

>ow "ava shares resources


Java has built'in su%%ort to %revent collisions over one kind o" resource= the #e#ory in an ob0ect. Since you ty%ically #ake the data ele#ents o" a class private and access that #e#ory only through #ethods, you can %revent collisions by #aking a %articular #ethod synchroni7e'. )nly one thread at a ti#e can call a synchroni7e' #ethod "or a %articular ob0ect *although that thread can call #ore than one o" the ob0ect s synchroni1ed #ethods,. (ere are si#%le synchroni7e' #ethods=

synchroniUe! voi! f-. @ /B ... B/ A synchroniUe! voi! g-.@ /B ... B/ A


Each ob0ect contains a single lock *also called a monitor, that is auto#atically %art o" the ob0ect *you don t have to write any s%ecial code,. :hen you call any synchroni7e' #ethod, that ob0ect is locked and no other synchroni7e' #ethod o" that ob0ect can be called until the "irst one "inishes and releases the lock. In the e&a#%le above, i" fA B is called "or an ob0ect, gA B cannot be called "or the sa#e ob0ect until fA B is co#%leted and releases the lock. Thus, there s a single lock that s shared by all the synchroni7e' #ethods o" a %articular ob0ect, and this lock %revents co##on #e#ory "ro# being written by #ore than one #ethod at a ti#e *i.e., #ore than one thread at a ti#e,. RFSURF STIJLT+(6PTE5M?TIH?U There s also a single lock %er class *as %art o" the -lass ob0ect "or the class,, so that synchroni7e' static #ethods can lock each other out "ro# si#ultaneous access o" static data on a class'wide basis. RFSURF STIJLT+(6PTE5M?TIHHU Cote that i" you want to guard so#e other resource "ro# si#ultaneous access by #ulti%le threads, you can do so by "orcing access to that resource through synchroni7e' #ethods. RFSURF STIJLT+(6PTE5M?TIH3U

1:nchroni?ing the counters


6r#ed with this new keyword it a%%ears that the solution is at hand= we ll si#%ly use the synchroni7e' keyword "or the #ethods in

::=

T(o-o*nter. The "ollowing e&a#%le is the sa#e as the %revious one,


with the addition o" the new keyword=

//3 c(I3%haring .Hava // Ysing the synchroniUe! key:or! to "revent // #ulti"le access to a "articular resource. // Pa""let co!e?%haring :i!th?),' height?,''Q // P"ara# na#e?siUe value?8( 8Q // P"ara# na#e?:atchers value?8(,8Q // P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class %haring e6ten!s J0""let @ T:oCounterNO s< "rivate static int accessCount ? '< "rivate static JTe6tLiel! aCount ? ne: JTe6tLiel!-8'8, *.< "ublic static voi! incre#ent0ccess-. @ accessCountKK< aCount.setTe6t-$nteger.to%tring-accessCount..< A "rivate JButton start ? ne: JButton-8%tart8., :atcher ? ne: JButton-8\atch8.< "rivate boolean is0""let ? true< "rivate int nu#Counters ? ( < "rivate int nu#\atchers ? (,< class T:oCounter e6ten!s Threa! @ "rivate boolean starte! ? false< "rivate JTe6tLiel! t( ? ne: JTe6tLiel!-,., t ? ne: JTe6tLiel!-,.< "rivate JLabel l ? ne: JLabel-8count( ?? count 8.< "rivate int count( ? ', count ? '< "ublic T:oCounter-. @ JPanel " ? ne: JPanel-.<

Cha ter 14! Multi le Threads

::1

".a!!-t(.< ".a!!-t .< ".a!!-l.< getContentPane-..a!!-".< A "ublic voi! start-. @ if-4starte!. @ starte! ? true< su"er.start-.< A A "ublic synchroniUe! voi! run-. @ :hile -true. @ t(.setTe6t-$nteger.to%tring-count(KK..< t .setTe6t-$nteger.to%tring-count KK..< try @ slee"-,''.< A catch-$nterru"te!E6ce"tion e. @ %yste#.err."rintln-8$nterru"te!8.< A A A "ublic synchroniUe! voi! synchTest-. @ incre#ent0ccess-.< if-count( 4? count . l.setTe6t-8Ynsynche!8.< A A class \atcher e6ten!s Threa! @ "ublic \atcher-. @ su"er.start-.< A "ublic voi! run-. @ :hile-true. @ for-int i ? '< i P s.length< iKK. sNiO.synchTest-.< try @ slee"-,''.< A catch-$nterru"te!E6ce"tion e. @ %yste#.err."rintln-8$nterru"te!8.< A A

::2

A A class %tartL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ for-int i ? '< i P s.length< iKK. sNiO.start-.< A A class \atcherL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ for-int i ? '< i P nu#\atchers< iKK. ne: \atcher-.< A A "ublic voi! init-. @ if-is0""let. @ %tring counters ? getPara#eter-8siUe8.< if-counters 4? null. nu#Counters ? $nteger."arse$nt-counters.< %tring :atchers ? getPara#eter-8:atchers8.< if-:atchers 4? null. nu#\atchers ? $nteger."arse$nt-:atchers.< A s ? ne: T:oCounterNnu#CountersO< Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< for-int i ? '< i P s.length< iKK. sNiO ? ne: T:oCounter-.< JPanel " ? ne: JPanel-.< start.a!!0ctionListener-ne: %tartL-..< ".a!!-start.< :atcher.a!!0ctionListener-ne: \atcherL-..< ".a!!-:atcher.< ".a!!-ne: Label-80ccess Count8..< ".a!!-aCount.< c".a!!-".< A "ublic static voi! #ain-%tringNO args. @ %haring a""let ? ne: %haring -.< // This isn2t an a""let, so set the flag an! // "ro!uce the "ara#eter values fro# args3

Cha ter 14! Multi le Threads

::3

a""let.is0""let ? false< a""let.nu#Counters ? -args.length ?? ' [ ( 3 $nteger."arse$nt-argsN'O..< a""let.nu#\atchers ? -args.length P [ (, 3 $nteger."arse$nt-argsN(O..< Console.run-a""let, ),', a""let.nu#Counters B ,'.< A A ///3>
/ou ll notice that both r*nA B and synchTestA B are synchroni7e'. I" you synchroni1e only one o" the #ethods, then the other is "ree to ignore the ob0ect lock and can be called with i#%unity. This is an i#%ortant %oint= Every #ethod that accesses a critical shared resource #ust be synchroni7e' or it won t work right. RFSURFSTIJLT+(6PTE5M?TIHGU Cow a new issue arises. The 0atcher can never get a %eek at what s going on because the entire r*nA B #ethod has been synchroni7e', and since r*nA B is always running "or each ob0ect the lock is always tied u% and synchTestA B can never be called. /ou can see this because the access-o*nt never changes. RFSURFSTIJLT+(6PTE5M?TIHIU :hat we d like "or this e&a#%le is a way to isolate only art o" the code inside r*nA B. The section o" code you want to isolate this way is called a critical section and you use the synchroni7e' keyword in a di""erent way to set u% a critical section. Java su%%orts critical sections with the s)nchroni?ed blockE this ti#e synchroni7e' is used to s%eci"y the ob0ect whose lock is being used to synchroni1e the enclosed code= RFSURF STIJLT+(6PTE5M?TIH2U

synchroniUe!-syncGbHect. @ // This co!e can be accesse! // by only one threa! at a ti#e A


Be"ore the synchroni1ed block can be entered, the lock #ust be acAuired on sync.b8ect. I" so#e other thread already has this lock, then the block cannot be entered until the lock is given u%. RFSURF STIJLT+(6PTE5M?TI3@U

::4

The )haringI e&a#%le can be #odi"ied by re#oving the synchroni7e' keyword "ro# the entire r*nA B #ethod and instead %utting a synchroni7e' block around the two critical lines. But what ob0ect should be used as the lockO The one that is already res%ected by synchTestA B, which is the current ob0ect * this,. So the #odi"ied r*nA B looks like this=

"ublic voi! run-. @ :hile -true. @ synchroniUe!-this. @ t(.setTe6t-$nteger.to%tring-count(KK..< t .setTe6t-$nteger.to%tring-count KK..< A try @ slee"-,''.< A catch-$nterru"te!E6ce"tion e. @ %yste#.err."rintln-8$nterru"te!8.< A A A
This is the only change that #ust be #ade to )haringI!8ava, and you ll see that while the two counters are never out o" synch *according to when the 0atcher is allowed to look at the#,, there is still adeAuate access %rovided to the 0atcher during the e&ecution o" r*nA B. RFSURF STIJLT+(6PTE5M?TI3MU )" course, all synchroni1ation de%ends on %rogra##er diligence= every %iece o" code that can access a shared resource #ust be wra%%ed in an a%%ro%riate synchroni1ed block. RFSURFSTIJLT+(6PTE5M?TI3KU

1:nchroni?ed efficienc:
Since having two #ethods write to the sa#e %iece o" data never sounds like a %articularly good idea, it #ight see# to #ake sense "or all #ethods to be auto#atically synchroni7e' and eli#inate the synchroni7e' keyword altogether. *)" course, the e&a#%le with a synchroni7e' r*n A B shows that this wouldn t work either., But it turns out that acAuiring a lock is not a chea% o%eration9it #ulti%lies the cost o" a #ethod call *that is, entering and e&iting "ro# the #ethod, not e&ecuting the body o" the #ethod, by a #ini#u# o" "our ti#es, and could be #uch #ore

Cha ter 14! Multi le Threads

::5

de%ending on your i#%le#entation. So i" you know that a %articular #ethod will not cause contention %roble#s it is e&%edient to leave o"" the synchroni7e' keyword. )n the other hand, leaving o"" the synchroni7e' keyword because you think it is a %er"or#ance bottleneck, and ho%ing that there aren t any collisions is an invitation to disaster. RFSURFSTIJLT+(6PTE5M?TI3LU

"ava;eans revisited
Cow that you understand synchroni1ation, you can take another look at JavaBeans. :henever you create a Bean, you #ust assu#e that it will run in a #ultithreaded environ#ent. This #eans that=

(*6) :henever %ossible, all the p*blic #ethods o" a Bean should be synchroni7e'. )" course, this incurs the synchroni7e' run'
ti#e overhead. I" that s a %roble#, #ethods that will not cause %roble#s in critical sections can be le"t un' synchroni7e', but kee% in #ind that this is not always obvious. Methods that Auali"y tend to be s#all *such as get-ircle)i7eA B in the "ollowing e&a#%le, andFor !ato#ic,$ that is, the #ethod call e&ecutes in such a short a#ount o" code that the ob0ect cannot be changed during e&ecution. Making such #ethods un' synchroni7e' #ight not have a signi"icant e""ect on the e&ecution s%eed o" your %rogra#. /ou #ight as well #ake all p*blic #ethods o" a Bean synchroni7e' and re#ove the synchroni7e' keyword only when you know "or sure that it s necessary and that it #akes a di""erence. RFSURFSTIJLT+(6PTE5M?TI3?U

(+7) :hen "iring a #ulticast event to a bunch o" listeners interested in


that event, you #ust assu#e that listeners #ight be added or re#oved while #oving through the list. RFSURF STIJLT+(6PTE5M?TI3HU The "irst %oint is "airly easy to deal with, but the second %oint reAuires a little #ore thought. +onsider the 2ang2ean!8ava e&a#%le %resented in the last cha%ter. That ducked out o" the #ultithreading Auestion by ignoring the synchroni7e' keyword *which hadn t been introduced yet, and #aking the event unicast. (ere s that e&a#%le #odi"ied to work in a #ultithreaded environ#ent and to use #ulticasting "or events=

::7

//3 c(I3BangBean .Hava // ;ou shoul! :rite your Beans this :ay so they // can run in a #ultithrea!e! environ#ent. i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort Hava.util.B< i#"ort Hava.io.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class BangBean e6ten!s JPanel i#"le#ents %erialiUable @ "rivate int 6#, y#< "rivate int c%iUe ? '< // Circle siUe "rivate %tring te6t ? 8Bang48< "rivate int font%iUe ? I1< "rivate Color tColor ? Color.re!< "rivate 0rrayList actionListeners ? ne: 0rrayList-.< "ublic BangBean -. @ a!!JouseListener-ne: JL-..< a!!JouseJotionListener-ne: JJ-..< A "ublic synchroniUe! int getCircle%iUe-. @ return c%iUe< A "ublic synchroniUe! voi! setCircle%iUe-int ne:%iUe. @ c%iUe ? ne:%iUe< A "ublic synchroniUe! %tring getBangTe6t-. @ return te6t< A "ublic synchroniUe! voi! setBangTe6t-%tring ne:Te6t. @ te6t ? ne:Te6t< A "ublic synchroniUe! int getLont%iUe-. @ return font%iUe< A "ublic synchroniUe! voi!

Cha ter 14! Multi le Threads

::8

setLont%iUe-int ne:%iUe. @ font%iUe ? ne:%iUe< A "ublic synchroniUe! Color getTe6tColor-. @ return tColor< A "ublic synchroniUe! voi! setTe6tColor-Color ne:Color. @ tColor ? ne:Color< A "ublic voi! "aintCo#"onent-ara"hics g. @ su"er."aintCo#"onent-g.< g.setColor-Color.black.< g.!ra:Gval-6# - c%iUe/ , y# - c%iUe/ , c%iUe, c%iUe.< A // This is a #ulticast listener, :hich is // #ore ty"ically use! than the unicast // a""roach taken in BangBean.Hava3 "ublic synchroniUe! voi! a!!0ctionListener-0ctionListener l. @ actionListeners.a!!-l.< A "ublic synchroniUe! voi! re#ove0ctionListener-0ctionListener l. @ actionListeners.re#ove-l.< A // &otice this isn2t synchroniUe!3 "ublic voi! notifyListeners-. @ 0ctionEvent a ? ne: 0ctionEvent-BangBean .this, 0ctionEvent.0CT$G&bPE5LG5JED, null.< 0rrayList lv ? null< // Jake a shallo: co"y of the List in case // so#eone a!!s a listener :hile :e2re // calling listeners3 synchroniUe!-this. @ lv ? -0rrayList.actionListeners.clone-.< A // Call all the listener #etho!s3 for-int i ? '< i P lv.siUe-.< iKK.

:::

--0ctionListener.lv.get-i.. .actionPerfor#e!-a.< A class JL e6ten!s Jouse0!a"ter @ "ublic voi! #ousePresse!-JouseEvent e. @ ara"hics g ? getara"hics-.< g.setColor-tColor.< g.setLontne: Lont8Ti#es5o#an8, Lont.BGLD, font%iUe..< int :i!th ? g.getLontJetrics-..string\i!th-te6t.< g.!ra:%tring-te6t, -get%iUe-..:i!th - :i!th. / , get%iUe-..height/ .< g.!is"ose-.< notifyListeners-.< A A class JJ e6ten!s JouseJotion0!a"ter @ "ublic voi! #ouseJove!-JouseEvent e. @ 6# ? e.get9-.< y# ? e.get;-.< re"aint-.< A A "ublic static voi! #ain-%tringNO args. @ BangBean bb ? ne: BangBean -.< bb.a!!0ctionListener-ne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e.@ %yste#.out."rintln-80ctionEvent8 K e.< A A.< bb.a!!0ctionListener-ne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e.@ %yste#.out."rintln-8BangBean action8.< A A.< bb.a!!0ctionListener-ne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e.@ %yste#.out."rintln-8Jore action8.<

Cha ter 14! Multi le Threads

::;

A A.< Console.run-bb, )'', )''.< A A ///3>


6dding synchroni7e' to the #ethods is an easy change. (owever, notice in a''Action+istenerA B and removeAction+istenerA B that the Action+isteners are now added to and re#oved "ro# an Array+ist, so you can have as #any as you want. RFSURF STIJLT+(6PTE5M?TI33U /ou can see that the #ethod notify+istenersA B is not synchroni7e'. It can be called "ro# #ore than one thread at a ti#e. It s also %ossible "or a''Action+istenerA B or removeAction+istenerA B to be called in the #iddle o" a call to notify+istenersA B, which is a %roble# since it traverses the Array+ist action+isteners. To alleviate the %roble#, the Array+ist is cloned inside a synchroni7e' clause and the clone is traversed *see 6%%endi& 6 "or details o" cloning,. This way the original Array+ist can be #ani%ulated without i#%act on notify+istenersA B. RFSURFSTIJLT+(6PTE5M?TI3GU The paint-omponentA B #ethod is also not synchroni7e'. 7eciding whether to synchroni1e overridden #ethods is not as clear as when you re 0ust adding your own #ethods. In this e&a#%le it turns out that paintA B see#s to work )> whether it s synchroni7e' or not. But the issues you #ust consider are=

(+() 7oes the #ethod #odi"y the state o" !critical$ variables within the
ob0ectO To discover whether the variables are !critical$ you #ust deter#ine whether they will be read or set by other threads in the %rogra#. *In this case, the reading or setting is virtually always acco#%lished via synchroni7e' #ethods, so you can 0ust e&a#ine those., In the case o" paintA B, no #odi"ication takes %lace. RFSURFSTIJLT+(6PTE5M?TI3IU

(+!) 7oes the #ethod de%end on the state o" these !critical$ variablesO I" a synchroni7e' #ethod #odi"ies a variable that your #ethod
uses, then you #ight very well want to #ake your #ethod synchroni7e' as well. Based on this, you #ight observe that

:;=

c)i7e is changed by synchroni7e' #ethods and there"ore paint A B should be synchroni7e'. (ere, however, you can ask !:hat s the worst thing that will ha%%en i" c)i7e is changed during a paint A BO$ :hen you see that it s nothing too bad, and a transient e""ect at that, you can decide to leave paintA B un' synchroni7e' to %revent the e&tra overhead "ro# the synchroni7e' #ethod call.
RFSURFSTIJLT+(6PTE5M?TI32U

(+*) 6 third clue is to notice whether the base'class version o" paintA B is synchroni7e', which it isn t. This isn t an airtight argu#ent, 0ust a clue. In this case, "or e&a#%le, a "ield that is changed via synchroni7e' #ethods *that is c)i7e, has been #i&ed into the paintA B "or#ula and #ight have changed the situation. Cotice, however, that synchroni7e' doesn t inherit9that is, i" a #ethod is synchroni7e' in the base class then it is not auto#atically synchroni7e' in the derived class overridden version. RFSURF
STIJLT+(6PTE5M?TIG@U The test code in Test2ang2eanI has been #odi"ied "ro# that in the %revious cha%ter to de#onstrate the #ulticast ability o" 2ang2eanI by adding e&tra listeners. RFSURFSTIJLT+(6PTE5M?TIGMU

;locking
6 thread can be in any one o" "our states=

(++) +e,= The thread ob0ect has been created but it hasn t been started
yet so it cannot run. RFSURFSTIJLT+(6PTE5M?TIGKU

(+,) -unnable= This #eans that a thread can be run when the ti#e'
slicing #echanis# has +P4 cycles available "or the thread. Thus, the thread #ight or #ight not be running, but there s nothing to %revent it "ro# being run i" the scheduler can arrange it; it s not dead or blocked. RFSURFSTIJLT+(6PTE5M?TIGLU

(+-) %ead= The nor#al way "or a thread to die is by returning "ro# its r*nA B #ethod. /ou can also call stopA B, but this throws an e&ce%tion that s a subclass o" &rror *which #eans you aren t "orced to %ut the call in a try block,. 5e#e#ber that throwing an

Cha ter 14! Multi le Threads

:;1

e&ce%tion should be a s%ecial event and not %art o" nor#al %rogra# e&ecution; thus the use o" stopA B is de%recated in Java K. There s also a 'estroyA B #ethod *which has never been i#%le#ented, that you should never call i" you can avoid it since it s drastic and doesn t release ob0ect locks. RFSURF STIJLT+(6PTE5M?TIG?U

(+4) 0locked= The thread could be run but there s so#ething that
%revents it. :hile a thread is in the blocked state the scheduler will si#%ly ski% over it and not give it any +P4 ti#e. 4ntil a thread reenters the runnable state it won t %er"or# any o%erations. RF SURFSTIJLT+(6PTE5M?TIGHU

;ecoming blocked
The blocked state is the #ost interesting one, and is worth "urther e&a#ination. 6 thread can beco#e blocked "or "ive reasons= RFSURF STIJLT+(6PTE5M?TIG3U

(+5) /ou ve %ut the thread to slee% by calling sleepAmillisecon'sB, in


which case it will not be run "or the s%eci"ied ti#e. RFSURF STIJLT+(6PTE5M?TIGGU

(+6) /ou ve sus%ended the e&ecution o" the thread with s*spen'A B. It will not beco#e runnable again until the thread gets the res*me A B #essage *these are de%recated in Java K, and will be e&a#ined
"urther,. RFSURFSTIJLT+(6PTE5M?TIGIU

(,7) /ou ve sus%ended the e&ecution o" the thread with (aitA B. It will not beco#e runnable again until the thread gets the notifyA B or notifyAllA B #essage. */es, this looks 0ust like nu#ber K, but
there s a distinct di""erence that will be revealed., RFSURF STIJLT+(6PTE5M?TIG2U

(,() The thread is waiting "or so#e IF) to co#%lete. RFSURF


STIJLT+(6PTE5M?TII@U

(,!) The thread is trying to call a synchroni7e' #ethod on another


ob0ect, and that ob0ect s lock is not available. RFSURF STIJLT+(6PTE5M?TIIMU

:;2

/ou can also call yiel'A B *a #ethod o" the Threa' class, to voluntarily give u% the +P4 so that other threads can run. (owever, the sa#e thing ha%%ens i" the scheduler decides that your thread has had enough ti#e and 0u#%s to another thread. That is, nothing %revents the scheduler "ro# #oving your thread and giving ti#e to so#e other thread. :hen a thread is blocked, there s so#e reason that it cannot continue running. RF SURFSTIJLT+(6PTE5M?TIIKU The "ollowing e&a#%le shows all "ive ways o" beco#ing blocked. It all e&ists in a single "ile called 2locking!8ava, but it will be e&a#ined here in discrete %ieces. */ou ll notice the !+ontinued$ and !+ontinuing$ tags that allow the code e&traction tool to %iece everything together., RFSURF STIJLT+(6PTE5M?TIILU Because this e&a#%le de#onstrates so#e de%recated #ethods, you ,ill get de%recation #essages when it is co#%iled. RFSURF STIJLT+(6PTE5M?TII?U Eirst, the basic "ra#ework=

//3 c(I3Blocking.Hava // De#onstrates the various :ays a threa! // can be blocke!. // Pa""let co!e?Blocking :i!th?),' height?,,'Q // P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort Hava.io.B< i#"ort co#.bruceeckel.s:ing.B< //////////// The basic fra#e:ork /////////// class Blockable e6ten!s Threa! @ "rivate Peeker "eeker< "rotecte! JTe6tLiel! state ? ne: JTe6tLiel!-)'.< "rotecte! int i< "ublic Blockable-Container c. @ c.a!!-state.< "eeker ? ne: Peeker-this, c.< A "ublic synchroniUe! int rea!-. @ return i< A

Cha ter 14! Multi le Threads

:;3

"rotecte! synchroniUe! voi! u"!ate-. @ state.setTe6t-getClass-..get&a#e-. K 8 state3 i ? 8 K i.< A "ublic voi! sto"Peeker-. @ // "eeker.sto"-.< De"recate! in Java (. "eeker.ter#inate-.< // The "referre! a""roach A A class Peeker e6ten!s Threa! @ "rivate Blockable b< "rivate int session< "rivate JTe6tLiel! status ? ne: JTe6tLiel!-)'.< "rivate boolean sto" ? false< "ublic Peeker-Blockable b, Container c. @ c.a!!-status.< this.b ? b< start-.< A "ublic voi! ter#inate-. @ sto" ? true< A "ublic voi! run-. @ :hile -4sto". @ status.setTe6t-b.getClass-..get&a#e-. K 8 Peeker 8 K -KKsession. K 8< value ? 8 K b.rea!-..< try @ slee"-(''.< A catch-$nterru"te!E6ce"tion e. @ %yste#.err."rintln-8$nterru"te!8.< A A A A ///3Continue!
The 2lockable class is #eant to be a base class "or all the classes in this e&a#%le that de#onstrate blocking. 6 2lockable ob0ect contains a JTe4tFiel' called state that is used to dis%lay in"or#ation about the ob0ect. The #ethod that dis%lays this in"or#ation is *p'ateA B. /ou can see it uses get-lassA B!get/ameA B to %roduce the na#e o" the class instead o" 0ust %rinting it out; this is because *p'ateA B cannot know the

:;4

e&act na#e o" the class it is called "or, since it will be a class derived "ro# 2lockable. RFSURFSTIJLT+(6PTE5M?TIIHU The indicator o" change in 2lockable is an int i, which will be incre#ented by the r*nA B #ethod o" the derived class. RFSURF STIJLT+(6PTE5M?TII3U There s a thread o" class #eeker that is started "or each 2lockable ob0ect, and the #eeker s 0ob is to watch its associated 2lockable ob0ect to see changes in i by calling rea'A B and re%orting the# in its stat*s JTe4tFiel'. This is i#%ortant= Cote that rea'A B and *p'ateA B are both synchroni7e', which #eans they reAuire that the ob0ect lock be "ree. RFSURFSTIJLT+(6PTE5M?TIIGU

1lee.ing
The "irst test in this %rogra# is with sleepA B<

///3Continuing ///////////// Blocking via slee"-. /////////// class %lee"er( e6ten!s Blockable @ "ublic %lee"er(-Container c. @ su"er-c.< A "ublic synchroniUe! voi! run-. @ :hile-true. @ iKK< u"!ate-.< try @ slee"-('''.< A catch-$nterru"te!E6ce"tion e. @ %yste#.err."rintln-8$nterru"te!8.< A A A A class %lee"er e6ten!s Blockable @ "ublic %lee"er -Container c. @ su"er-c.< A "ublic voi! run-. @ :hile-true. @ change-.< try @

Cha ter 14! Multi le Threads

:;5

slee"-('''.< A catch-$nterru"te!E6ce"tion e. @ %yste#.err."rintln-8$nterru"te!8.< A A A "ublic synchroniUe! voi! change-. @ iKK< u"!ate-.< A A ///3Continue!
In )leeper> the entire r*nA B #ethod is synchroni7e'. /ou ll see that the #eeker associated with this ob0ect will run along #errily until you start the thread, and then the #eeker sto%s cold. This is one "or# o" blocking= since )leeper>!r*nA B is synchroni7e', and once the thread starts it s always inside r*nA B, the #ethod never gives u% the ob0ect lock and the #eeker is blocked. RFSURFSTIJLT+(6PTE5M?TIIIU

)leeperI %rovides a solution by #aking r*nA B un' synchroni7e'. )nly the changeA B #ethod is synchroni7e', which #eans that while r*nA B is in sleepA B, the #eeker can access the synchroni7e' #ethod it needs, na#ely rea'A B. (ere you ll see that the #eeker continues running when you start the )leeperI thread. RFSURF
STIJLT+(6PTE5M?TII2U

1us.ending and resuming


The ne&t %art o" the e&a#%le introduces the conce%t o" sus%ension. The

Threa' class has a #ethod s*spen'A B to te#%orarily sto% the thread and res*meA B that restarts it at the %oint it was halted. res*meA B #ust
be called by so#e thread outside the sus%ended one, and in this case there s a se%arate class called $es*mer that does 0ust that. Each o" the classes de#onstrating sus%endFresu#e has an associated resu#er=

///3Continuing /////////// Blocking via sus"en!-. /////////// class %us"en!5esu#e e6ten!s Blockable @ "ublic %us"en!5esu#e-Container c. @ su"er-c.< ne: 5esu#er-this.<

:;7

A A class %us"en!5esu#e( e6ten!s %us"en!5esu#e @ "ublic %us"en!5esu#e(-Container c. @ su"er-c.<A "ublic synchroniUe! voi! run-. @ :hile-true. @ iKK< u"!ate-.< sus"en!-.< // De"recate! in Java (. A A A class %us"en!5esu#e e6ten!s %us"en!5esu#e @ "ublic %us"en!5esu#e -Container c. @ su"er-c.<A "ublic voi! run-. @ :hile-true. @ change-.< sus"en!-.< // De"recate! in Java (. A A "ublic synchroniUe! voi! change-. @ iKK< u"!ate-.< A A class 5esu#er e6ten!s Threa! @ "rivate %us"en!5esu#e sr< "ublic 5esu#er-%us"en!5esu#e sr. @ this.sr ? sr< start-.< A "ublic voi! run-. @ :hile-true. @ try @ slee"-('''.< A catch-$nterru"te!E6ce"tion e. @ %yste#.err."rintln-8$nterru"te!8.< A

Cha ter 14! Multi le Threads

:;8

sr.resu#e-.< // De"recate! in Java (. A A A ///3Continue! )*spen'$es*me> also has a synchroni7e' r*nA B #ethod. 6gain, when you start this thread you ll see that its associated #eeker gets
blocked waiting "or the lock to beco#e available, which never ha%%ens. This is "i&ed as be"ore in )*spen'$es*meI, which does not synchroni7e the entire r*nA B #ethod but instead uses a se%arate synchroni7e' changeA B #ethod. RFSURFSTIJLT+(6PTE5M?TI2@U /ou should be aware that Java K de%recates the use o" s*spen'A B and res*meA B, because s*spen'A B holds the ob0ect s lock and is thus deadlock'%rone. That is, you can easily get a nu#ber o" locked ob0ects waiting on each other, and this will cause your %rogra# to "ree1e. 6lthough you #ight see the# used in older %rogra#s you should not use s*spen'A B and res*meA B. The %ro%er solution is described later in this cha%ter. RFSURFSTIJLT+(6PTE5M?TI2MU

Wait and notif:


In the "irst two e&a#%les, it s i#%ortant to understand that both sleepA B and s*spen'A B do not release the lock as they are called. /ou #ust be aware o" this when working with locks. )n the other hand, the #ethod (aitA B does release the lock when it is called, which #eans that other synchroni7e' #ethods in the thread ob0ect could be called during a (aitA B. In the "ollowing two classes, you ll see that the r*nA B #ethod is "ully synchroni7e' in both cases, however, the #eeker still has "ull access to the synchroni7e' #ethods during a (aitA B. This is because (aitA B releases the lock on the ob0ect as it sus%ends the #ethod it s called within. RFSURFSTIJLT+(6PTE5M?TI2KU /ou ll also see that there are two "or#s o" (aitA B. The "irst takes an argu#ent in #illiseconds that has the sa#e #eaning as in sleepA B= %ause "or this %eriod o" ti#e. The di""erence is that in (aitA B, the ob0ect lock is released and you can co#e out o" the (aitA B because o" a notify A B as well as having the clock run out. RFSURFSTIJLT+(6PTE5M?TI2LU

:;:

The second "or# takes no argu#ents, and #eans that the (aitA B will continue until a notifyA B co#es along and will not auto#atically ter#inate a"ter a ti#e. RFSURFSTIJLT+(6PTE5M?TI2?U )ne "airly uniAue as%ect o" (aitA B and notifyA B is that both #ethods are %art o" the base class .b8ect and not %art o" Threa' as are sleepA B, s*spen'A B, and res*meA B. 6lthough this see#s a bit strange at "irst9 to have so#ething that s e&clusively "or threading as %art o" the universal base class9it s essential because they #ani%ulate the lock that s also %art o" every ob0ect. 6s a result, you can %ut a (aitA B inside any synchroni7e' #ethod, regardless o" whether there s any threading going on inside that %articular class. In "act, the onl) %lace you can call (aitA B is within a synchroni7e' #ethod or block. I" you call (aitA B or notifyA B within a #ethod that s not synchroni7e', the %rogra# will co#%ile, but when you run it you ll get an Illegal1onitor)tate&4ception with the so#ewhat nonintuitive #essage !current thread not owner.$ Cote that sleepA B, s*spen'A B, and res*meA B can all be called within non' synchroni7e' #ethods since they don t #ani%ulate the lock. RFSURFSTIJLT+(6PTE5M?TI2HU /ou can call (aitA B or notifyA B only "or your own lock. 6gain, you can co#%ile code that tries to use the wrong lock, but it will %roduce the sa#e Illegal1onitor)tate&4ception #essage as be"ore. /ou can t "ool with so#eone else s lock, but you can ask another ob0ect to %er"or# an o%eration that #ani%ulates its own lock. So one a%%roach is to create a synchroni7e' #ethod that calls notifyA B "or its own ob0ect. (owever, in /otifier you ll see the notifyA B call inside a synchroni7e' block=

synchroniUe!-:n . @ :n .notify-.< A
where (nI is the ob0ect o" ty%e 0ait/otifyI. This #ethod, which is not %art o" 0ait/otifyI, acAuires the lock on the (nI ob0ect, at which %oint it s legal "or it to call notifyA B "or (nI and you won t get the Illegal1onitor)tate&4ception. RFSURFSTIJLT+(6PTE5M?TI23U

///3Continuing /////////// Blocking via :ait-. /////////// class \ait&otify( e6ten!s Blockable @

Cha ter 14! Multi le Threads

:;;

"ublic \ait&otify(-Container c. @ su"er-c.< A "ublic synchroniUe! voi! run-. @ :hile-true. @ iKK< u"!ate-.< try @ :ait-('''.< A catch-$nterru"te!E6ce"tion e. @ %yste#.err."rintln-8$nterru"te!8.< A A A A class \ait&otify e6ten!s Blockable @ "ublic \ait&otify -Container c. @ su"er-c.< ne: &otifier-this.< A "ublic synchroniUe! voi! run-. @ :hile-true. @ iKK< u"!ate-.< try @ :ait-.< A catch-$nterru"te!E6ce"tion e. @ %yste#.err."rintln-8$nterru"te!8.< A A A A class &otifier e6ten!s Threa! @ "rivate \ait&otify :n < "ublic &otifier-\ait&otify :n . @ this.:n ? :n < start-.< A "ublic voi! run-. @ :hile-true. @ try @

;==

slee"- '''.< A catch-$nterru"te!E6ce"tion e. @ %yste#.err."rintln-8$nterru"te!8.< A synchroniUe!-:n . @ :n .notify-.< A A A A ///3Continue! (aitA B is ty%ically used when you ve gotten to the %oint where you re waiting "or so#e other condition, under the control o" "orces outside your thread, to change and you don t want to idly wait by inside the thread. So (aitA B allows you to %ut the thread to slee% while waiting "or the world to change, and only when a notifyA B or notifyAllA B occurs does the thread wake u% and check "or changes. Thus, it %rovides a way to synchroni1e between threads. RFSURFSTIJLT+(6PTE5M?TI2GU

;locking on IDO
I" a strea# is waiting "or so#e IF) activity, it will auto#atically block. In the "ollowing %ortion o" the e&a#%le, the two classes work with generic $ea'er and 0riter ob0ects, but in the test "ra#ework a %i%ed strea# will be set u% to allow the two threads to sa"ely %ass data to each other *which is the %ur%ose o" %i%ed strea#s,. RFSURF STIJLT+(6PTE5M?TI2IU The )en'er %uts data into the 0riter and slee%s "or a rando# a#ount o" ti#e. (owever, $eceiver has no sleepA B, s*spen'A B, or (aitA B. But when it does a rea'A B it auto#atically blocks when there is no #ore data.

///3Continuing class %en!er e6ten!s Blockable @ // sen! "rivate \riter out< "ublic %en!er-Container c, \riter out. @ su"er-c.< this.out ? out< A "ublic voi! run-. @

Cha ter 14! Multi le Threads

;=1

:hile-true. @ for-char c ? 202< c P? 2U2< cKK. @ try @ iKK< out.:rite-c.< state.setTe6t-8%en!er sent3 8 K -char.c.< slee"--int.-)''' B Jath.ran!o#-...< A catch-$nterru"te!E6ce"tion e. @ %yste#.err."rintln-8$nterru"te!8.< A catch-$GE6ce"tion e. @ %yste#.err."rintln-8$G "roble#8.< A A A A A class 5eceiver e6ten!s Blockable @ "rivate 5ea!er in< "ublic 5eceiver-Container c, 5ea!er in. @ su"er-c.< this.in ? in< A "ublic voi! run-. @ try @ :hile-true. @ iKK< // %ho: "eeker it2s alive // Blocks until characters are there3 state.setTe6t-85eceiver rea!3 8 K -char.in.rea!-..< A A catch-$GE6ce"tion e. @ %yste#.err."rintln-8$G "roble#8.< A A A ///3Continue!
Both classes also %ut in"or#ation into their state "ields and change i so the #eeker can see that the thread is running. RFSURF STIJLT+(6PTE5M?TI22U

;=2

#esting
The #ain a%%let class is sur%risingly si#%le because #ost o" the work has been %ut into the 2lockable "ra#ework. Basically, an array o" 2lockable ob0ects is created, and since each one is a thread, they %er"or# their own activities when you %ress the !start$ button. There s also a button and action#erforme'A B clause to sto% all o" the #eeker ob0ects, which %rovides a de#onstration o" the alternative to the de%recated *in Java K, stopA B #ethod o" Threa'. RFSURF STIJLT+(6PTE5M?TIM@@U To set u% a connection between the )en'er and $eceiver ob0ects, a #ipe'0riter and #ipe'$ea'er are created. Cote that the #ipe'$ea'er in #ust be connected to the #ipe'0riter o*t via a constructor argu#ent. 6"ter that, anything that s %laced in o*t can later be e&tracted "ro# in, as i" it %assed through a %i%e *hence the na#e,. The in and o*t ob0ects are then %assed to the $eceiver and )en'er constructors, res%ectively, which treat the# as $ea'er and 0riter ob0ects o" any ty%e *that is, they are u%cast,. RFSURF STIJLT+(6PTE5M?TIM@MU The array o" 2lockable re"erences b is not initiali1ed at its %oint o" de"inition because the %i%ed strea#s cannot be set u% be"ore that de"inition takes %lace *the need "or the try block %revents this,.

///3Continuing /////////// Testing Everything /////////// "ublic class Blocking e6ten!s J0""let @ "rivate JButton start ? ne: JButton-8%tart8., sto"Peekers ? ne: JButton-8%to" Peekers8.< "rivate boolean starte! ? false< "rivate BlockableNO b< "rivate Pi"e!\riter out< "rivate Pi"e!5ea!er in< class %tartL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ if-4starte!. @ starte! ? true< for-int i ? '< i P b.length< iKK. bNiO.start-.<

Cha ter 14! Multi le Threads

;=3

A A A class %to"PeekersL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ // De#onstration of the "referre! // alternative to Threa!.sto"-.3 for-int i ? '< i P b.length< iKK. bNiO.sto"Peeker-.< A A "ublic voi! init-. @ Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< out ? ne: Pi"e!\riter-.< try @ in ? ne: Pi"e!5ea!er-out.< A catch-$GE6ce"tion e. @ %yste#.err."rintln-8Pi"e!5ea!er "roble#8.< A b ? ne: BlockableNO @ ne: %lee"er(-c"., ne: %lee"er -c"., ne: %us"en!5esu#e(-c"., ne: %us"en!5esu#e -c"., ne: \ait&otify(-c"., ne: \ait&otify -c"., ne: %en!er-c", out., ne: 5eceiver-c", in. A< start.a!!0ctionListener-ne: %tartL-..< c".a!!-start.< sto"Peekers.a!!0ctionListenerne: %to"PeekersL-..< c".a!!-sto"Peekers.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Blocking-., ),', ,,'.< A A ///3>

;=4

In initA B, notice the loo% that #oves through the entire array and adds the state and peeker!stat*s te&t "ields to the %age. RFSURF STIJLT+(6PTE5M?TIM@KU :hen the 2lockable threads are initially created, each one auto#atically creates and starts its own #eeker. So you ll see the #eekers running be"ore the 2lockable threads are started. This is i#%ortant, as so#e o" the #eekers will get blocked and sto% when the 2lockable threads start, and it s essential to see this to understand that %articular as%ect o" blocking. RFSURFSTIJLT+(6PTE5M?TIM@LU

Deadlock
Because threads can beco#e blocked and because ob0ects can have synchroni7e' #ethods that %revent threads "ro# accessing that ob0ect until the synchroni1ation lock is released, it s %ossible "or one thread to get stuck waiting "or another thread, which in turn waits "or another thread, etc., until the chain leads back to a thread waiting on the "irst one. /ou get a continuous loo% o" threads waiting on each other and no one can #ove. This is called deadlock. The clai# is that it doesn t ha%%en that o"ten, but when it ha%%ens to you it s "rustrating to debug. RFSURF STIJLT+(6PTE5M?TIM@?U There is no language su%%ort to hel% %revent deadlock; it s u% to you to avoid it by care"ul design. These are not co#"orting words to the %erson who s trying to debug a deadlocking %rogra#. RFSURF STIJLT+(6PTE5M?TIM@HU

#he de.recation of sto 1 2H sus end1 2H resume1 28 and destroy1 2 in "ava !


)ne change that has been #ade in Java K to reduce the %ossibility o" deadlock is the de%recation o" Threa' s stopA B, s*spen'A B, res*me A B, and 'estroyA B #ethods. RFSURFSTIJLT+(6PTE5M?TIM@3U The reason that the stopA B #ethod is de%recated is because it doesn t release the locks that the thread has acAuired, and i" the ob0ects are in an inconsistent state *!da#aged$, other threads can view and #odi"y the# in that state. The resulting %roble#s can be subtle and di""icult to detect.

Cha ter 14! Multi le Threads

;=5

Instead o" using stopA B, you should "ollow the e&a#%le in 2locking! 8ava and use a "lag to tell the thread when to ter#inate itsel" by e&iting its r*nA B #ethod. RFSURFSTIJLT+(6PTE5M?TIM@GU There are ti#es when a thread blocks9such as when it is waiting "or in%ut9and it cannot %oll a "lag as it does in 2locking!8ava. In these cases, you still shouldn t use stopA B, but instead you can use the interr*ptA B #ethod in Threa' to break out o" the blocked code=

//3 c(I3$nterru"t.Hava // The alternative a""roach to using // sto"-. :hen a threa! is blocke!. // Pa""let co!e?$nterru"t :i!th? '' height?(''Q // P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort co#.bruceeckel.s:ing.B< class Blocke! e6ten!s Threa! @ "ublic synchroniUe! voi! run-. @ try @ :ait-.< // Blocks A catch-$nterru"te!E6ce"tion e. @ %yste#.err."rintln-8$nterru"te!8.< A %yste#.out."rintln-8E6iting run-.8.< A A "ublic class $nterru"t e6ten!s J0""let @ "rivate JButton interru"t ? ne: JButton-8$nterru"t8.< "rivate Blocke! blocke! ? ne: Blocke!-.< "ublic voi! init-. @ Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< c".a!!-interru"t.< interru"t.a!!0ctionListenerne: 0ctionListener-. @ "ublic

;=7

voi! actionPerfor#e!-0ctionEvent e. @ %yste#.out."rintln-8Button "resse!8.< if-blocke! ?? null. return< Threa! re#ove ? blocke!< blocke! ? null< // to release it re#ove.interru"t-.< A A.< blocke!.start-.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: $nterru"t-., '', (''.< A A ///3>
The (aitA B inside 2locke'!r*nA B %roduces the blocked thread. :hen you %ress the button, the blocke' re"erence is set to n*ll so the garbage collector will clean it u%, and then the ob0ect s interr*ptA B #ethod is called. The "irst ti#e you %ress the button you ll see that the thread Auits, but a"ter that there s no thread to kill so you 0ust see that the button has been %ressed. RFSURFSTIJLT+(6PTE5M?TIM@IU The s*spen'A B and res*meA B #ethods turn out to be inherently deadlock'%rone. :hen you call s*spen'A B, the target thread sto%s but it still holds any locks that it has acAuired u% to that %oint. So no other thread can access the locked resources until the thread is resu#ed. 6ny thread that wants to resu#e the target thread and also tries to use any o" the locked resources %roduces deadlock. /ou should not use s*spen'A B and res*meA B, but instead %ut a "lag in your Threa' class to indicate whether the thread should be active or sus%ended. I" the "lag indicates that the thread is sus%ended, the thread goes into a wait using (aitA B. :hen the "lag indicates that the thread should be resu#ed the thread is restarted with notifyA B. 6n e&a#%le can be %roduced by #odi"ying -o*nterI!8ava. 6lthough the e""ect is si#ilar, you ll notice that the code organi1ation is Auite di""erent9anony#ous inner classes are used "or all o" the listeners and the Threa' is an inner class, which #akes %rogra##ing slightly #ore convenient since it eli#inates so#e o" the e&tra bookkee%ing necessary in -o*nterI!8ava= RFSURF STIJLT+(6PTE5M?TIM@2U

Cha ter 14! Multi le Threads

;=8

//3 c(I3%us"en!.Hava // The alternative a""roach to using sus"en!-. // an! resu#e-., :hich are !e"recate! in Java . // Pa""let co!e?%us"en! :i!th?)'' height?(''Q // P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class %us"en! e6ten!s J0""let @ "rivate JTe6tLiel! t ? ne: JTe6tLiel!-('.< "rivate JButton sus"en! ? ne: JButton-8%us"en!8., resu#e ? ne: JButton-85esu#e8.< "rivate %us"en!able ss ? ne: %us"en!able-.< class %us"en!able e6ten!s Threa! @ "rivate int count ? '< "rivate boolean sus"en!e! ? false< "ublic %us"en!able-. @ su"er.start-.< A "ublic voi! fau6%us"en!-. @ sus"en!e! ? true< A "ublic synchroniUe! voi! fau65esu#e-. @ sus"en!e! ? false< notify-.< A "ublic voi! run-. @ :hile -true. @ try @ slee"-(''.< synchroniUe!-this. @ :hile-sus"en!e!. :ait-.< A A catch-$nterru"te!E6ce"tion e. @ %yste#.err."rintln-8$nterru"te!8.< A t.setTe6t-$nteger.to%tring-countKK..< A A

;=:

A "ublic voi! init-. @ Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< c".a!!-t.< sus"en!.a!!0ctionListenerne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ ss.fau6%us"en!-.< A A.< c".a!!-sus"en!.< resu#e.a!!0ctionListenerne: 0ctionListener-. @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ ss.fau65esu#e-.< A A.< c".a!!-resu#e.< A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: %us"en!-., )'', (''.< A A ///3>
The "lag s*spen'e' inside )*spen'able is used to turn sus%ension on and o"". To sus%end, the "lag is set to tr*e by calling fa*4)*spen'A B and this is detected inside r*nA B. The (aitA B, as described earlier in this cha%ter, #ust be synchroni7e' so that it has the ob0ect lock. In fa*4$es*meA B, the s*spen'e' "lag is set to false and notifyA B is called9since this wakes u% (aitA B inside a synchroni7e' clause the fa*4$es*meA B #ethod #ust also be synchroni7e' so that it acAuires the lock be"ore calling notifyA B *thus the lock is available "or the (aitA B to wake u% with,. I" you "ollow the style shown in this %rogra# you can avoid using s*spen'A B and res*meA B. RFSURF STIJLT+(6PTE5M?TIMM@U The 'estroyA B #ethod o" Threa' has never been i#%le#ented; it s like a s*spen'A B that cannot resu#e, so it has the sa#e deadlock issues as

Cha ter 14! Multi le Threads

;=;

s*spen'A B. (owever, this is not a de%recated #ethod and it #ight be


i#%le#ented in a "uture version o" Java *a"ter K, "or s%ecial situations in which the risk o" a deadlock is acce%table. RFSURF STIJLT+(6PTE5M?TIMMMU /ou #ight wonder why these #ethods, now de%recated, were included in Java in the "irst %lace. It see#s an ad#ission o" a rather signi"icant #istake to si#%ly re#ove the# outright *and %okes yet another hole in the argu#ents "or Java s e&ce%tional design and in"allibility touted by Sun #arketing %eo%le,. The heartening %art about the change is that it clearly indicates that the technical %eo%le and not the #arketing %eo%le are running the show9they discovered a %roble# and they are "i&ing it. I "ind this #uch #ore %ro#ising and ho%e"ul than leaving the %roble# in because !"i&ing it would ad#it an error.$ It #eans that Java will continue to i#%rove, even i" it #eans a little disco#"ort on the %art o" Java %rogra##ers. I d rather deal with the disco#"ort than watch the language stagnate. RFSURFSTIJLT+(6PTE5M?TIMMKU

riorities
The riorit) o" a thread tells the scheduler how i#%ortant this thread is. I" there are a nu#ber o" threads blocked and waiting to be run, the scheduler will run the one with the highest %riority "irst. (owever, this doesn t #ean that threads with lower %riority don t get run *that is, you can t get deadlocked because o" %riorities,. Dower %riority threads 0ust tend to run less o"ten. RFSURFSTIJLT+(6PTE5M?TIMMLU 6lthough %riorities are interesting to know about and to %lay with, in %ractice you al#ost never need to set %riorities yoursel". So "eel "ree to ski% the rest o" this section i" %riorities aren t interesting to you. RFSURF STIJLT+(6PTE5M?TIMM?U

$eading and setting .riorities


/ou can read the %riority o" a thread with get#riorityA B and change it with set#riorityA B. The "or# o" the %rior !counter$ e&a#%les can be used to show the e""ect o" changing the %riorities. In this a%%let you ll see

;1=

that the counters slow down as the associated threads have their %riorities lowered=

//3 c(I3Counter,.Hava // 0!Husting the "riorities of threa!s. // Pa""let co!e?Counter, :i!th?I,' height?+''Q // P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort co#.bruceeckel.s:ing.B< class Ticker e6ten!s Threa! @ "rivate JButton b ? ne: JButton-8Toggle8., incPriority ? ne: JButton-8u"8., !ecPriority ? ne: JButton-8!o:n8.< "rivate JTe6tLiel! t ? ne: JTe6tLiel!-('., "r ? ne: JTe6tLiel!-).< // Dis"lay "riority "rivate int count ? '< "rivate boolean runLlag ? true< "ublic Ticker -Container c. @ b.a!!0ctionListener-ne: ToggleL-..< incPriority.a!!0ctionListener-ne: Y"L-..< !ecPriority.a!!0ctionListener-ne: Do:nL-..< JPanel " ? ne: JPanel-.< ".a!!-t.< ".a!!-"r.< ".a!!-b.< ".a!!-incPriority.< ".a!!-!ecPriority.< c.a!!-".< A class ToggleL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ runLlag ? 4runLlag< A A class Y"L i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @

Cha ter 14! Multi le Threads

;11

int ne:Priority ? getPriority-. K (< if-ne:Priority Q Threa!.J09bP5$G5$T;. ne:Priority ? Threa!.J09bP5$G5$T;< setPriority-ne:Priority.< A A class Do:nL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ int ne:Priority ? getPriority-. - (< if-ne:Priority P Threa!.J$&bP5$G5$T;. ne:Priority ? Threa!.J$&bP5$G5$T;< setPriority-ne:Priority.< A A "ublic voi! run-. @ :hile -true. @ if-runLlag. @ t.setTe6t-$nteger.to%tring-countKK..< "r.setTe6t$nteger.to%tring-getPriority-...< A yiel!-.< A A A "ublic class Counter, e6ten!s J0""let @ "rivate JButton start ? ne: JButton-8%tart8., u"Ja6 ? ne: JButton-8$nc Ja6 Priority8., !o:nJa6 ? ne: JButton-8Dec Ja6 Priority8.< "rivate boolean starte! ? false< "rivate static final int %$TE ? ('< "rivate Ticker NO s ? ne: Ticker N%$TEO< "rivate JTe6tLiel! #" ? ne: JTe6tLiel!-).< "ublic voi! init-. @ Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< for-int i ? '< i P s.length< iKK. sNiO ? ne: Ticker -c".< c".a!!-ne: JLabel-

;12

8J09bP5$G5$T; ? 8 K Threa!.J09bP5$G5$T;..< c".a!!-ne: JLabel-8J$&bP5$G5$T; ? 8 K Threa!.J$&bP5$G5$T;..< c".a!!-ne: JLabel-8arou" Ja6 Priority ? 8..< c".a!!-#".< c".a!!-start.< c".a!!-u"Ja6.< c".a!!-!o:nJa6.< start.a!!0ctionListener-ne: %tartL-..< u"Ja6.a!!0ctionListener-ne: Y"Ja6L-..< !o:nJa6.a!!0ctionListener-ne: Do:nJa6L-..< sho:Ja6Priority-.< // 5ecursively !is"lay "arent threa! grou"s3 Threa!arou" "arent ? sN'O.getThrea!arou"-..getParent-.< :hile-"arent 4? null. @ c".a!!-ne: Label8Parent threa!grou" #a6 "riority ? 8 K "arent.getJa6Priority-...< "arent ? "arent.getParent-.< A A "ublic voi! sho:Ja6Priority-. @ #".setTe6t-$nteger.to%tringsN'O.getThrea!arou"-..getJa6Priority-...< A class %tartL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ if-4starte!. @ starte! ? true< for-int i ? '< i P s.length< iKK. sNiO.start-.< A A A class Y"Ja6L i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ int #a6" ? sN'O.getThrea!arou"-..getJa6Priority-.< if-KK#a6" Q Threa!.J09bP5$G5$T;. #a6" ? Threa!.J09bP5$G5$T;<

Cha ter 14! Multi le Threads

;13

sN'O.getThrea!arou"-..setJa6Priority-#a6".< sho:Ja6Priority-.< A A class Do:nJa6L i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ int #a6" ? sN'O.getThrea!arou"-..getJa6Priority-.< if---#a6" P Threa!.J$&bP5$G5$T;. #a6" ? Threa!.J$&bP5$G5$T;< sN'O.getThrea!arou"-..setJa6Priority-#a6".< sho:Ja6Priority-.< A A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Counter,-., I,', +''.< A A ///3> TickerI "ollows the "or# established earlier in this cha%ter, but there s an e&tra JTe4tFiel' "or dis%laying the %riority o" the thread and two #ore buttons "or incre#enting and decre#enting the %riority. RFSURF STIJLT+(6PTE5M?TIMMHU
6lso notice the use o" yiel'A B, which voluntarily hands control back to the scheduler. :ithout this the #ultithreading #echanis# still works, but you ll notice it runs slowly *try re#oving the call to yiel'A B to see this,. /ou could also call sleepA B, but then the rate o" counting would be controlled by the sleepA B duration instead o" the %riority. RFSURF STIJLT+(6PTE5M?TIMM3U The initA B in -o*nter@ creates an array o" ten TickerIs; their buttons and "ields are %laced on the "or# by the TickerI constructor. -o*nter@ adds buttons to start everything u% as well as incre#ent and decre#ent the #a&i#u# %riority o" the thread grou%. In addition, there are labels that dis%lay the #a&i#u# and #ini#u# %riorities %ossible "or a thread and a JTe4tFiel' to show the thread grou% s #a&i#u# %riority. *The ne&t section will describe thread grou%s., Einally, the %riorities o" the %arent thread grou%s are also dis%layed as labels. RFSURF STIJLT+(6PTE5M?TIMMGU

;14

:hen you %ress an !u%$ or !down$ button, that TickerI s %riority is "etched and incre#ented or decre#ented accordingly. RFSURF STIJLT+(6PTE5M?TIMMIU :hen you run this %rogra#, you ll notice several things. Eirst o" all, the thread grou% s de"ault %riority is "ive. Even i" you decre#ent the #a&i#u# %riority below "ive be"ore starting the threads *or be"ore creating the threads, which reAuires a code change,, each thread will have a de"ault %riority o" "ive. RFSURFSTIJLT+(6PTE5M?TIMM2U The si#%le test is to take one counter and decre#ent its %riority to one, and observe that it counts #uch slower. But now try to incre#ent it again. /ou can get it back u% to the thread grou% s %riority, but no higher. Cow decre#ent the thread grou% s %riority a cou%le o" ti#es. The thread %riorities are unchanged, but i" you try to #odi"y the# either u% or down you ll see that they ll auto#atically %o% to the %riority o" the thread grou%. 6lso, new threads will still be given a de"ault %riority, even i" that s higher than the grou% %riority. *Thus the grou% %riority is not a way to %revent new threads "ro# having higher %riorities than e&isting ones., RFSURF STIJLT+(6PTE5M?TIMK@U Einally, try to incre#ent the grou% #a&i#u# %riority. It can t be done. /ou can only reduce thread grou% #a&i#u# %riorities, not increase the#. RFSURFSTIJLT+(6PTE5M?TIMKMU

#hread grou.s
6ll threads belong to a thread grou%. This can be either the de"ault thread grou% or a grou% you e&%licitly s%eci"y when you create the thread. 6t creation, the thread is bound to a grou% and cannot change to a di""erent grou%. Each a%%lication has at least one thread that belongs to the syste# thread grou%. I" you create #ore threads without s%eci"ying a grou%, they will also belong to the syste# thread grou%. RFSURF STIJLT+(6PTE5M?TIMKKU Thread grou%s #ust also belong to other thread grou%s. The thread grou% that a new one belongs to #ust be s%eci"ied in the constructor. I" you create a thread grou% without s%eci"ying a thread grou% "or it to belong to, it will be %laced under the syste# thread grou%. Thus, all thread

Cha ter 14! Multi le Threads

;15

grou%s in your a%%lication will ulti#ately have the syste# thread grou% as the %arent. RFSURFSTIJLT+(6PTE5M?TIMKLU The reason "or the e&istence o" thread grou%s is hard to deter#ine "ro# the literature, which tends to be con"using on this sub0ect. It s o"ten cited as !security reasons.$ 6ccording to 6rnold N 8osling, @ !Threads within a thread grou% can #odi"y the other threads in the grou%, including any "arther down the hierarchy. 6 thread cannot #odi"y threads outside o" its own grou% or contained grou%s.$ It s hard to know what !#odi"y$ is su%%osed to #ean here. The "ollowing e&a#%le shows a thread in a !lea"$ subgrou% #odi"ying the %riorities o" all the threads in its tree o" thread grou%s as well as calling a #ethod "or all the threads in its tree.

//3 c(I3Test0ccess.Hava // Mo: threa!s can access other threa!s // in a "arent threa! grou". "ublic class Test0ccess @ "ublic static voi! #ain-%tringNO args. @ Threa!arou" 6 ? ne: Threa!arou"-868., y ? ne: Threa!arou"-6, 8y8., U ? ne: Threa!arou"-y, 8U8.< Threa! one ? ne: TestThrea!(-6, 8one8., t:o ? ne: TestThrea! -U, 8t:o8.< A A class TestThrea!( e6ten!s Threa! @ "rivate int i< TestThrea!(-Threa!arou" g, %tring na#e. @ su"er-g, na#e.< A voi! f-. @ iKK< // #o!ify this threa! %yste#.out."rintln-get&a#e-. K 8 f-.8.< A
@ The Java Programming (anguage, by >en 6rnold and Ja#es 8osling, 6ddison':esley M223 %% MG2.

;17

A class TestThrea! e6ten!s TestThrea!( @ TestThrea! -Threa!arou" g, %tring na#e. @ su"er-g, na#e.< start-.< A "ublic voi! run-. @ Threa!arou" g ? getThrea!arou"-..getParent-..getParent-.< g.list-.< Threa!NO g0ll ? ne: Threa!Ng.activeCount-.O< g.enu#erate-g0ll.< for-int i ? '< i P g0ll.length< iKK. @ if-g0llNiO 4? null. @ g0llNiO.setPriority-Threa!.J$&bP5$G5$T;.< --TestThrea!(.g0llNiO..f-.< A g.list-.< A A ///3>
In mainA B, several Threa'"ro*ps are created, lea"ing o"" "ro# each other= 4 has no argu#ent but its na#e *a )tring,, so it is auto#atically %laced in the !syste#$ thread grou%, while y is under 4 and 7 is under y. Cote that initiali1ation ha%%ens in te&tual order so this code is legal. RF SURFSTIJLT+(6PTE5M?TIMK?U Two threads are created and %laced in di""erent thread grou%s. TestThrea'> doesn t have a r*nA B #ethod but it does have an fA B that #odi"ies the thread and %rints so#ething so you can see it was called. TestThrea'I is a subclass o" TestThrea'> and its r*nA B is "airly elaborate. It "irst gets the thread grou% o" the current thread, then #oves u% the heritage tree by two levels using get#arentA B. *This is contrived since I %ur%osely %lace the TestThrea'I ob0ect two levels down in the hierarchy., 6t this %oint, an array o" re"erences to Threa's is created using the #ethod active-o*ntA B to ask how #any threads are in this thread grou% and all the child thread grou%s. The en*merateA B #ethod %laces re"erences to all o" these threads in the array gAll, then I si#%ly #ove through the entire array calling the fA B #ethod "or each thread, as

Cha ter 14! Multi le Threads

;18

well as #odi"ying the %riority. Thus, a thread in a !lea"$ thread grou% #odi"ies threads in %arent thread grou%s. Cote that since the "irst edition

o" this book a%%eared, the behavior o" en*merateA B a%%ears to have changed, and it will now so#eti#es %lace n*ll entries into the array, so you #ust guard against these in your code.RFSURF
STIJLT+(6PTE5M?TIMKHU The debugging #ethod listA B %rints all the in"or#ation about a thread grou% to standard out%ut and is hel%"ul when investigating thread grou% behavior. (ere s the out%ut o" the %rogra#=

Hava.lang.Threa!arou"Nna#e?6,#a6"ri?('O Threa!None,,,6O Hava.lang.Threa!arou"Nna#e?y,#a6"ri?('O Hava.lang.Threa!arou"Nna#e?U,#a6"ri?('O Threa!Nt:o,,,UO t:o f-. Hava.lang.Threa!arou"Nna#e?6,#a6"ri?('O Threa!None,,,6O Hava.lang.Threa!arou"Nna#e?y,#a6"ri?('O Hava.lang.Threa!arou"Nna#e?U,#a6"ri?('O Threa!Nt:o,(,UOHava.lang.Threa!arou" Nna#e?6,#a6"ri?('O Threa!None,,,6O Hava.lang.Threa!arou"Nna#e?y,#a6"ri?('O Hava.lang.Threa!arou"Nna#e?U,#a6"ri?('O Threa!Nt:o,,,UO one f-. t:o f-. Hava.lang.Threa!arou"Nna#e?6,#a6"ri?('O Threa!None,(,6O Hava.lang.Threa!arou"Nna#e?y,#a6"ri?('O Hava.lang.Threa!arou"Nna#e?U,#a6"ri?('O Threa!Nt:o,(,UO
Cot only does listA B %rint the class na#e o" Threa'"ro*p or Threa', but it also %rints the thread grou% na#e and its #a&i#u# %riority. Eor threads, the thread na#e is %rinted, "ollowed by the thread %riority and the grou% that it belongs to. Cote that listA B indents the threads and thread grou%s to indicate that they are children o" the unindented thread grou%. RFSURFSTIJLT+(6PTE5M?TIMK3U

;1:

/ou can see that fA B is called by the TestThrea'I r*nA B #ethod, so it s obvious that all threads in a grou% are vulnerable. (owever, you can access only the threads that branch o"" "ro# your own system thread grou% tree, and %erha%s this is what is #eant by !sa"ety.$ /ou cannot access anyone else s syste# thread grou% tree. RFSURF STIJLT+(6PTE5M?TIMKGU

Controlling thread grou.s


Putting aside the sa"ety issue, one thing thread grou%s see# to be use"ul "or is control= you can %er"or# certain o%erations on an entire thread grou% with a single co##and. The "ollowing e&a#%le de#onstrates this, and the restrictions on %riorities within thread grou%s. The co##ented nu#bers in %arentheses %rovide a re"erence to co#%are to the out%ut.

//3 c(I3Threa!arou"(.Hava // Mo: threa! grou"s control "riorities // of the threa!s insi!e the#. "ublic class Threa!arou"( @ "ublic static voi! #ain-%tringNO args. @ // aet the syste# threa! D "rint its $nfo3 Threa!arou" sys ? Threa!.currentThrea!-..getThrea!arou"-.< sys.list-.< // -(. // 5e!uce the syste# threa! grou" "riority3 sys.setJa6Priority-Threa!.J09bP5$G5$T; - (.< // $ncrease the #ain threa! "riority3 Threa! curr ? Threa!.currentThrea!-.< curr.setPriority-curr.getPriority-. K (.< sys.list-.< // - . // 0tte#"t to set a ne: grou" to the #a63 Threa!arou" g( ? ne: Threa!arou"-8g(8.< g(.setJa6Priority-Threa!.J09bP5$G5$T;.< // 0tte#"t to set a ne: threa! to the #a63 Threa! t ? ne: Threa!-g(, 808.< t.setPriority-Threa!.J09bP5$G5$T;.< g(.list-.< // -). // 5e!uce g(2s #a6 "riority, then atte#"t // to increase it3 g(.setJa6Priority-Threa!.J09bP5$G5$T; - .<

Cha ter 14! Multi le Threads

;1;

g(.setJa6Priority-Threa!.J09bP5$G5$T;.< g(.list-.< // -I. // 0tte#"t to set a ne: threa! to the #a63 t ? ne: Threa!-g(, 8B8.< t.setPriority-Threa!.J09bP5$G5$T;.< g(.list-.< // -,. // Lo:er the #a6 "riority belo: the !efault // threa! "riority3 g(.setJa6Priority-Threa!.J$&bP5$G5$T; K .< // Look at a ne: threa!2s "riority before // an! after changing it3 t ? ne: Threa!-g(, 8C8.< g(.list-.< // -+. t.setPriority-t.getPriority-. -(.< g(.list-.< // -*. // Jake g a chil! Threa!grou" of g( an! // try to increase its "riority3 Threa!arou" g ? ne: Threa!arou"-g(, 8g 8.< g .list-.< // -1. g .setJa6Priority-Threa!.J09bP5$G5$T;.< g .list-.< // -C. // 0!! a bunch of ne: threa!s to g 3 for -int i ? '< i P ,< iKK. ne: Threa!-g , $nteger.to%tring-i..< // %ho: infor#ation about all threa!grou"s // an! threa!s3 sys.list-.< // -('. %yste#.out."rintln-8%tarting all threa!s38.< Threa!NO all ? ne: Threa!Nsys.activeCount-.O< sys.enu#erate-all.< for-int i ? '< i P all.length< iKK. if-allNiO 4? null DD 4allNiO.is0live-.. allNiO.start-.< // %us"en!s D %to"s all threa!s in // this grou" an! its subgrou"s3 %yste#.out."rintln-80ll threa!s starte!8.< sys.sus"en!-.< // De"recate! in Java // &ever gets here... %yste#.out."rintln-80ll threa!s sus"en!e!8.< sys.sto"-.< // De"recate! in Java %yste#.out."rintln-80ll threa!s sto""e!8.<

;2=

A A ///3>
The out%ut that "ollows has been edited to allow it to "it on the %age *the

8ava!lang! has been re#oved, and to add nu#bers to corres%ond to the


co##ented nu#bers in the listing above. RFSURF STIJLT+(6PTE5M?TIMKIU

-(. Threa!arou"Nna#e?syste#,#a6"ri?('O Threa!N#ain,,,syste#O - . Threa!arou"Nna#e?syste#,#a6"ri?CO Threa!N#ain,+,syste#O -). Threa!arou"Nna#e?g(,#a6"ri?CO Threa!N0,C,g(O -I. Threa!arou"Nna#e?g(,#a6"ri?1O Threa!N0,C,g(O -,. Threa!arou"Nna#e?g(,#a6"ri?1O Threa!N0,C,g(O Threa!NB,1,g(O -+. Threa!arou"Nna#e?g(,#a6"ri?)O Threa!N0,C,g(O Threa!NB,1,g(O Threa!NC,+,g(O -*. Threa!arou"Nna#e?g(,#a6"ri?)O Threa!N0,C,g(O Threa!NB,1,g(O Threa!NC,),g(O -1. Threa!arou"Nna#e?g ,#a6"ri?)O -C. Threa!arou"Nna#e?g ,#a6"ri?)O -('.Threa!arou"Nna#e?syste#,#a6"ri?CO Threa!N#ain,+,syste#O Threa!arou"Nna#e?g(,#a6"ri?)O Threa!N0,C,g(O Threa!NB,1,g(O Threa!NC,),g(O Threa!arou"Nna#e?g ,#a6"ri?)O Threa!N',+,g O Threa!N(,+,g O Threa!N ,+,g O Threa!N),+,g O Threa!NI,+,g O

Cha ter 14! Multi le Threads

;21

%tarting all threa!s3 0ll threa!s starte!


6ll %rogra#s have at least one thread running, and the "irst action in

mainA B is to call the static #ethod o" Threa' called c*rrentThrea' A B. Ero# this thread, the thread grou% is %roduced and listA B is called
"or the result. The out%ut is=

-(. Threa!arou"Nna#e?syste#,#a6"ri?('O Threa!N#ain,,,syste#O


/ou can see that the na#e o" the #ain thread grou% is system, and the na#e o" the #ain thread is main, and it belongs to the system thread grou%. RFSURFSTIJLT+(6PTE5M?TIMK2U The second e&ercise shows that the system grou% s #a&i#u# %riority can be reduced and the main thread can have its %riority increased=

- . Threa!arou"Nna#e?syste#,#a6"ri?CO Threa!N#ain,+,syste#O
The third e&ercise creates a new thread grou%, g>, which auto#atically belongs to the system thread grou% since it isn t otherwise s%eci"ied. 6 new thread A is %laced in g>. 6"ter atte#%ting to set this grou% s #a&i#u# %riority to the highest level and A s %riority to the highest level, the result is=

-). Threa!arou"Nna#e?g(,#a6"ri?CO Threa!N0,C,g(O


Thus, it s not %ossible to change the thread grou% s #a&i#u# %riority to be higher than its %arent thread grou%. RFSURF STIJLT+(6PTE5M?TIML@U The "ourth e&ercise reduces g> s #a&i#u# %riority by two and then tries to increase it u% to Threa'!1AXX#$I.$IT:. The result is=

-I. Threa!arou"Nna#e?g(,#a6"ri?1O Threa!N0,C,g(O


/ou can see that the increase in #a&i#u# %riority didn t work. /ou can only decrease a thread grou% s #a&i#u# %riority, not increase it. 6lso, notice that thread A s %riority didn t change, and now it is higher than the

;22

thread grou% s #a&i#u# %riority. +hanging a thread grou% s #a&i#u# %riority doesn t a""ect e&isting threads. RFSURF STIJLT+(6PTE5M?TIMLMU The "i"th e&ercise atte#%ts to set a new thread to #a&i#u# %riority=

-,. Threa!arou"Nna#e?g(,#a6"ri?1O Threa!N0,C,g(O Threa!NB,1,g(O


The new thread cannot be changed to anything higher than the #a&i#u# thread grou% %riority. RFSURFSTIJLT+(6PTE5M?TIMLKU The de"ault thread %riority "or this %rogra# is si&; that s the %riority a new thread will be created at and where it will stay i" you don t #ani%ulate the %riority. E&ercise 3 lowers the #a&i#u# thread grou% %riority below the de"ault thread %riority to see what ha%%ens when you create a new thread under this condition=

-+. Threa!arou"Nna#e?g(,#a6"ri?)O Threa!N0,C,g(O Threa!NB,1,g(O Threa!NC,+,g(O


Even though the #a&i#u# %riority o" the thread grou% is three, the new thread is still created using the de"ault %riority o" si&. Thus, #a&i#u# thread grou% %riority does not a""ect de"ault %riority. *In "act, there a%%ears to be no way to set the de"ault %riority "or new threads., RFSURF STIJLT+(6PTE5M?TIMLLU 6"ter changing the %riority, atte#%ting to decre#ent it by one, the result is=

-*. Threa!arou"Nna#e?g(,#a6"ri?)O Threa!N0,C,g(O Threa!NB,1,g(O Threa!NC,),g(O


)nly when you atte#%t to change the %riority is the thread grou% s #a&i#u# %riority en"orced. RFSURFSTIJLT+(6PTE5M?TIML?U

Cha ter 14! Multi le Threads

;23

6 si#ilar e&%eri#ent is %er"or#ed in *I, and *2,, in which a new thread grou% gI is created as a child o" g> and its #a&i#u# %riority is changed. /ou can see that it s i#%ossible "or gI s #a&i#u# to go higher than g> s=

-1. Threa!arou"Nna#e?g ,#a6"ri?)O -C. Threa!arou"Nna#e?g ,#a6"ri?)O


6lso notice that gI is auto#atically set to the thread grou% #a&i#u# %riority o" g> as gI is created. RFSURFSTIJLT+(6PTE5M?TIMLHU 6"ter all o" these e&%eri#ents, the entire syste# o" thread grou%s and threads is %rinted=

-('.Threa!arou"Nna#e?syste#,#a6"ri?CO Threa!N#ain,+,syste#O Threa!arou"Nna#e?g(,#a6"ri?)O Threa!N0,C,g(O Threa!NB,1,g(O Threa!NC,),g(O Threa!arou"Nna#e?g ,#a6"ri?)O Threa!N',+,g O Threa!N(,+,g O Threa!N ,+,g O Threa!N),+,g O Threa!NI,+,g O
So because o" the rules o" thread grou%s, a child grou% #ust always have a #a&i#u# %riority that s less than or eAual to its %arent s #a&i#u# %riority. RFSURFSTIJLT+(6PTE5M?TIML3U The last %art o" this %rogra# de#onstrates #ethods "or an entire grou% o" threads. Eirst the %rogra# #oves through the entire tree o" threads and starts each one that hasn t been started. Eor dra#a, the system grou% is then sus%ended and "inally sto%%ed. *6lthough it s interesting to see that s*spen'A B and stopA B work on entire thread grou%s, you should kee% in #ind that these #ethods are de%recated in Java K., But when you sus%end the system grou% you also sus%end the main thread and the whole %rogra# shuts down, so it never gets to the %oint where the threads are sto%%ed. 6ctually, i" you do sto% the main thread it throws a Threa' eath e&ce%tion, so this is not a ty%ical thing to do. Since Threa'"ro*p is inherited "ro# .b8ect, which contains the (aitA B

;24

#ethod, you can also choose to sus%end the %rogra# "or any nu#ber o" seconds by calling (aitAsecon's K >DDDB. This #ust acAuire the lock inside a synchroni1ed block, o" course. RFSURF STIJLT+(6PTE5M?TIMLGU The Threa'"ro*p class also has s*spen'A B and res*meA B #ethods so you can sto% and start an entire thread grou% and all o" its threads and subgrou%s with a single co##and. *6gain, s*spen'A B and res*meA B are de%recated in Java K., RFSURFSTIJLT+(6PTE5M?TIMLIU Thread grou%s can see# a bit #ysterious at "irst, but kee% in #ind that you %robably won t be using the# directly very o"ten. RFSURF STIJLT+(6PTE5M?TIML2U

5unnable revisited
Earlier in this cha%ter, I suggested that you think care"ully be"ore #aking an a%%let or #ain Frame as an i#%le#entation o" $*nnable. )" course, i" you #ust inherit "ro# a class and you want to add threading behavior to the class, $*nnable is the correct solution. The "inal e&a#%le in this cha%ter e&%loits this by #aking a $*nnable J#anel class that %aints di""erent colors on itsel". This a%%lication is set u% to take values "ro# the co##and line to deter#ine how big the grid o" colors is and how long to sleepA B between color changes. By %laying with these values you ll discover so#e interesting and %ossibly ine&%licable "eatures o" threads=

//3 c(I3ColorBo6es.Hava // Ysing the 5unnable interface. // Pa""let co!e?ColorBo6es :i!th?,'' height?I''Q // P"ara# na#e?gri! value?8( 8Q // P"ara# na#e?"ause value?8,'8Q // P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort co#.bruceeckel.s:ing.B< class CBo6 e6ten!s JPanel i#"le#ents 5unnable @ "rivate Threa! t<

Cha ter 14! Multi le Threads

;25

"rivate int "ause< "rivate static final ColorNO colors ? @ Color.black, Color.blue, Color.cyan, Color.!arkaray, Color.gray, Color.green, Color.lightaray, Color.#agenta, Color.orange, Color."ink, Color.re!, Color.:hite, Color.yello: A< "rivate Color cColor ? ne:Color-.< "rivate static final Color ne:Color-. @ return colorsN -int.-Jath.ran!o#-. B colors.length. O< A "ublic voi! "aintCo#"onent-ara"hics g. @ su"er."aintCo#"onent-g.< g.setColor-cColor.< Di#ension s ? get%iUe-.< g.fill5ect-', ', s.:i!th, s.height.< A "ublic CBo6-int "ause. @ this."ause ? "ause< t ? ne: Threa!-this.< t.start-.< A "ublic voi! run-. @ :hile-true. @ cColor ? ne:Color-.< re"aint-.< try @ t.slee"-"ause.< A catch-$nterru"te!E6ce"tion e. @ %yste#.err."rintln-8$nterru"te!8.< A A A A "ublic class ColorBo6es e6ten!s J0""let @ "rivate boolean is0""let ? true< "rivate int gri! ? ( <

;27

"rivate int "ause ? ,'< "ublic voi! init-. @ // aet "ara#eters fro# \eb "age3 if -is0""let. @ %tring gsiUe ? getPara#eter-8gri!8.< if-gsiUe 4? null. gri! ? $nteger."arse$nt-gsiUe.< %tring "se ? getPara#eter-8"ause8.< if-"se 4? null. "ause ? $nteger."arse$nt-"se.< A Container c" ? getContentPane-.< c".setLayout-ne: ari!Layout-gri!, gri!..< for -int i ? '< i P gri! B gri!< iKK. c".a!!-ne: CBo6-"ause..< A "ublic static voi! #ain-%tringNO args. @ ColorBo6es a""let ? ne: ColorBo6es-.< a""let.is0""let ? false< if-args.length Q '. a""let.gri! ? $nteger."arse$nt-argsN'O.< if-args.length Q (. a""let."ause ? $nteger."arse$nt-argsN(O.< Console.run-a""let, ,'', I''.< A A ///3> -olor2o4es is the usual a%%letFa%%lication with an initA B that sets u% the 84I. This sets u% the "ri'+ayo*t so that it has gri' cells in each di#ension. Then it adds the a%%ro%riate nu#ber o" -2o4 ob0ects to "ill the grid, %assing the pa*se value to each one. In mainA B you can see how pa*se and gri' have de"ault values that can be changed i" you %ass in co##and'line argu#ents, or by using a%%let %ara#eters. RFSURF STIJLT+(6PTE5M?TIM?@U -2o4 is where all the work takes %lace. This is inherited "ro# J#anel and it i#%le#ents the $*nnable inter"ace so each J#anel can also be a Threa'. 5e#e#ber that when you i#%le#ent $*nnable, you don t #ake a Threa' ob0ect, 0ust a class that has a r*nA B #ethod. Thus, you #ust e&%licitly create a Threa' ob0ect and hand the $*nnable ob0ect to

Cha ter 14! Multi le Threads

;28

the constructor, then call startA B *this ha%%ens in the constructor,. In -2o4 this thread is called t. RFSURFSTIJLT+(6PTE5M?TIM?MU Cotice the array colors, which is an enu#eration o" all the colors in class -olor. This is used in ne(-olorA B to %roduce a rando#ly selected color. The current cell color is c-olor. RFSURF STIJLT+(6PTE5M?TIM?KU

paint-omponentA B is Auite si#%le9it 0ust sets the color to c-olor and "ills the entire J#anel with that color. RFSURF
STIJLT+(6PTE5M?TIM?LU In r*nA B, you see the in"inite loo% that sets the c-olor to a new rando# color and then calls repaintA B to show it. Then the thread goes to sleep A B "or the a#ount o" ti#e s%eci"ied on the co##and line. RFSURF STIJLT+(6PTE5M?TIM??U Precisely because this design is "le&ible and threading is tied to each J#anel ele#ent, you can e&%eri#ent by #aking as #any threads as you want. *In reality, there is a restriction i#%osed by the nu#ber o" threads your JVM can co#"ortably handle., RFSURFSTIJLT+(6PTE5M?TIM?HU This %rogra# also #akes an interesting bench#ark, since it can show dra#atic %er"or#ance di""erences between one JVM threading i#%le#entation and another. RFSURFSTIJLT+(6PTE5M?TIM?3U

#oo man: threads


6t so#e %oint, you ll "ind that -olor2o4es bogs down. )n #y #achine, this occurred so#ewhere a"ter a M@ & M@ grid. :hy does this ha%%enO /ou re naturally sus%icious that Swing #ight have so#ething to do with it, so here s an e&a#%le that tests that %re#ise by #aking "ewer threads. The "ollowing code is reorgani1ed so that an Array+ist implements $*nnable and that Array+ist holds a nu#ber o" color blocks and rando#ly chooses ones to u%date. Then a nu#ber o" these Array+ist ob0ects are created, de%ending roughly on the grid di#ension you choose. 6s a result, you have "ar "ewer threads than color blocks, so i" there s a s%eedu% we ll know it was because there were too #any threads in the %revious e&a#%le=

;2:

//3 c(I3ColorBo6es .Hava // Balancing threa! use. // Pa""let co!e?ColorBo6es :i!th?+'' height?,''Q // P"ara# na#e?gri! value?8( 8Q // P"ara# na#e?"ause value?8,'8Q // P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort Hava.util.B< i#"ort co#.bruceeckel.s:ing.B< class CBo6 e6ten!s JPanel @ "rivate static final ColorNO colors ? @ Color.black, Color.blue, Color.cyan, Color.!arkaray, Color.gray, Color.green, Color.lightaray, Color.#agenta, Color.orange, Color."ink, Color.re!, Color.:hite, Color.yello: A< "rivate Color cColor ? ne:Color-.< "rivate static final Color ne:Color-. @ return colorsN -int.-Jath.ran!o#-. B colors.length. O< A voi! ne6tColor-. @ cColor ? ne:Color-.< re"aint-.< A "ublic voi! "aintCo#"onent-ara"hics g. @ su"er."aintCo#"onent-g.< g.setColor-cColor.< Di#ension s ? get%iUe-.< g.fill5ect-', ', s.:i!th, s.height.< A A class CBo6List e6ten!s 0rrayList i#"le#ents 5unnable @ "rivate Threa! t<

Cha ter 14! Multi le Threads

;2;

"rivate int "ause< "ublic CBo6List-int "ause. @ this."ause ? "ause< t ? ne: Threa!-this.< A "ublic voi! go-. @ t.start-.< A "ublic voi! run-. @ :hile-true. @ int i ? -int.-Jath.ran!o#-. B siUe-..< --CBo6 .get-i...ne6tColor-.< try @ t.slee"-"ause.< A catch-$nterru"te!E6ce"tion e. @ %yste#.err."rintln-8$nterru"te!8.< A A A "ublic GbHect last-. @ return get-siUe-. - (.<A A "ublic class ColorBo6es e6ten!s J0""let @ "rivate boolean is0""let ? true< "rivate int gri! ? ( < // %horter !efault "ause than ColorBo6es3 "rivate int "ause ? ,'< "rivate CBo6ListNO v< "ublic voi! init-. @ // aet "ara#eters fro# \eb "age3 if -is0""let. @ %tring gsiUe ? getPara#eter-8gri!8.< if-gsiUe 4? null. gri! ? $nteger."arse$nt-gsiUe.< %tring "se ? getPara#eter-8"ause8.< if-"se 4? null. "ause ? $nteger."arse$nt-"se.< A Container c" ? getContentPane-.< c".setLayout-ne: ari!Layout-gri!, gri!..< v ? ne: CBo6ListNgri!O< for-int i ? '< i P gri!< iKK. vNiO ? ne: CBo6List-"ause.<

;3=

for -int i ? '< i P gri! B gri!< iKK. @ vNi V gri!O.a!!-ne: CBo6 -..< c".a!!--CBo6 .vNi V gri!O.last-..< A for-int i ? '< i P gri!< iKK. vNiO.go-.< A "ublic static voi! #ain-%tringNO args. @ ColorBo6es a""let ? ne: ColorBo6es -.< a""let.is0""let ? false< if-args.length Q '. a""let.gri! ? $nteger."arse$nt-argsN'O.< if-args.length Q (. a""let."ause ? $nteger."arse$nt-argsN(O.< Console.run-a""let, ,'', I''.< A A ///3>
In -olor2o4esI an array o" -2o4+ist is created and initiali1ed to hold gri' -2o4+ists, each o" which knows how long to slee%. 6n eAual nu#ber o" -2o4I ob0ects is then added to each -2o4+ist, and each list is told to goA B, which starts its thread. RFSURF STIJLT+(6PTE5M?TIM?GU

-2o4I is si#ilar to -2o4= it %aints itsel" with a rando#ly chosen color. But that s all a -2o4I does. 6ll o" the threading has been #oved into -2o4+ist. RFSURFSTIJLT+(6PTE5M?TIM?IU
The -2o4+ist could also have inherited Threa' and had a #e#ber ob0ect o" ty%e Array+ist. That design has the advantage that the a''A B and getA B #ethods could then be given s%eci"ic argu#ent and return value ty%es instead o" generic .b8ects. *Their na#es could also be changed to so#ething shorter., (owever, the design used here see#ed at "irst glance to reAuire less code. In addition, it auto#atically retains all the other behaviors o" an Array+ist. :ith all the casting and %arentheses necessary "or getA B, this #ight not be the case as your body o" code grows. RFSURFSTIJLT+(6PTE5M?TIM?2U 6s be"ore, when you i#%le#ent $*nnable you don t get all o" the eAui%#ent that co#es with Threa', so you have to create a new Threa' and hand yoursel" to its constructor in order to have so#ething to start

Cha ter 14! Multi le Threads

;31

A B, as you can see in the -2o4+ist constructor and in goA B. The r*nA B
#ethod si#%ly chooses a rando# ele#ent nu#ber within the list and calls ne4t-olorA B "or that ele#ent to cause it to choose a new rando#ly selected color. RFSURFSTIJLT+(6PTE5M?TIMH@U 4%on running this %rogra#, you see that it does indeed run "aster and res%ond #ore Auickly *"or instance, when you interru%t it, it sto%s #ore Auickly,, and it doesn t see# to bog down as #uch at higher grid si1es. Thus, a new "actor is added into the threading eAuation= you #ust watch to see that you don t have !too #any threads$ *whatever that turns out to #ean "or your %articular %rogra# and %lat"or#9here, the slowdown in -olor2o4es a%%ears to be caused by the "act that there s only one thread that is res%onsible "or all %ainting, and it gets bogged down by too #any reAuests,. I" you have too #any threads, you #ust try to use techniAues like the one above to !balance$ the nu#ber o" threads in your %rogra#. I" you see %er"or#ance %roble#s in a #ultithreaded %rogra# you now have a nu#ber o" issues to e&a#ine= RFSURFSTIJLT+(6PTE5M?TIMHMU

(,*) 7o you have enough calls to sleepA B, yiel'A B, andFor (aitA BO (,+) 6re calls to sleepA B long enoughO (,,) 6re you running too #any threadsO (,-) (ave you tried di""erent %lat"or#s and JVMsO
Issues like this are one reason that #ultithreaded %rogra##ing is o"ten considered an art. RFSURFSTIJLT+(6PTE5M?TIMHKU

1ummar:
It is vital to learn when to use #ultithreading and when to avoid it. The #ain reason to use it is to #anage a nu#ber o" tasks whose inter#ingling will #ake #ore e""icient use o" the co#%uter *including the ability to trans%arently distribute the tasks across #ulti%le +P4s, or be #ore convenient "or the user. The classic e&a#%le o" resource balancing is using the +P4 during IF) waits. The classic e&a#%le o" user convenience is #onitoring a !sto%$ button during long downloads. RFSURF STIJLT+(6PTE5M?TIMHLU

;32

The #ain drawbacks to #ultithreading are=

(,4) Slowdown while waiting "or shared resources (,5) 6dditional +P4 overhead reAuired to #anage threads (,6) 4nrewarded co#%le&ity, such as the silly idea o" having a se%arate
thread to u%date each ele#ent o" an array

(-7) Pathologies including starving, racing, and deadlock


6n additional advantage to threads is that they substitute !light$ e&ecution conte&t switches *o" the order o" M@@ instructions, "or !heavy$ %rocess conte&t switches *o" the order o" M@@@s o" instructions,. Since all threads in a given %rocess share the sa#e #e#ory s%ace, a light conte&t switch changes only %rogra# e&ecution and local variables. )n the other hand, a %rocess change9the heavy conte&t switch9#ust e&change the "ull #e#ory s%ace. RFSURFSTIJLT+(6PTE5M?TIMH?U Threading is like ste%%ing into an entirely new world and learning a whole new %rogra##ing language, or at least a new set o" language conce%ts. :ith the a%%earance o" thread su%%ort in #ost #icroco#%uter o%erating syste#s, e&tensions "or threads have also been a%%earing in %rogra##ing languages or libraries. In all cases, thread %rogra##ing *M, see#s #ysterious and reAuires a shi"t in the way you think about %rogra##ing; and *K, looks si#ilar to thread su%%ort in other languages, so when you understand threads, you understand a co##on tongue. 6nd although su%%ort "or threads can #ake Java see# like a #ore co#%licated language, don t bla#e Java. Threads are tricky. RFSURF STIJLT+(6PTE5M?TIMHHU )ne o" the biggest di""iculties with threads occurs because #ore than one thread #ight be sharing a resource9such as the #e#ory in an ob0ect9 and you #ust #ake sure that #ulti%le threads don t try to read and change that resource at the sa#e ti#e. This reAuires 0udicious use o" the synchroni7e' keyword, which is a hel%"ul tool but #ust be understood thoroughly because it can Auietly introduce deadlock situations. RFSURF STIJLT+(6PTE5M?TIMH3U In addition, there s a certain art to the a%%lication o" threads. Java is designed to allow you to create as #any ob0ects as you need to solve your

Cha ter 14! Multi le Threads

;33

%roble#9at least in theory. *+reating #illions o" ob0ects "or an engineering "inite'ele#ent analysis, "or e&a#%le, #ight not be %ractical in Java., (owever, it see#s that there is an u%%er bound to the nu#ber o" threads you ll want to create, because at so#e %oint a large nu#ber o" threads see#s to beco#e unwieldy. This critical %oint is not in the #any thousands as it #ight be with ob0ects, but rather in the low hundreds, so#eti#es less than M@@. 6s you o"ten create only a hand"ul o" threads to solve a %roble#, this is ty%ically not #uch o" a li#it, yet in a #ore general design it beco#es a constraint. RFSURFSTIJLT+(6PTE5M?TIMHGU 6 signi"icant nonintuitive issue in threading is that, because o" thread scheduling, you can ty%ically #ake your a%%lications run $aster by inserting calls to sleepA B inside r*nA B s #ain loo%. This de"initely #akes it "eel like an art, in %articular when the longer delays see# to s%eed u% %er"or#ance. )" course, the reason this ha%%ens is that shorter delays can cause the end'o"' sleepA B scheduler interru%t to ha%%en be"ore the running thread is ready to go to slee%, "orcing the scheduler to sto% it and restart it later so it can "inish what it was doing and then go to slee%. It takes e&tra thought to reali1e how #essy things can get. RFSURF STIJLT+(6PTE5M?TIMHIU )ne thing you #ight notice #issing in this cha%ter is an ani#ation e&a#%le, which is one o" the #ost %o%ular things to do with a%%lets. (owever, a co#%lete solution *with sound, to this %roble# co#es with the Java J7> *available at >ava'sun'com, in the de#o section. In addition, we can e&%ect better ani#ation su%%ort to beco#e %art o" "uture versions o" Java, while co#%letely di""erent non'Java, non'%rogra##ing solutions to ani#ation "or the :eb are a%%earing that will %robably be su%erior to traditional a%%roaches. Eor e&%lanations about how Java ani#ation works, see Core Java 2 by (orst#ann N +ornell, Prentice' (all, M22G. Eor #ore advanced discussions o" threading, see Concurrent Programming in Java by 7oug Dea, 6ddison':esley, M22G, or Java Threads by )aks N :ong, ) 5eilly, M22G. RFSURF STIJLT+(6PTE5M?TIMH2U

/0ercises
Solutions to selected e&ercises can be "ound in the electronic docu#entThe Thinking in Java "nnotated Solution @uide, available "or a s#all "ee "ro# ,,,'0ruceEckel'com.

;34

!+4) Inherit a class "ro# Threa' and override the r*nA B #ethod.
Inside r*nA B, %rint a #essage, and then call sleepA B. 5e%eat this three ti#es, then return "ro# r*nA B. Put a start'u% #essage in the constructor and override finali7eA B to %rint a shut'down #essage. Make a se%arate thread class that calls )ystem!gcA B and )ystem!r*nFinali7ationA B inside r*nA B, %rinting a #essage as it does so. Make several thread ob0ects o" both ty%es and run the# to see what ha%%ens. RFSURF STIJLT+(6PTE5M?TIM3@U

!+5) Modi"y )haringI!8ava to add a synchroni7e' block inside


the r*nA B #ethod o" T(o-o*nter instead o" synchroni1ing the entire r*nA B #ethod. RFSURFSTIJLT+(6PTE5M?TIM3MU

!+6) +reate two Threa' subclasses, one with a r*nA B that starts
u% , ca%tures the re"erence o" the second Threa' ob0ect and then calls (aitA B. The other class r*nA B should ca%ture the re"erence o" the "irst Threa' ob0ect. Its r*nA B should call notifyAllA B "or the "irst thread a"ter so#e nu#ber o" seconds have %assed, so the "irst thread can %rint a #essage. RFSURF STIJLT+(6PTE5M?TIM3KU

!,7) In -o*nter@!8ava inside TickerI, re#ove the yiel'A B and


e&%lain the results. 5e%lace the yiel'A B with a sleepA B and e&%lain the results. RFSURFSTIJLT+(6PTE5M?TIM3LU

!,() In Threa'"ro*p>!8ava, re%lace the call to sys!s*spen'A B


with a call to (aitA B "or the thread grou%, causing it to wait "or two seconds. Eor this to work correctly you #ust acAuire the lock "or sys inside a synchroni7e' block. RFSURF STIJLT+(6PTE5M?TIM3?U

!,!) +hange

aemons!8ava so that mainA B has a sleepA B instead o" a rea'+ineA B. E&%eri#ent with di""erent slee% ti#es to see
what ha%%ens. RFSURFSTIJLT+(6PTE5M?TIM3HU

!,*) In +ha%ter I, locate the "reenho*se-ontrols!8ava e&a#%le,


which consists o" three "iles. In &vent!8ava, the class &vent is based on watching the ti#e. +hange &vent so that it is a Threa',

Cha ter 14! Multi le Threads

;35

and change the rest o" the design so that it works with this new Threa''based &vent. RFSURFSTIJLT+(6PTE5M?TIM33U

!,+) Modi"y E&ercise G so that the 8ava!*til!Timer class "ound in


J7> M.L is used to run the syste#. RFSURF STIJLT+(6PTE5M?TIM3GU

!,,) Starting with )ine0ave!8ava "ro# +ha%ter ML, create a


%rogra# *an a%%letFa%%lication using the -onsole class, that draws an ani#ated sine wave that a%%ears to scrolls %ast the viewing window like an oscillosco%e, driving the ani#ation with a Threa'. The s%eed o" the ani#ation should be controlled with a 8ava!s(ing!J)li'er control. RFSURFSTIJLT+(6PTE5M?TIM3IU

!,-) Modi"y E&ercise 2 so that #ulti%le sine wave %anels are created
within the a%%lication. The nu#ber o" sine wave %anels should be controlled by (TMD tags or co##and'line %ara#eters. RFSURF STIJLT+(6PTE5M?TIM32U

!,4) Modi"y E&ercise 2 so that the 8ava!s(ing!Timer class is used


to drive the ani#ation. Cote the di""erence between this and 8ava! *til!Timer. RFSURFSTIJLT+(6PTE5M?TIMG@U

!,5) Modi"y )impleThrea'!8ava so that all the threads are


dae#on threads, and veri"y that the %rogra# ends as soon as mainA B is able to e&it. RFSU

;37

(,: Distributed Com.uting


RFSTIJLT+(6PTE5MHTI@U(istorically, %rogra##ing across #ulti%le #achines has been error'%rone, di""icult, and co#%le&.
The %rogra##er had to know #any details about the network and so#eti#es even the hardware. /ou usually needed to understand the various !layers$ o" the networking %rotocol, and there were a lot o" di""erent "unctions in each di""erent networking library concerned with connecting, %acking, and un%acking blocks o" in"or#ation; shi%%ing those blocks back and "orth; and handshaking. It was a daunting task. RFSURF STIJLT+(6PTE5MHTIMU (owever, the basic idea o" distributed co#%uting is not so di""icult, and is abstracted very nicely in the Java libraries. /ou want to=

8et so#e in"or#ation "ro# that #achine over there and #ove it
to this #achine here, or vice versa. This is acco#%lished with basic network %rogra##ing. RFSURFSTIJLT+(6PTE5MHTIKU

+onnect to a database, which #ay live across a network. This is acco#%lished with Java %ata0ase Connectivit) *J7B+,, which is
an abstraction away "ro# the #essy, %lat"or#'s%eci"ic details o" SeD *the structured #uer) language used "or #ost database transactions,. RFSURFSTIJLT+(6PTE5MHTILU

Provide services via a :eb server. This is acco#%lished with Java s servlets and Java Server Pages *JSPs,. RFSURF
STIJLT+(6PTE5MHTI?U

E&ecute #ethods on Java ob0ects that live on re#ote #achines


trans%arently, as i" those ob0ects were resident on local #achines.

;38

This is acco#%lished with Java s -emote Method Invocation *5MI,. RFSURFSTIJLT+(6PTE5MHTIHU

4se code written in other languages, running on other architectures. This is acco#%lished using the Common Ob>ect -e#uest 0roker "rchitecture *+)5B6,, which is directly
su%%orted by Java. RFSURFSTIJLT+(6PTE5MHTI3U

Isolate business logic "ro# connectivity issues, es%ecially


connections with databases including transaction #anage#ent and security. This is acco#%lished using Enter rise Java0eans *EJBs,. EJBs are not actually a distributed architecture, but the resulting a%%lications are usually used in a networked client' server syste#. RFSURFSTIJLT+(6PTE5MHTIGU

Easily, dyna#ically, add and re#ove devices "ro# a network


re%resenting a local syste#. This is acco#%lished with Java s Jini. RFSURFSTIJLT+(6PTE5MHTIIU Each to%ic will be given a light introduction in this cha%ter. Please note that each sub0ect is volu#inous and by itsel" the sub0ect o" entire books, so this cha%ter is only #eant to "a#iliari1e you with the to%ics, not #ake you an e&%ert *however, you can go a long way with the in"or#ation %resented here on network %rogra##ing, servlets and JSPs,. RFSURF STIJLT+(6PTE5MHTI2U

2etwork .rogramming
)ne o" Java s great strengths is %ainless networking. The Java network library designers have #ade it Auite si#ilar to reading and writing "iles, e&ce%t that the !"ile$ e&ists on a re#ote #achine and the re#ote #achine can decide e&actly what it wants to do about the in"or#ation you re reAuesting or sending. 6s #uch as %ossible, the underlying details o" networking have been abstracted away and taken care o" within the JVM and local #achine installation o" Java. The %rogra##ing #odel you use is that o" a "ile; in "act, you actually wra% the network connection *a !socket$, with strea# ob0ects, so you end u% using the sa#e #ethod calls as you do with all other strea#s. In addition, Java s built'in #ultithreading is e&ce%tionally handy when dealing with another

;3:

Thinking in Java

,,,'0ruceEckel'com

networking issue= handling #ulti%le connections at once. RFSURF STIJLT+(6PTE5MHTIM@U This section introduces Java s networking su%%ort using easy'to' understand e&a#%les. RFSURFSTIJLT+(6PTE5MHTIMMU

Identif:ing a machine
)" course, in order to tell one #achine "ro# another and to #ake sure that you are connected with a %articular #achine, there #ust be so#e way o" uniAuely identi"ying #achines on a network. Early networks were satis"ied to %rovide uniAue na#es "or #achines within the local network. (owever, Java works within the Internet, which reAuires a way to uniAuely identi"y a #achine "ro# all the others in the ,orld. This is acco#%lished with the IP *Internet Protocol, address which can e&ist in two "or#s!= RFSURFSTIJLT+(6PTE5MHTIMKU

(-() The "a#iliar 7CS * %omain +ame S)stem, "or#. My do#ain na#e is br*ceeckel!com, and i" I have a co#%uter called .p*s in #y do#ain, its do#ain na#e would be .p*s!br*ceeckel!com. This
is e&actly the kind o" na#e that you use when you send e#ail to %eo%le, and is o"ten incor%orated into a :orld :ide :eb address.

(-!) 6lternatively, you can use the dotted Auad$ "or#, which is "our nu#bers se%arated by dots, such as >IJ!I@@!IY!>ID.
In both cases, the IP address is re%resented internally as a LK'bit nu#ber @ *so each o" the Auad nu#bers cannot e&ceed KHH,, and you can get a s%ecial Java ob0ect to re%resent this nu#ber "ro# either o" the "or#s above by using the static InetA''ress!get2y/ameA B #ethod that s in 8ava!net. The result is an ob0ect o" ty%e InetA''ress that you can use to build a !socket,$ as you will see later. RFSURFSTIJLT+(6PTE5MHTIMLU 6s a si#%le e&a#%le o" using InetA''ress!get2y/ameA B, consider what ha%%ens i" you have a dial'u% Internet service %rovider *ISP,. Each ti#e you dial u%, you are assigned a te#%orary IP address. But while you re connected, your IP address has the sa#e validity as any other IP
@ This #eans a #a&i#u# o" 0ust over "our billion nu#bers, which is ra%idly running out. The new standard "or IP addresses will use a MKI'bit nu#ber, which should %roduce enough uniAue IP addresses "or the "oreseeable "uture.

;3;

address on the Internet. I" so#eone connects to your #achine using your IP address then they can connect to a :eb server or ETP server that you have running on your #achine. )" course, they need to know your IP address, and since a new one is assigned each ti#e you dial u%, how can you "ind out what it isO RFSURFSTIJLT+(6PTE5MHTIM?U The "ollowing %rogra# uses InetA''ress!get2y/ameA B to %roduce your IP address. To use it, you #ust know the na#e o" your co#%uter. )n :indows 2HF2I, go to !Settings,$ !+ontrol Panel,$ !Cetwork,$ and then select the !Identi"ication$ tab. !+o#%uter na#e$ is the na#e to %ut on the co##and line.

//3 c(,3\ho0#$.Hava // Lin!s out your net:ork a!!ress :hen // you2re connecte! to the $nternet. i#"ort Hava.net.B< "ublic class \ho0#$ @ "ublic static voi! #ain-%tringNO args. thro:s E6ce"tion @ if-args.length 4? (. @ %yste#.err."rintln8Ysage3 \ho0#$ Jachine&a#e8.< %yste#.e6it-(.< A $net0!!ress a ? $net0!!ress.getBy&a#e-argsN'O.< %yste#.out."rintln-a.< A A ///3>
In this case, the #achine is called !%e%%y.$ So, once I ve connected to #y ISP I run the %rogra#=

Hava \ho0#$ "e""y


I get back a #essage like this *o" course, the address is di""erent each ti#e,=

"e""y/(CC.(C'.1*.*,

;4=

Thinking in Java

,,,'0ruceEckel'com

I" I tell #y "riend this address and I have a :eb server running on #y co#%uter, he can connect to it by going to the 45D htt !//1;;'1;=':8'85 *only as long as I continue to stay connected during that session,. This can so#eti#es be a handy way to distribute in"or#ation to so#eone else, or to test out a :eb site con"iguration be"ore %osting it to a !real$ server. RFSURFSTIJLT+(6PTE5MHTIMHU

1ervers and clients


The whole %oint o" a network is to allow two #achines to connect and talk to each other. )nce the two #achines have "ound each other they can have a nice, two'way conversation. But how do they "ind each otherO It s like getting lost in an a#use#ent %ark= one #achine has to stay in one %lace and listen while the other #achine says, !(ey, where are youO$ RF SURFSTIJLT+(6PTE5MHTIM3U The #achine that !stays in one %lace$ is called the server, and the one that seeks is called the client. This distinction is i#%ortant only while the client is trying to connect to the server. )nce they ve connected, it beco#es a two'way co##unication %rocess and it doesn t #atter any#ore that one ha%%ened to take the role o" server and the other ha%%ened to take the role o" the client. RFSURFSTIJLT+(6PTE5MHTIMGU So the 0ob o" the server is to listen "or a connection, and that s %er"or#ed by the s%ecial server ob0ect that you create. The 0ob o" the client is to try to #ake a connection to a server, and this is %er"or#ed by the s%ecial client ob0ect you create. )nce the connection is #ade, you ll see that at both server and client ends, the connection is #agically turned into an IF ) strea# ob0ect, and "ro# then on you can treat the connection as i" you were reading "ro# and writing to a "ile. Thus, a"ter the connection is #ade you will 0ust use the "a#iliar IF) co##ands "ro# +ha%ter MM. This is one o" the nice "eatures o" Java networking. RFSURF STIJLT+(6PTE5MHTIMIU

#esting .rograms without a network


Eor #any reasons, you #ight not have a client #achine, a server #achine, and a network available to test your %rogra#s. /ou #ight be %er"or#ing e&ercises in a classroo# situation, or you could be writing %rogra#s that aren t yet stable enough to %ut onto the network. The creators o" the

;41

Internet Protocol were aware o" this issue, and they created a s%ecial address called localhost to be the !local loo%back$ IP address "or testing without a network. The generic way to %roduce this address in Java is=

$net0!!ress a!!r ? $net0!!ress.getBy&a#e-null.<


I" you hand get2y/ameA B a n*ll, it de"aults to using the localhost. The InetA''ress is what you use to re"er to the %articular #achine, and you #ust %roduce this be"ore you can go any "urther. /ou can t #ani%ulate the contents o" an InetA''ress *but you can %rint the# out, as you ll see in the ne&t e&a#%le,. The only way you can create an InetA''ress is through one o" that class s overloaded static #e#ber #ethods get2y/ameA B *which is what you ll usually use,, getAll2y/ameA B, or get+ocalHostA B. RFSURF STIJLT+(6PTE5MHTIM2U /ou can also %roduce the local loo%back address by handing it the string localhost=

$net0!!ress.getBy&a#e-8localhost8.<
*assu#ing !localhost$ is con"igured in your #achine s !hosts$ table,, or by using its dotted Auad "or# to na#e the reserved IP nu#ber "or the loo%back=

$net0!!ress.getBy&a#e-8( *.'.'.(8.<
6ll three "or#s %roduce the sa#e result. RFSURF STIJLT+(6PTE5MHTIK@U

ort: a uni%ue .lace within the machine


6n IP address isn t enough to identi"y a uniAue server, since #any servers can e&ist on one #achine. Each IP #achine also contains orts, and when you re setting u% a client or a server you #ust choose a %ort where both client and server agree to connect; i" you re #eeting so#eone, the IP address is the neighborhood and the %ort is the bar. RFSURF STIJLT+(6PTE5MHTIKMU The %ort is not a %hysical location in a #achine, but a so"tware abstraction *#ainly "or bookkee%ing %ur%oses,. The client %rogra#

;42

Thinking in Java

,,,'0ruceEckel'com

knows how to connect to the #achine via its IP address, but how does it connect to a desired service *%otentially one o" #any on that #achine,O That s where the %ort nu#bers co#e in as a second level o" addressing. The idea is that i" you ask "or a %articular %ort, you re reAuesting the service that s associated with the %ort nu#ber. The ti#e o" day is a si#%le e&a#%le o" a service. Ty%ically, each service is associated with a uniAue %ort nu#ber on a given server #achine. It s u% to the client to know ahead o" ti#e which %ort nu#ber the desired service is running on. RF SURFSTIJLT+(6PTE5MHTIKKU The syste# services reserve the use o" %orts M through M@K?, so you shouldn t use those or any other %ort that you know to be in use. The "irst choice "or e&a#%les in this book will be %ort I@I@ *in #e#ory o" the venerable old I'bit Intel I@I@ chi% in #y "irst co#%uter, a +PFM #achine,. RFSURFSTIJLT+(6PTE5MHTIKLU

1ockets
The socket is the so"tware abstraction used to re%resent the !ter#inals$ o" a connection between two #achines. Eor a given connection, there s a socket on each #achine, and you can i#agine a hy%othetical !cable$ running between the two #achines with each end o" the !cable$ %lugged into a socket. )" course, the %hysical hardware and cabling between #achines is co#%letely unknown. The whole %oint o" the abstraction is that we don t have to know #ore than is necessary. RFSURF STIJLT+(6PTE5MHTIK?U In Java, you create a socket to #ake the connection to the other #achine, then you get an Inp*t)tream and .*tp*t)tream *or, with the a%%ro%riate converters, $ea'er and 0riter, "ro# the socket in order to be able to treat the connection as an IF) strea# ob0ect. There are two strea#'based socket classes= a )erver)ocket that a server uses to !listen$ "or inco#ing connections and a )ocket that a client uses in order to initiate a connection. )nce a client #akes a socket connection, the )erver)ocket returns *via the acceptA B #ethod, a corres%onding )ocket through which co##unications will take %lace on the server side. Ero# then on, you have a true )ocket to )ocket connection and you treat both ends the sa#e way because they are the sa#e. 6t this %oint, you use the #ethods getInp*t)treamA B and get.*tp*t)treamA B to

;43

%roduce the corres%onding Inp*t)tream and .*tp*t)tream ob0ects "ro# each )ocket. These #ust be wra%%ed inside bu""ers and "or#atting classes 0ust like any other strea# ob0ect described in +ha%ter MM. RFSURF STIJLT+(6PTE5MHTIKHU The use o" the ter# )erver)ocket would see# to be another e&a#%le o" a con"using na#ing sche#e in the Java libraries. /ou #ight think )erver)ocket would be better na#ed !Server+onnector$ or so#ething without the word !Socket$ in it. /ou #ight also think that )erver)ocket and )ocket should both be inherited "ro# so#e co##on base class. Indeed, the two classes do have several #ethods in co##on, but not enough to give the# a co##on base class. Instead, )erver)ocket s 0ob is to wait until so#e other #achine connects to it, then to return an actual )ocket. This is why )erver)ocket see#s to be a bit #isna#ed, since its 0ob isn t really to be a socket but instead to #ake a )ocket ob0ect when so#eone else connects to it. RFSURFSTIJLT+(6PTE5MHTIK3U (owever, the )erver)ocket does create a %hysical !server$ or listening socket on the host #achine. This socket listens "or inco#ing connections and then returns an !established$ socket *with the local and re#ote end%oints de"ined, via the acceptA B #ethod. The con"using %art is that both o" these sockets *listening and established, are associated with the sa#e server socket. The listening socket can acce%t only new connection reAuests and not data %ackets. So while )erver)ocket doesn t #ake #uch sense %rogra##atically, it does !%hysically.$ RFSURF STIJLT+(6PTE5MHTIKGU :hen you create a )erver)ocket, you give it only a %ort nu#ber. /ou don t have to give it an IP address because it s already on the #achine it re%resents. :hen you create a )ocket, however, you #ust give both the IP address and the %ort nu#ber where you re trying to connect. *(owever, the )ocket that co#es back "ro# )erver)ocket!acceptA B already contains all this in"or#ation., RFSURFSTIJLT+(6PTE5MHTIKIU

A sim.le server and client


This e&a#%le #akes the si#%lest use o" servers and clients using sockets. 6ll the server does is wait "or a connection, then uses the )ocket %roduced by that connection to create an Inp*t)tream and .*tp*t)tream. These are converted to a $ea'er and a 0riter, then

;44

Thinking in Java

,,,'0ruceEckel'com

wra%%ed in a 2*ffere'$ea'er and a #rint0riter. 6"ter that, everything it reads "ro# the 2*ffere'$ea'er it echoes to the #rint0riter until it receives the line !EC7,$ at which ti#e it closes the connection. RFSURFSTIJLT+(6PTE5MHTIK2U The client #akes the connection to the server, then creates an

.*tp*t)tream and %er"or#s the sa#e wra%%ing as in the server. Dines o" te&t are sent through the resulting #rint0riter. The client also creates an Inp*t)tream *again, with a%%ro%riate conversions and
wra%%ing, to hear what the server is saying *which, in this case, is 0ust the words echoed back,. RFSURFSTIJLT+(6PTE5MHTIL@U Both the server and client use the sa#e %ort nu#ber and the client uses the local loo%back address to connect to the server on the sa#e #achine so you don t have to test it over a network. *Eor so#e con"igurations, you #ight need to be connected to a network "or the %rogra#s to work, even i" you aren t communicating over that network., RFSURF STIJLT+(6PTE5MHTILMU (ere is the server=

//3 c(,3Jabber%erver.Hava // Wery si#"le server that Hust // echoes :hatever the client sen!s. i#"ort Hava.io.B< i#"ort Hava.net.B< "ublic class Jabber%erver @ // Choose a "ort outsi!e of the range (-(' I3 "ublic static final int PG5T ? 1'1'< "ublic static voi! #ain-%tringNO args. thro:s $GE6ce"tion @ %erver%ocket s ? ne: %erver%ocket-PG5T.< %yste#.out."rintln-8%tarte!3 8 K s.< try @ // Blocks until a connection occurs3 %ocket socket ? s.acce"t-.< try @ %yste#.out."rintln8Connection acce"te!3 8K socket.< Buffere!5ea!er in ?

;45

ne: Buffere!5ea!erne: $n"ut%trea#5ea!ersocket.get$n"ut%trea#-...< // Gut"ut is auto#atically flushe! // by Print\riter3 Print\riter out ? ne: Print\riterne: Buffere!\riterne: Gut"ut%trea#\ritersocket.getGut"ut%trea#-...,true.< :hile -true. @ %tring str ? in.rea!Line-.< if -str.e=uals-8E&D8.. break< %yste#.out."rintln-8Echoing3 8 K str.< out."rintln-str.< A // 0l:ays close the t:o sockets... A finally @ %yste#.out."rintln-8closing...8.< socket.close-.< A A finally @ s.close-.< A A A ///3>
/ou can see that the )erver)ocket 0ust needs a %ort nu#ber, not an IP address *since it s running on this #achine.,. :hen you call acceptA B, the #ethod blocks until so#e client tries to connect to it. That is, it s there waiting "or a connection, but other %rocesses can run *see +ha%ter M?,. :hen a connection is #ade, acceptA B returns with a )ocket ob0ect re%resenting that connection. RFSURFSTIJLT+(6PTE5MHTILKU The res%onsibility "or cleaning u% the sockets is cra"ted care"ully here. I" the )erver)ocket constructor "ails, the %rogra# 0ust Auits *notice we #ust assu#e that the constructor "or )erver)ocket doesn t leave any o%en network sockets lying around i" it "ails,. Eor this case, mainA B thro(s I.&4ception so a try block is not necessary. I" the )erver)ocket constructor is success"ul then all other #ethod calls #ust be guarded in a try6finally block to ensure that, no #atter how the block

;47

Thinking in Java

,,,'0ruceEckel'com

is le"t, the )erver)ocket is %ro%erly closed. RFSURF STIJLT+(6PTE5MHTILLU The sa#e logic is used "or the )ocket returned by acceptA B. I" accept A B "ails, then we #ust assu#e that the )ocket doesn t e&ist or hold any resources, so it doesn t need to be cleaned u%. I" it s success"ul, however, the "ollowing state#ents #ust be in a try6finally block so that i" they "ail the )ocket will still be cleaned u%. +are is reAuired here because sockets use i#%ortant non#e#ory resources, so you #ust be diligent in order to clean the# u% *since there is no destructor in Java to do it "or you,. RF SURFSTIJLT+(6PTE5MHTIL?U Both the )erver)ocket and the )ocket %roduced by acceptA B are %rinted to )ystem!o*t. This #eans that their to)tringA B #ethods are auto#atically called. These %roduce=

%erver%ocketNa!!r?'.'.'.',PG5T?',local"ort?1'1'O %ocketNa!!r?( *.'.'.(,PG5T?('**,local"ort?1'1'O


Shortly, you ll see how these "it together with what the client is doing. RF SURFSTIJLT+(6PTE5MHTILHU The ne&t %art o" the %rogra# looks 0ust like o%ening "iles "or reading and writing e&ce%t that the Inp*t)tream and .*tp*t)tream are created "ro# the )ocket ob0ect. Both the Inp*t)tream and .*tp*t)tream ob0ects are converted to $ea'er and 0riter ob0ects using the !converter$ classes Inp*t)tream$ea'er and .*tp*t)tream0riter, res%ectively. /ou could also have used the Java M.@ Inp*t)tream and .*tp*t)tream classes directly, but with out%ut there s a distinct advantage to using the 0riter a%%roach. This a%%ears with #rint0riter, which has an overloaded constructor that takes a second argu#ent, a boolean "lag that indicates whether to auto#atically "lush the out%ut at the end o" each printlnA B *but not printA B, state#ent. Every ti#e you write to o*t, its bu""er #ust be "lushed so the in"or#ation goes out over the network. Elushing is i#%ortant "or this %articular e&a#%le because the client and server each wait "or a line "ro# the other %arty be"ore %roceeding. I" "lushing doesn t occur, the in"or#ation will not be %ut onto the network until the bu""er is "ull, which causes lots o" %roble#s in this e&a#%le. RFSURFSTIJLT+(6PTE5MHTIL3U

;48

:hen writing network %rogra#s you need to be care"ul about using auto#atic "lushing. Every ti#e you "lush the bu""er a %acket #ust be created and sent. In this case, that s e&actly what we want, since i" the %acket containing the line isn t sent then the handshaking back and "orth between server and client will sto%. Put another way, the end o" a line is the end o" a #essage. But in #any cases, #essages aren t deli#ited by lines so it s #uch #ore e""icient to not use auto "lushing and instead let the built'in bu""ering decide when to build and send a %acket. This way, larger %ackets can be sent and the %rocess will be "aster. RFSURF STIJLT+(6PTE5MHTILGU Cote that, like virtually all strea#s you o%en, these are bu""ered. There s an e&ercise at the end o" this cha%ter to show you what ha%%ens i" you don t bu""er the strea#s *things get slow,. RFSURF STIJLT+(6PTE5MHTILIU The in"inite (hile loo% reads lines "ro# the 2*ffere'$ea'er in and writes in"or#ation to )ystem!o*t and to the #rint0riter o*t. Cote that in and o*t could be any strea#s, they 0ust ha%%en to be connected to the network. RFSURFSTIJLT+(6PTE5MHTIL2U :hen the client sends the line consisting o" !EC7,$ the %rogra# breaks out o" the loo% and closes the )ocket. (ere s the client=

//3 c(,3JabberClient.Hava // Wery si#"le client that Hust sen!s // lines to the server an! rea!s lines // that the server sen!s. i#"ort Hava.net.B< i#"ort Hava.io.B< "ublic class JabberClient @ "ublic static voi! #ain-%tringNO args. thro:s $GE6ce"tion @ // Passing null to getBy&a#e-. "ro!uces the // s"ecial 8Local Loo"back8 $P a!!ress, for // testing on one #achine :/o a net:ork3 $net0!!ress a!!r ? $net0!!ress.getBy&a#e-null.<

;4:

Thinking in Java

,,,'0ruceEckel'com

// 0lternatively, you can use // the a!!ress or na#e3 // $net0!!ress a!!r ? // $net0!!ress.getBy&a#e-8( *.'.'.(8.< // $net0!!ress a!!r ? // $net0!!ress.getBy&a#e-8localhost8.< %yste#.out."rintln-8a!!r ? 8 K a!!r.< %ocket socket ? ne: %ocket-a!!r, Jabber%erver.PG5T.< // auar! everything in a try-finally to #ake // sure that the socket is close!3 try @ %yste#.out."rintln-8socket ? 8 K socket.< Buffere!5ea!er in ? ne: Buffere!5ea!erne: $n"ut%trea#5ea!ersocket.get$n"ut%trea#-...< // Gut"ut is auto#atically flushe! // by Print\riter3 Print\riter out ? ne: Print\riterne: Buffere!\riterne: Gut"ut%trea#\ritersocket.getGut"ut%trea#-...,true.< for-int i ? '< i P ('< i KK. @ out."rintln-8ho:!y 8 K i.< %tring str ? in.rea!Line-.< %yste#.out."rintln-str.< A out."rintln-8E&D8.< A finally @ %yste#.out."rintln-8closing...8.< socket.close-.< A A A ///3>
In mainA B you can see all three ways to %roduce the InetA''ress o" the local loo%back IP address= using n*ll, localhost, or the e&%licit reserved address >IZ!D!D!>. )" course, i" you want to connect to a #achine across a network you substitute that #achine s IP address. :hen the

;4;

InetA''ress a''r is %rinted *via the auto#atic call to its to)tringA B


#ethod, the result is= RFSURFSTIJLT+(6PTE5MHTI?@U

localhost/( *.'.'.(
By handing get2y/ameA B a n*ll, it de"aulted to "inding the localhost, and that %roduced the s%ecial address >IZ!D!D!>. RFSURF STIJLT+(6PTE5MHTI?MU Cote that the )ocket called socket is created with both the InetA''ress and the %ort nu#ber. To understand what it #eans when you %rint one o" these )ocket ob0ects, re#e#ber that an Internet connection is deter#ined uniAuely by these "our %ieces o" data= clientHost, client#ort/*mber, serverHost, and server#ort/*mber. :hen the server co#es u%, it takes u% its assigned %ort *I@I@, on the localhost *MKG.@.@.M,. :hen the client co#es u%, it is allocated to the ne&t available %ort on its #achine, M@GG in this case, which also ha%%ens to be on the sa#e #achine *MKG.@.@.M, as the server. Cow, in order "or data to #ove between the client and server, each side has to know where to send it. There"ore, during the %rocess o" connecting to the !known$ server, the client sends a !return address$ so the server knows where to send its data. This is what you see in the e&a#%le out%ut "or the server side=
%ocketNa!!r?( *.'.'.(,"ort?('**,local"ort?1'1'O

This #eans that the server 0ust acce%ted a connection "ro# MKG.@.@.M on %ort M@GG while listening on its local %ort *I@I@,. )n the client side= RF SURFSTIJLT+(6PTE5MHTI?KU
%ocketNa!!r?localhost/( *.'.'.(,PG5T?1'1',local"ort?('**O

which #eans that the client #ade a connection to MKG.@.@.M on %ort I@I@ using the local %ort M@GG. RFSURFSTIJLT+(6PTE5MHTI?LU /ou ll notice that every ti#e you start u% the client anew, the local %ort nu#ber is incre#ented. It starts at M@KH *one %ast the reserved block o" %orts, and kee%s going u% until you reboot the #achine, at which %oint it starts at M@KH again. *)n 4CIZ #achines, once the u%%er li#it o" the socket range is reached, the nu#bers will wra% around to the lowest available nu#ber again., RFSURFSTIJLT+(6PTE5MHTI??U

;5=

Thinking in Java

,,,'0ruceEckel'com

)nce the )ocket ob0ect has been created, the %rocess o" turning it into a 2*ffere'$ea'er and #rint0riter is the sa#e as in the server *again, in both cases you start with a )ocket,. (ere, the client initiates the conversation by sending the string !howdy$ "ollowed by a nu#ber. Cote that the bu""er #ust again be "lushed *which ha%%ens auto#atically via the second argu#ent to the #rint0riter constructor,. I" the bu""er isn t "lushed, the whole conversation will hang because the initial !howdy$ will never get sent *the bu""er isn t "ull enough to cause the send to ha%%en auto#atically,. Each line that is sent back "ro# the server is written to )ystem!o*t to veri"y that everything is working correctly. To ter#inate the conversation, the agreed'u%on !EC7$ is sent. I" the client si#%ly hangs u%, then the server throws an e&ce%tion. RFSURF STIJLT+(6PTE5MHTI?HU /ou can see that the sa#e care is taken here to ensure that the network resources re%resented by the )ocket are %ro%erly cleaned u%, using a try6finally block. RFSURFSTIJLT+(6PTE5MHTI?3U Sockets %roduce a !dedicated$ connection that %ersists until it is e&%licitly disconnected. *The dedicated connection can still be disconnected une&%licitly i" one side, or an inter#ediary link, o" the connection crashes., This #eans the two %arties are locked in co##unication and the connection is constantly o%en. This see#s like a logical a%%roach to networking, but it %uts an e&tra load on the network. Dater in this cha%ter you ll see a di""erent a%%roach to networking, in which the connections are only te#%orary. RFSURFSTIJLT+(6PTE5MHTI?GU

1erving multi.le clients


The Jabber)erver works, but it can handle only one client at a ti#e. In a ty%ical server, you ll want to be able to deal with #any clients at once. The answer is #ultithreading, and in languages that don t directly su%%ort #ultithreading this #eans all sorts o" co#%lications. In +ha%ter M? you saw that #ultithreading in Java is about as si#%le as %ossible, considering that #ultithreading is a rather co#%le& to%ic. Because threading in Java is reasonably straight"orward, #aking a server that handles #ulti%le clients is relatively easy. RFSURF STIJLT+(6PTE5MHTI?IU

;51

The basic sche#e is to #ake a single )erver)ocket in the server and call acceptA B to wait "or a new connection. :hen acceptA B returns, you take the resulting )ocket and use it to create a new thread whose 0ob is to serve that %articular client. Then you call acceptA B again to wait "or a new client. RFSURFSTIJLT+(6PTE5MHTI?2U In the "ollowing server code, you can see that it looks si#ilar to the Jabber)erver!8ava e&a#%le e&ce%t that all o" the o%erations to serve a %articular client have been #oved inside a se%arate thread class=

//3 c(,3JultiJabber%erver.Hava // 0 server that uses #ultithrea!ing // to han!le any nu#ber of clients. i#"ort Hava.io.B< i#"ort Hava.net.B< class %erveGneJabber e6ten!s Threa! @ "rivate %ocket socket< "rivate Buffere!5ea!er in< "rivate Print\riter out< "ublic %erveGneJabber-%ocket s. thro:s $GE6ce"tion @ socket ? s< in ? ne: Buffere!5ea!erne: $n"ut%trea#5ea!ersocket.get$n"ut%trea#-...< // Enable auto-flush3 out ? ne: Print\riterne: Buffere!\riterne: Gut"ut%trea#\ritersocket.getGut"ut%trea#-..., true.< // $f any of the above calls thro: an // e6ce"tion, the caller is res"onsible for // closing the socket. Gther:ise the threa! // :ill close it. start-.< // Calls run-. A "ublic voi! run-. @ try @

;52

Thinking in Java

,,,'0ruceEckel'com

:hile -true. @ %tring str ? in.rea!Line-.< if -str.e=uals-8E&D8.. break< %yste#.out."rintln-8Echoing3 8 K str.< out."rintln-str.< A %yste#.out."rintln-8closing...8.< A catch-$GE6ce"tion e. @ %yste#.err."rintln-8$G E6ce"tion8.< A finally @ try @ socket.close-.< A catch-$GE6ce"tion e. @ %yste#.err."rintln-8%ocket not close!8.< A A A A "ublic class JultiJabber%erver @ static final int PG5T ? 1'1'< "ublic static voi! #ain-%tringNO args. thro:s $GE6ce"tion @ %erver%ocket s ? ne: %erver%ocket-PG5T.< %yste#.out."rintln-8%erver %tarte!8.< try @ :hile-true. @ // Blocks until a connection occurs3 %ocket socket ? s.acce"t-.< try @ ne: %erveGneJabber-socket.< A catch-$GE6ce"tion e. @ // $f it fails, close the socket, // other:ise the threa! :ill close it3 socket.close-.< A A A finally @ s.close-.< A A

;53

A ///3>
The )erve.neJabber thread takes the )ocket ob0ect that s %roduced by acceptA B in mainA B every ti#e a new client #akes a connection. Then, as be"ore, it creates a 2*ffere'$ea'er and auto'"lushed #rint0riter ob0ect using the )ocket. Einally, it calls the s%ecial Threa' #ethod startA B, which %er"or#s thread initiali1ation and then calls r*nA B. This %er"or#s the sa#e kind o" action as in the %revious e&a#%le= reading so#ething "ro# the socket and then echoing it back until it reads the s%ecial !EC7$ signal. RFSURFSTIJLT+(6PTE5MHTIH@U The res%onsibility "or cleaning u% the socket #ust again be care"ully designed. In this case, the socket is created outside o" the )erve.neJabber so the res%onsibility can be shared. I" the )erve.neJabber constructor "ails, it will 0ust throw the e&ce%tion to the caller, who will then clean u% the thread. But i" the constructor succeeds, then the )erve.neJabber ob0ect takes over res%onsibility "or cleaning u% the thread, in its r*nA B. RFSURFSTIJLT+(6PTE5MHTIHMU Cotice the si#%licity o" the 1*ltiJabber)erver. 6s be"ore, a )erver)ocket is created and acceptA B is called to allow a new connection. But this ti#e, the return value o" acceptA B *a )ocket, is %assed to the constructor "or )erve.neJabber, which creates a new thread to handle that connection. :hen the connection is ter#inated, the thread si#%ly goes away. RFSURFSTIJLT+(6PTE5MHTIHKU I" the creation o" the )erver)ocket "ails, the e&ce%tion is again thrown through mainA B. But i" the creation succeeds, the outer try6finally guarantees its cleanu%. The inner try6catch guards only against the "ailure o" the )erve.neJabber constructor; i" the constructor succeeds, then the )erve.neJabber thread will close the associated socket. RF SURFSTIJLT+(6PTE5MHTIHLU To test that the server really does handle #ulti%le clients, the "ollowing %rogra# creates #any clients *using threads, that connect to the sa#e server. The #a&i#u# nu#ber o" threads allowed is deter#ined by the final int 1AXXTH$&A ).

//3 c(,3JultiJabberClient.Hava // Client that tests the JultiJabber%erver

;54

Thinking in Java

,,,'0ruceEckel'com

// by starting u" #ulti"le clients. i#"ort Hava.net.B< i#"ort Hava.io.B< class JabberClientThrea! e6ten!s Threa! @ "rivate %ocket socket< "rivate Buffere!5ea!er in< "rivate Print\riter out< "rivate static int counter ? '< "rivate int i! ? counterKK< "rivate static int threa!count ? '< "ublic static int threa!Count-. @ return threa!count< A "ublic JabberClientThrea!-$net0!!ress a!!r. @ %yste#.out."rintln-8Jaking client 8 K i!.< threa!countKK< try @ socket ? ne: %ocket-a!!r, JultiJabber%erver.PG5T.< A catch-$GE6ce"tion e. @ %yste#.err."rintln-8%ocket faile!8.< // $f the creation of the socket fails, // nothing nee!s to be cleane! u". A try @ in ? ne: Buffere!5ea!erne: $n"ut%trea#5ea!ersocket.get$n"ut%trea#-...< // Enable auto-flush3 out ? ne: Print\riterne: Buffere!\riterne: Gut"ut%trea#\ritersocket.getGut"ut%trea#-..., true.< start-.< A catch-$GE6ce"tion e. @ // The socket shoul! be close! on any // failures other than the socket // constructor3

;55

try @ socket.close-.< A catch-$GE6ce"tion e . @ %yste#.err."rintln-8%ocket not close!8.< A A // Gther:ise the socket :ill be close! by // the run-. #etho! of the threa!. A "ublic voi! run-. @ try @ for-int i ? '< i P ,< iKK. @ out."rintln-8Client 8 K i! K 83 8 K i.< %tring str ? in.rea!Line-.< %yste#.out."rintln-str.< A out."rintln-8E&D8.< A catch-$GE6ce"tion e. @ %yste#.err."rintln-8$G E6ce"tion8.< A finally @ // 0l:ays close it3 try @ socket.close-.< A catch-$GE6ce"tion e. @ %yste#.err."rintln-8%ocket not close!8.< A threa!count--< // En!ing this threa! A A A "ublic class JultiJabberClient @ static final int J09bTM5E0D% ? I'< "ublic static voi! #ain-%tringNO args. thro:s $GE6ce"tion, $nterru"te!E6ce"tion @ $net0!!ress a!!r ? $net0!!ress.getBy&a#e-null.< :hile-true. @ if-JabberClientThrea!.threa!Count-. P J09bTM5E0D%. ne: JabberClientThrea!-a!!r.<

;57

Thinking in Java

,,,'0ruceEckel'com

Threa!.currentThrea!-..slee"-(''.< A A A ///3>
The Jabber-lientThrea' constructor takes an InetA''ress and uses it to o%en a )ocket. /ou re %robably starting to see the %attern= the )ocket is always used to create so#e kind o" $ea'er andFor 0riter *or Inp*t)tream andFor .*tp*t)tream, ob0ect, which is the only way that the )ocket can be used. */ou can, o" course, write a class or two to auto#ate this %rocess instead o" doing all the ty%ing i" it beco#es %ain"ul., 6gain, startA B %er"or#s thread initiali1ation and calls r*nA B. (ere, #essages are sent to the server and in"or#ation "ro# the server is echoed to the screen. (owever, the thread has a li#ited li"eti#e and eventually co#%letes. Cote that the socket is cleaned u% i" the constructor "ails a"ter the socket is created but be"ore the constructor co#%letes. )therwise the res%onsibility "or calling closeA B "or the socket is relegated to the r*nA B #ethod. RFSURFSTIJLT+(6PTE5MHTIH?U The threa'co*nt kee%s track o" how #any Jabber-lientThrea' ob0ects currently e&ist. It is incre#ented as %art o" the constructor and decre#ented as r*nA B e&its *which #eans the thread is ter#inating,. In 1*ltiJabber-lient!mainA B, you can see that the nu#ber o" threads is tested, and i" there are too #any, no #ore are created. Then the #ethod slee%s. This way, so#e threads will eventually ter#inate and #ore can be created. /ou can e&%eri#ent with 1AXXTH$&A ) to see where your %articular syste# begins to have trouble with too #any connections. RF SURFSTIJLT+(6PTE5MHTIHHU

Datagrams
The e&a#%les you ve seen so "ar use the Transmission Control Protocol *T+P, also known as stream/based sockets,, which is designed "or ulti#ate reliability and guarantees that the data will get there. It allows retrans#ission o" lost data, it %rovides #ulti%le %aths through di""erent routers in case one goes down, and bytes are delivered in the order they are sent. 6ll this control and reliability co#es at a cost= T+P has a high overhead. RFSURFSTIJLT+(6PTE5MHTIH3U

;58

There s a second %rotocol, called <ser %atagram Protocol *47P,, which doesn t guarantee that the %ackets will be delivered and doesn t guarantee that they will arrive in the order they were sent. It s called an !unreliable %rotocol$ *T+P is a !reliable %rotocol$,, which sounds bad, but because it s #uch "aster it can be use"ul. There are so#e a%%lications, such as an audio signal, in which it isn t so critical i" a "ew %ackets are dro%%ed here or there but s%eed is vital. )r consider a ti#e'o"'day server, where it really doesn t #atter i" one o" the #essages is lost. 6lso, so#e a%%lications #ight be able to "ire o"" a 47P #essage to a server and can then assu#e, i" there is no res%onse in a reasonable %eriod o" ti#e, that the #essage was lost. RFSURFSTIJLT+(6PTE5MHTIHGU Ty%ically, you ll do #ost o" your direct network %rogra##ing with T+P, and only occasionally will you use 47P. There s a #ore co#%lete treat#ent o" 47P, including an e&a#%le, in the "irst edition o" this book *available on the +7 5)M bound into this book, or as a "ree download "ro# ,,,'0ruceEckel'com,. RFSURFSTIJLT+(6PTE5MHTIHIU

Csing C$&s from within an a..let


It s %ossible "or an a%%let to cause the dis%lay o" any 45D through the :eb browser the a%%let is running within. /ou can do this with the "ollowing line=

get0""letConte6t-..sho:Docu#ent-u.<
in which * is the U$+ ob0ect. (ere s a si#%le e&a#%le that redirects you to another :eb %age. 6lthough you re 0ust redirected to an (TMD %age, you could also redirect to the out%ut o" a +8I %rogra#. RFSURF STIJLT+(6PTE5MHTIH2U

//3 c(,3%ho:MTJL.Hava // Pa""let co!e?%ho:MTJL :i!th?('' height?,'Q // P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort Hava.net.B< i#"ort Hava.io.B< i#"ort co#.bruceeckel.s:ing.B<

;5:

Thinking in Java

,,,'0ruceEckel'com

"ublic class %ho:MTJL e6ten!s J0""let @ JButton sen! ? ne: JButton-8ao8.< JLabel l ? ne: JLabel-.< "ublic voi! init-. @ Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< sen!.a!!0ctionListener-ne: 0l-..< c".a!!-sen!.< c".a!!-l.< A class 0l i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent ae. @ try @ // This coul! be a Ca$ "rogra# instea! of // an MTJL "age. Y5L u ? ne: Y5L-getDocu#entBase-., 8LetcherLra#e.ht#l8.< // Dis"lay the out"ut of the Y5L using // the \eb bro:ser, as an or!inary "age3 get0""letConte6t-..sho:Docu#ent-u.< A catch-E6ce"tion e. @ l.setTe6t-e.to%tring-..< A A A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: %ho:MTJL-., ('', ,'.< A A ///3>
The beauty o" the U$+ class is how #uch it shields you "ro#. /ou can connect to :eb servers without knowing #uch at all about what s going on under the covers. RFSURFSTIJLT+(6PTE5MHTI3@U

$eading a file from the server


6 variation on the above %rogra# reads a "ile located on the server. In this case, the "ile is s%eci"ied by the client=

//3 c(,3Letcher.Hava // Pa""let co!e?Letcher :i!th?,'' height?)''Q

;5;

// P/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort Hava.net.B< i#"ort Hava.io.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class Letcher e6ten!s J0""let @ JButton fetch$t? ne: JButton-8Letch the Data8.< JTe6tLiel! f ? ne: JTe6tLiel!-8Letcher.Hava8, '.< JTe6t0rea t ? ne: JTe6t0rea-(',I'.< "ublic voi! init-. @ Container c" ? getContentPane-.< c".setLayout-ne: Llo:Layout-..< fetch$t.a!!0ctionListener-ne: LetchL-..< c".a!!-ne: J%crollPane-t..< c".a!!-f.< c".a!!-fetch$t.< A "ublic class LetchL i#"le#ents 0ctionListener @ "ublic voi! actionPerfor#e!-0ctionEvent e. @ try @ Y5L url ? ne: Y5L-getDocu#entBase-., f.getTe6t-..< t.setTe6t-url K 8_n8.< $n"ut%trea# is ? url.o"en%trea#-.< Buffere!5ea!er in ? ne: Buffere!5ea!erne: $n"ut%trea#5ea!er-is..< %tring line< :hile --line ? in.rea!Line-.. 4? null. t.a""en!-line K 8_n8.< A catch-E6ce"tion e6. @ t.a""en!-e6.to%tring-..< A A A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: Letcher-., ,'', )''.< A A ///3>

;7=

Thinking in Java

,,,'0ruceEckel'com

The creation o" the U$+ ob0ect is si#ilar to the %revious e&a#%le9 get oc*ment2aseA B is the starting %oint as be"ore, but this ti#e the na#e o" the "ile is read "ro# the JTe4tFiel'. )nce the U$+ ob0ect is created, its )tring version is %laced in the JTe4tArea so we can see what it looks like. Then an Inp*t)tream is %rocured "ro# the U$+, which in this case will si#%ly %roduce a strea# o" the characters in the "ile. 6"ter converting to a $ea'er and bu""ering, each line is read and a%%ended to the JTe4tArea. Cote that the JTe4tArea has been %laced inside a J)croll#ane so that scrolling is handled auto#atically. RFSURF STIJLT+(6PTE5MHTI3MU

More to networking
There s actually a lot #ore to networking than can be covered in this introductory treat#ent. Java networking also %rovides "airly e&tensive su%%ort "or 45Ds, including %rotocol handlers "or di""erent ty%es o" content that can be discovered at an Internet site. /ou can "ind other Java networking "eatures "ully and care"ully described in Java +et,ork Programming by Elliotte 5usty (arold *) 5eilly, M22G,. RFSURF STIJLT+(6PTE5MHTI3KU

"ava Database Connectivit: 8"D;C9


It has been esti#ated that hal" o" all so"tware develo%#ent involves clientFserver o%erations. 6 great %ro#ise o" Java has been the ability to build %lat"or#'inde%endent clientFserver database a%%lications. This has co#e to "ruition with Java 7ataBase +onnectivity *J7B+,. RFSURF STIJLT+(6PTE5MHTI3LU )ne o" the #a0or %roble#s with databases has been the "eature wars between the database co#%anies. There is a !standard$ database language, Structured euery Danguage *SeD'2K,, but you #ust usually know which database vendor you re working with des%ite the standard. J7B+ is designed to be %lat"or#'inde%endent, so you don t need to worry about the database you re using while you re %rogra##ing. (owever, it s

;71

still %ossible to #ake vendor's%eci"ic calls "ro# J7B+ so you aren t restricted "ro# doing what you #ust. RFSURFSTIJLT+(6PTE5MHTI3?U )ne %lace where %rogra##ers #ay need to use SeD ty%e na#es is in the SeD T0BLE C5E0TE state#ent when they are creating a new database table and de"ining the SeD ty%e "or each colu#n. 4n"ortunately there are signi"icant variations between SeD ty%es su%%orted by di""erent database %roducts. 7i""erent databases that su%%ort SeD ty%es with the sa#e se#antics and structure #ay give those ty%es di""erent na#es. Most #a0or databases su%%ort an SeD data ty%e "or large binary values= in )racle this ty%e is called a LG&a 50\, Sybase calls it $J0aE, In"or#i& calls it B;TE, and 7BK calls it LG&a W05CM05 LG5 B$T D0T0. There"ore, i" database %ortability is a goal you should try to use only generic SeD ty%e identi"iers. RFSURFSTIJLT+(6PTE5MHTI3HU Portability is an issue when writing "or a book where readers #ay be testing the e&a#%les with all kinds o" unknown data stores. I have tried to write these e&a#%les to be as %ortable as %ossible. /ou should also notice that the database's%eci"ic code has been isolated in order to centrali1e any changes that you #ay need to %er"or# to get the e&a#%les o%erational in your environ#ent. RFSURFSTIJLT+(6PTE5MHTI33U J7B+, like #any o" the 6PIs in Java, is designed "or si#%licity. The #ethod calls you #ake corres%ond to the logical o%erations you d think o" doing when gathering data "ro# a database= connect to the database, create a state#ent and e&ecute the Auery, and look at the result set. RF SURFSTIJLT+(6PTE5MHTI3GU To allow this %lat"or# inde%endence, J7B+ %rovides a driver manager that dyna#ically #aintains all the driver ob0ects that your database Aueries will need. So i" you have three di""erent kinds o" vendor databases to connect to, you ll need three di""erent driver ob0ects. The driver ob0ects register the#selves with the driver #anager at the ti#e o" loading, and you can "orce the loading using -lass!for/ameA B. RFSURF STIJLT+(6PTE5MHTI3IU To o%en a database, you #ust create a !database 45D$ that s%eci"ies=

(-*) That you re using J7B+ with !0dbc.$ RFSURF


STIJLT+(6PTE5MHTI32U

;72

Thinking in Java

,,,'0ruceEckel'com

(-+) The !sub%rotocol$= the na#e o" the driver or the na#e o" a
database connectivity #echanis#. Since the design o" J7B+ was ins%ired by )7B+, the "irst sub%rotocol available is the !0dbc'odbc bridge,$ s%eci"ied by !odbc.$ RFSURFSTIJLT+(6PTE5MHTIG@U

(-,) The database identi"ier. This varies with the database driver used,
but it generally %rovides a logical na#e that is #a%%ed by the database ad#inistration so"tware to a %hysical directory where the database tables are located. Eor your database identi"ier to have any #eaning, you #ust register the na#e using your database ad#inistration so"tware. *The %rocess o" registration varies "ro# %lat"or# to %lat"or#., RFSURFSTIJLT+(6PTE5MHTIGMU 6ll this in"or#ation is co#bined into one string, the !database 45D.$ Eor e&a#%le, to connect through the )7B+ sub%rotocol to a database identi"ied as !%eo%le,$ the database 45D could be= RFSURF STIJLT+(6PTE5MHTIGKU

%tring !bYrl ? 8H!bc3o!bc3"eo"le8<


I" you re connecting across a network, the database 45D will contain the connection in"or#ation identi"ying the re#ote #achine and can beco#e a bit inti#idating. (ere is an e&a#%le o" a +loudSca%e database being called "ro# a re#ote client utili1ing 5MI= RFSURF STIJLT+(6PTE5MHTIGLU

H!bc3r#i3//(C .(+1.(*'. *3('CC/H!bc3clou!sca"e3!b


This database 45D is really two 0dbc calls in one. The "irst %art ! H!bc3 r#i3//(C .(+1.(*'. *3('CC/$ uses 5MI to #ake the connection to the re#ote database engine listening on %ort M@22 at IP 6ddress M2K.M3I.MG@.KG. The second %art o" the 45D, ! H!bc3clou!sca"e3!b$ conveys the #ore ty%ical settings using the sub%rotocol and database na#e but this will only ha%%en a"ter the "irst section has #ade the connection via 5MI to the re#ote #achine. RFSURF STIJLT+(6PTE5MHTIG?U :hen you re ready to connect to the database, call the static #ethod river1anager!get-onnectionA B and %ass it the database 45D, the user na#e, and a %assword to get into the database. /ou get back a

;73

-onnection ob0ect that you can then use to Auery and #ani%ulate the
database. RFSURFSTIJLT+(6PTE5MHTIGHU The "ollowing e&a#%le o%ens a database o" contact in"or#ation and looks "or a %erson s last na#e as given on the co##and line. It selects only the na#es o" %eo%le that have e#ail addresses, then %rints out all the ones that #atch the given last na#e=

//3 c(,3H!bc3Looku".Hava // Looks u" e#ail a!!resses in a // local !atabase using JDBC. i#"ort Hava.s=l.B< "ublic class Looku" @ "ublic static voi! #ain-%tringNO args. thro:s %/LE6ce"tion, Class&otLoun!E6ce"tion @ %tring !bYrl ? 8H!bc3o!bc3"eo"le8< %tring user ? 88< %tring "ass:or! ? 88< // Loa! the !river -registers itself. Class.for&a#e8sun.H!bc.o!bc.J!bcG!bcDriver8.< Connection c ? DriverJanager.getConnection!bYrl, user, "ass:or!.< %tate#ent s ? c.create%tate#ent-.< // %/L co!e3 5esult%et r ? s.e6ecute/uery8%ELECT L$5%T, L0%T, EJ0$L 8 K 8L5GJ "eo"le.csv "eo"le 8 K 8\ME5E 8 K 8-L0%T?28 K argsN'O K 82. 8 K 8 0&D -EJ0$L $s &ot &ull. 8 K 8G5DE5 B; L$5%T8.< :hile-r.ne6t-.. @ // Ca"italiUation !oesn2t #atter3 %yste#.out."rintlnr.get%tring-8Last8. K 8, 8 K r.get%tring-8f$5%T8. K 83 8 K r.get%tring-8EJ0$L8. .< A

;74

Thinking in Java

,,,'0ruceEckel'com

s.close-.< // 0lso closes 5esult%et A A ///3>


/ou can see the creation o" the database 45D as %reviously described. In this e&a#%le, there is no %assword %rotection on the database so the user na#e and %assword are e#%ty strings. RFSURFSTIJLT+(6PTE5MHTIG3U )nce the connection is #ade with river1anager!get-onnectionA B, you can use the resulting -onnection ob0ect to create a )tatement ob0ect using the create)tatementA B #ethod. :ith the resulting )tatement, you can call e4ec*te3*eryA B, %assing in a string containing an SeD'2K standard SeD state#ent. */ou ll see shortly how you can generate this state#ent auto#atically, so you don t have to know #uch about SeD., RFSURFSTIJLT+(6PTE5MHTIGGU The e4ec*te3*eryA B #ethod returns a $es*lt)et ob0ect, which is an iterator= the ne4tA B #ethod #oves the iterator to the ne&t record in the state#ent, or returns false i" the end o" the result set has been reached. /ou ll always get a $es*lt)et ob0ect back "ro# e4ec*te3*eryA B even i" a Auery results in an e#%ty set *that is, an e&ce%tion is not thrown,. Cote that you #ust call ne4tA B once be"ore trying to read any record data. I" the result set is e#%ty, this "irst call to ne4tA B will return false. Eor each record in the result set, you can select the "ields using *a#ong other a%%roaches, the "ield na#e as a string. 6lso note that the ca%itali1ation o" the "ield na#e is ignored9it doesn t #atter with an SeD database. /ou deter#ine the ty%e you ll get back by calling getIntA B, get)tringA B, getFloatA B, etc. 6t this %oint, you ve got your database data in Java native "or#at and can do whatever you want with it using ordinary Java code. RFSURFSTIJLT+(6PTE5MHTIGIU

'etting the e0am.le to work


:ith J7B+, understanding the code is relatively si#%le. The con"using %art is #aking it work on your %articular syste#. The reason this is con"using is that it reAuires you to "igure out how to get your J7B+ driver to load %ro%erly, and how to set u% a database using your database ad#inistration so"tware. RFSURFSTIJLT+(6PTE5MHTIG2U

;75

)" course, this %rocess can vary radically "ro# #achine to #achine, but the %rocess I used to #ake it work under LK'bit :indows #ight give you clues to hel% you attack your own situation. RFSURF STIJLT+(6PTE5MHTII@U

1te. (: <ind the "D;C Driver


The %rogra# above contains the state#ent=

Class.for&a#e-8sun.H!bc.o!bc.J!bcG!bcDriver8.<
This i#%lies a directory structure, which is deceiving. :ith this %articular installation o" J7> M.M, there was no "ile called J'bc.'bc river!class, so i" you looked at this e&a#%le and went searching "or it you d be "rustrated. )ther %ublished e&a#%les use a %seudo na#e, such as !#y7river.+lassCa#e,$ which is less than hel%"ul. In "act, the load state#ent above "or the 0dbc'odbc driver *the only one that actually co#es with the J7>, a%%ears in only a "ew %laces in the online docu#entation *in %articular, a %age labeled !J7B+')7B+ Bridge 7river$,. I" the load state#ent above doesn t work, then the na#e #ight have been changed as %art o" a Java version change, so you should hunt through the docu#entation again. RFSURFSTIJLT+(6PTE5MHTIIMU I" the load state#ent is wrong, you ll get an e&ce%tion at this %oint. To test whether your driver load state#ent is working correctly, co##ent out the code a"ter the state#ent and u% to the catch clause; i" the %rogra# throws no e&ce%tions it #eans that the driver is loading %ro%erly. RFSURF STIJLT+(6PTE5MHTIIKU

1te. !: Configure the database


6gain, this is s%eci"ic to LK'bit :indows; you #ight need to do so#e research to "igure it out "or your own %lat"or#. RFSURF STIJLT+(6PTE5MHTIILU Eirst, o%en the control %anel. /ou #ight "ind two icons that say !)7B+.$ /ou #ust use the one that says !LKbit )7B+,$ since the other one is "or backward co#%atibility with M3'bit )7B+ so"tware and will %roduce no results "or J7B+. :hen you o%en the !LKbit )7B+$ icon, you ll see a tabbed dialog with a nu#ber o" tabs, including !4ser 7SC,$ !Syste# 7SC,$ !Eile 7SC,$ etc., in which !7SC$ #eans !7ata Source Ca#e.$ It

;77

Thinking in Java

,,,'0ruceEckel'com

turns out that "or the J7B+')7B+ bridge, the only %lace where it s i#%ortant to set u% your database is !Syste# 7SC,$ but you ll also want to test your con"iguration and create Aueries, and "or that you ll also need to set u% your database in !Eile 7SC.$ This will allow the Microso"t euery tool *that co#es with Microso"t )""ice, to "ind the database. Cote that other Auery tools are also available "ro# other vendors. RFSURF STIJLT+(6PTE5MHTII?U The #ost interesting database is one that you re already using. Standard )7B+ su%%orts a nu#ber o" di""erent "ile "or#ats including such venerable workhorses as 7Base. (owever, it also includes the si#%le !co##a'se%arated 6S+II$ "or#at, which virtually every data tool has the ability to write. In #y case, I 0ust took #y !%eo%le$ database that I ve been #aintaining "or years using various contact'#anage#ent tools and e&%orted it as a co##a'se%arated 6S+II "ile *these ty%ically have an e&tension o" !csv,. In the !Syste# 7SC$ section I chose !6dd,$ chose the te&t driver to handle #y co##a'se%arated 6S+II "ile, and then un' checked !use current directory$ to allow #e to s%eci"y the directory where I e&%orted the data "ile. RFSURFSTIJLT+(6PTE5MHTIIHU /ou ll notice when you do this that you don t actually s%eci"y a "ile, only a directory. That s because a database is ty%ically re%resented as a collection o" "iles under a single directory *although it could be re%resented in other "or#s as well,. Each "ile usually contains a single table, and the SeD state#ents can %roduce results that are culled "ro# #ulti%le tables in the database *this is called a >oin,. 6 database that contains only a single table *like #y !%eo%le$ database, is usually called a $lat/$ile database. Most %roble#s that go beyond the si#%le storage and retrieval o" data generally reAuire #ulti%le tables that #ust be related by 0oins to %roduce the desired results, and these are called relational databases. RFSURFSTIJLT+(6PTE5MHTII3U

1te. *: #est the configuration


To test the con"iguration you ll need a way to discover whether the database is visible "ro# a %rogra# that Aueries it. )" course, you can si#%ly run the J7B+ %rogra# e&a#%le above, u% to and including the state#ent=

Connection c ? DriverJanager.getConnection-

;78

!bYrl, user, "ass:or!.<


I" an e&ce%tion is thrown, your con"iguration was incorrect. RFSURF STIJLT+(6PTE5MHTIIGU (owever, it s use"ul to get a Auery'generation tool involved at this %oint. I used Microso"t euery that ca#e with Microso"t )""ice, but you #ight %re"er so#ething else. The Auery tool #ust know where the database is, and Microso"t euery reAuired that I go to the )7B+ 6d#inistrator s !Eile 7SC$ tab and add a new entry there, again s%eci"ying the te&t driver and the directory where #y database lives. /ou can na#e the entry anything you want, but it s hel%"ul to use the sa#e na#e you used in !Syste# 7SC. $ RFSURFSTIJLT+(6PTE5MHTIIIU )nce you ve done this, you will see that your database is available when you create a new Auery using your Auery tool. RFSURF STIJLT+(6PTE5MHTII2U

1te. +: 'enerate :our 1R& %uer:


The Auery that I created using Microso"t euery not only showed #e that #y database was there and in good order, but it also auto#atically created the SeD code that I needed to insert into #y Java %rogra#. I wanted a Auery that would search "or records that had the last na#e that was ty%ed on the co##and line when starting the Java %rogra#. So as a starting %oint, I searched "or a s%eci"ic last na#e, !Eckel.$ I also wanted to dis%lay only those na#es that had e#ail addresses associated with the#. The ste%s I took to create this Auery were=

(--) Start a new Auery and use the euery :i1ard. Select the !%eo%le$
database. *This is the eAuivalent o" o%ening the database connection using the a%%ro%riate database 45D.,

(-4) Select the !%eo%le$ table within the database. Ero# within the
table, choose the colu#ns EI5ST, D6ST, and EM6ID.

(-5) 4nder !Eilter 7ata,$ choose D6ST and select !eAuals$ with an
argu#ent o" !Eckel.$ +lick the !6nd$ radio button.

(-6) +hoose EM6ID and select !Is not Cull.$ (47) 4nder !Sort By,$ choose EI5ST.

;7:

Thinking in Java

,,,'0ruceEckel'com

The result o" this Auery will show you whether you re getting what you want. RFSURFSTIJLT+(6PTE5MHTI2@U Cow you can %ress the SeD button and without any research on your %art, u% will %o% the correct SeD code, ready "or you to cut and %aste. Eor this Auery, it looked like this=

%ELECT "eo"le.L$5%T, "eo"le.L0%T, "eo"le.EJ0$L L5GJ "eo"le.csv "eo"le \ME5E -"eo"le.L0%T?2Eckel2. 0&D -"eo"le.EJ0$L $s &ot &ull. G5DE5 B; "eo"le.L$5%T
Es%ecially with #ore co#%licated Aueries it s easy to get things wrong, but by using a Auery tool you can interactively test your Aueries and auto#atically generate the correct code. It s hard to argue the case "or doing this by hand. RFSURFSTIJLT+(6PTE5MHTI2MU

1te. ,: Modif: and .aste in :our %uer:


/ou ll notice that the code above looks di""erent "ro# what s used in the %rogra#. That s because the Auery tool uses "ull Auali"ication "or all o" the na#es, even when there s only one table involved. *:hen #ore than one table is involved, the Auali"ication %revents collisions between colu#ns "ro# di""erent tables that have the sa#e na#es., Since this Auery involves only one table, you can o%tionally re#ove the !%eo%le$ Auali"ier "ro# #ost o" the na#es, like this= RFSURFSTIJLT+(6PTE5MHTI2KU

%ELECT L$5%T, L0%T, EJ0$L L5GJ "eo"le.csv "eo"le \ME5E -L0%T?2Eckel2. 0&D -EJ0$L $s &ot &ull. G5DE5 B; L$5%T
In addition, you don t want this %rogra# to be hard coded to look "or only one na#e. Instead, it should hunt "or the na#e given as the co##and' line argu#ent. Making these changes and turning the SeD state#ent into a dyna#ically'created )tring %roduces= RFSURF STIJLT+(6PTE5MHTI2LU

8%ELECT L$5%T, L0%T, EJ0$L 8 K 8L5GJ "eo"le.csv "eo"le 8 K

;7;

8\ME5E 8 K 8-L0%T?28 K argsN'O K 82. 8 K 8 0&D -EJ0$L $s &ot &ull. 8 K 8G5DE5 B; L$5%T8.<
SeD has another way to insert na#es into a Auery called stored rocedures, which is used "or s%eed. But "or #uch o" your database e&%eri#entation and "or your "irst cut, building your own Auery strings in Java is "ine. RFSURFSTIJLT+(6PTE5MHTI2?U /ou can see "ro# this e&a#%le that by using the tools currently available 9in %articular the Auery'building tool9database %rogra##ing with SeD and J7B+ can be Auite straight"orward. RFSURF STIJLT+(6PTE5MHTI2HU

A 'CI version of the looku. .rogram


It s #ore use"ul to leave the looku% %rogra# running all the ti#e and si#%ly switch to it and ty%e in a na#e whenever you want to look so#eone u%. The "ollowing %rogra# creates the looku% %rogra# as an a%%licationFa%%let, and it also adds na#e co#%letion so the data will show u% without "orcing you to ty%e the entire last na#e=

//3 c(,3H!bc3WLooku".Hava // aY$ version of Looku".Hava. // Pa""let co!e?WLooku" // :i!th?,'' height? ''QP/a""letQ i#"ort Hava6.s:ing.B< i#"ort Hava.a:t.B< i#"ort Hava.a:t.event.B< i#"ort Hava6.s:ing.event.B< i#"ort Hava.s=l.B< i#"ort co#.bruceeckel.s:ing.B< "ublic class WLooku" e6ten!s J0""let @ %tring !bYrl ? 8H!bc3o!bc3"eo"le8< %tring user ? 88< %tring "ass:or! ? 88< %tate#ent s<

;8=

Thinking in Java

,,,'0ruceEckel'com

JTe6tLiel! searchLor ? ne: JTe6tLiel!- '.< JLabel co#"letion ? ne: JLabel-8 8.< JTe6t0rea results ? ne: JTe6t0rea-I', '.< "ublic voi! init-. @ searchLor.getDocu#ent-..a!!Docu#entListenerne: %earchL-..< JPanel " ? ne: JPanel-.< ".a!!-ne: Label-8Last na#e to search for38..< ".a!!-searchLor.< ".a!!-co#"letion.< Container c" ? getContentPane-.< c".a!!-", Bor!erLayout.&G5TM.< c".a!!-results, Bor!erLayout.CE&TE5.< try @ // Loa! the !river -registers itself. Class.for&a#e8sun.H!bc.o!bc.J!bcG!bcDriver8.< Connection c ? DriverJanager.getConnection!bYrl, user, "ass:or!.< s ? c.create%tate#ent-.< A catch-E6ce"tion e. @ results.setTe6t-e.to%tring-..< A A class %earchL i#"le#ents Docu#entListener @ "ublic voi! change!Y"!ate-Docu#entEvent e.@A "ublic voi! insertY"!ate-Docu#entEvent e.@ te6tWalueChange!-.< A "ublic voi! re#oveY"!ate-Docu#entEvent e.@ te6tWalueChange!-.< A A "ublic voi! te6tWalueChange!-. @ 5esult%et r< if-searchLor.getTe6t-..length-. ?? '. @ co#"letion.setTe6t-88.< results.setTe6t-88.< return< A

;81

try @ // &a#e co#"letion3 r ? s.e6ecute/uery8%ELECT L0%T L5GJ "eo"le.csv "eo"le 8 K 8\ME5E -L0%T Like 28 K searchLor.getTe6t-. K 8V2. G5DE5 B; L0%T8.< if-r.ne6t-.. co#"letion.setTe6tr.get%tring-8last8..< r ? s.e6ecute/uery8%ELECT L$5%T, L0%T, EJ0$L 8 K 8L5GJ "eo"le.csv "eo"le 8 K 8\ME5E -L0%T?28 K co#"letion.getTe6t-. K 82. 0&D -EJ0$L $s &ot &ull. 8 K 8G5DE5 B; L$5%T8.< A catch-E6ce"tion e. @ results.setTe6tsearchLor.getTe6t-. K 8_n8.< results.a""en!-e.to%tring-..< return< A results.setTe6t-88.< try @ :hile-r.ne6t-.. @ results.a""en!r.get%tring-8Last8. K 8, 8 K r.get%tring-8f$5%T8. K 83 8 K r.get%tring-8EJ0$L8. K 8_n8.< A A catch-E6ce"tion e. @ results.setTe6t-e.to%tring-..< A A "ublic static voi! #ain-%tringNO args. @ Console.run-ne: WLooku"-., ,'', ''.< A A ///3>

;82

Thinking in Java

,,,'0ruceEckel'com

Much o" the database logic is the sa#e, but you can see that a oc*ment+istener is added to listen to the JTe4tFiel' *see the 8ava4!s(ing!JTe4tFiel' entry in the Java (TMD docu#entation "ro# >ava'sun'com "or details,, so that whenever you ty%e a new character it "irst tries to do a na#e co#%letion by looking u% the last na#e in the database and using the "irst one that shows u%. *It %laces it in the completion J+abel, and uses that as the looku% te&t., This way, as soon as you ve ty%ed enough characters "or the %rogra# to uniAuely "ind the na#e you re looking "or, you can sto%. RFSURFSTIJLT+(6PTE5MHTI23U

Wh: the "D;C A I seems so com.le0


:hen you browse the online docu#entation "or J7B+ it can see# daunting. In %articular, in the atabase1eta ata inter"ace9which is 0ust huge, contrary to #ost o" the inter"aces you see in Java9there are #ethods such as 'ata efinition-a*sesTransaction-ommitA B, get1a4-ol*mn/ame+engthA B, get1a4)tatement+engthA B, stores1i4e'-ase3*ote'I'entifiersA B, s*pportsA/)I?IInterme'iate)3+A B, s*pports+imite'.*terJoinsA B, and so on. :hat s this all aboutO RF SURFSTIJLT+(6PTE5MHTI2GU 6s #entioned earlier, databases have see#ed "ro# their ince%tion to be in a constant state o" tur#oil, %ri#arily because the de#and "or database a%%lications, and thus database tools, is so great. )nly recently has there been any convergence on the co##on language o" SeD *and there are %lenty o" other database languages in co##on use,. But even with an SeD !standard$ there are so #any variations on that the#e that J7B+ #ust %rovide the large atabase1eta ata inter"ace so that your code can discover the ca%abilities o" the %articular !standard$ SeD database that it s currently connected to. In short, you can write si#%le, trans%ortable SeD, but i" you want to o%ti#i1e s%eed your coding will #ulti%ly tre#endously as you investigate the ca%abilities o" a %articular vendor s database. RFSURFSTIJLT+(6PTE5MHTI2IU This, o" course, is not Java s "ault. The discre%ancies between database %roducts are 0ust so#ething that J7B+ tries to hel% co#%ensate "or. But

;83

bear in #ind that your li"e will be easier i" you can either write generic Aueries and not worry Auite as #uch about %er"or#ance, or, i" you #ust tune "or %er"or#ance, know the %lat"or# you re writing "or so you don t need to write all that investigation code. RFSURF STIJLT+(6PTE5MHTI22U

A more so.histicated e0am.le


6 #ore interesting e&a#%le@ involves a #ultitable database that resides on a server. (ere, the database is #eant to %rovide a re%ository "or co##unity activities and to allow %eo%le to sign u% "or these events, so it is called the Communit) Interests %atabase *+I7,. This e&a#%le will only %rovide an overview o" the database and its i#%le#entation, and is not intended to be an in'de%th tutorial on database develo%#ent. There are nu#erous books, se#inars, and so"tware %ackages that will hel% you in the design and develo%#ent o" a database. RFSURF STIJLT+(6PTE5MHTIM@@U In addition, this e&a#%le %resu#es the %rior installation o" an SeD database on a server *although it could also be run on a local #achine,, and the interrogation and discovery o" an a%%ro%riate J7B+ driver "or that database. Several "ree SeD databases are available, and so#e are even auto#atically installed with various "lavors o" Dinu&. /ou are res%onsible "or #aking the choice o" database and locating the J7B+ driver; the e&a#%le here is based on an SeD database syste# called !+loudsca%e .$ ,$ which can be "reely downloaded "or develo%#ent *not

de%loy#ent, "ro# htt%=FFwww.+loudsca%e.co#. /ou ll need to "ollow the instructions in the download in order to %ro%erly install and set u% +loudsca%e.RFSURFSTIJLT+(6PTE5MHTIM@MU
To kee% changes in the connection in"or#ation si#%le, the database driver, database 45D, user na#e, and %assword are %laced in a se%arate class=

//3 c(,3H!bc3C$DConnect.Hava // Database connection infor#ation for // the co##unity interests !atabase -C$D..
@ +reated by 7ave Bartlett.

;84

Thinking in Java

,,,'0ruceEckel'com

"ublic class C$DConnect @ // 0ll the infor#ation s"ecific to Clou!%ca"e3 "ublic static %tring !bDriver ? 8CGJ.clou!sca"e.core.JDBCDriver8< "ublic static %tring !bY5L ? 8H!bc3clou!sca"e3!3/!ocs/b:ork/J%a"ienDB8< "ublic static %tring user ? 88< "ublic static %tring "ass:or! ? 88< A ///3>
In this e&a#%le, there is no %assword %rotection on the database so the user na#e and %assword are e#%ty strings. :ith +loudsca%e, the

'bU$+ contains the directory %ath where the database is located, but other RFSURFSTIJLT+(6PTE5MHTIM@KU 7BMSs and J7B+ drivers will use other ways to encode this in"or#ation. This e&a#%le assu#es that the database !JSa%ien7B$ has already been created, but in order to get the e&a#%le to work you ll need to use the cvie( tool that co#es with +loudsca%e in order to create the new database, and then you #ust change the above 'bU$+ to re"lect the %ath o" the database you created.
The database consists o" a set o" tables that have a structure as shown here=
EVTMEMS MEM_ID EVT_ID MEM_ORD EVENTS EVT_ID TITLE (IE) TYPE LOC_ID PRICE DATETIME

MEMBERS MEM_ID MEM_UNAME (AK) MEM_LNAME (IE) MEM_FNAME (IE) ADDRESS CITY STATE ZIP PHONE EMAIL LOCATIONS LOC_ID NAME (IE) CONTACT ADDRESS CITY STATE ZIP PHONE DIRECTIONS

;85

!Me#bers$ contains co##unity #e#ber in"or#ation, !Events$ and !Docations$ contain in"or#ation about the activities and where they take %lace, and !Evt#e#s$ connects events and #e#bers that would like to attend that event. /ou can see that a data #e#ber in one table %roduces a key in another table. RFSURFSTIJLT+(6PTE5MHTIM@LU The "ollowing class contains the SeD strings that will create these database tables *re"er to an SeD guide "or an e&%lanation o" the SeD code,= RFSURFSTIJLT+(6PTE5MHTIM@?U

//3 c(,3H!bc3C$D%/L.Hava // %/L strings to create the tables for the C$D. "ublic class C$D%/L @ "ublic static %tringNO s=l ? @ // Create the JEJBE5% table3 8!ro" table JEJBE5%8, 8create table JEJBE5% 8 K 8-JEJb$D $&TEaE5 "ri#ary key, 8 K 8JEJbY&0JE W05CM05-( . not null uni=ue, 8K 8JEJbL&0JE W05CM05-I'., 8 K 8JEJbL&0JE W05CM05- '., 8 K 80DD5E%% W05CM05-I'., 8 K 8C$T; W05CM05- '., 8 K 8%T0TE CM05-I., 8 K 8T$P CM05-,., 8 K 8PMG&E CM05-( ., 8 K 8EJ0$L W05CM05-)'..8, 8create uni=ue in!e6 8 K 8L&0JEb$D9 on JEJBE5%-JEJbL&0JE.8, // Create the EWE&T% table 8!ro" table EWE&T%8, 8create table EWE&T% 8 K 8-EWTb$D $&TEaE5 "ri#ary key, 8 K 8EWTbT$TLE W05CM05-)'. not null, 8 K 8EWTbT;PE W05CM05- '., 8 K 8LGCb$D $&TEaE5, 8 K 8P5$CE DEC$J0L, 8 K 8D0TET$JE T$JE%T0JP.8, 8create uni=ue in!e6 8 K 8T$TLEb$D9 on EWE&T%-EWTbT$TLE.8,

;87

Thinking in Java

,,,'0ruceEckel'com

// Create the EWTJEJ% table 8!ro" table EWTJEJ%8, 8create table EWTJEJ% 8 K 8-JEJb$D $&TEaE5 not null, 8 K 8EWTb$D $&TEaE5 not null, 8 K 8JEJbG5D $&TEaE5.8, 8create uni=ue in!e6 8 K 8EWTJEJb$D9 on EWTJEJ%-JEJb$D, EWTb$D.8, // Create the LGC0T$G&% table 8!ro" table LGC0T$G&%8, 8create table LGC0T$G&% 8 K 8-LGCb$D $&TEaE5 "ri#ary key, 8 K 8LGCb&0JE W05CM05-)'. not null, 8 K 8CG&T0CT W05CM05-,'., 8 K 80DD5E%% W05CM05-I'., 8 K 8C$T; W05CM05- '., 8 K 8%T0TE W05CM05-I., 8 K 8T$P W05CM05-,., 8 K 8PMG&E CM05-( ., 8 K 8D$5ECT$G&% W05CM05-I'C+..8, 8create uni=ue in!e6 8 K 8&0JEb$D9 on LGC0T$G&%-LGCb&0JE.8, A< A ///3>
The "ollowing %rogra# uses the -I -onnect and -I )3+ in"or#ation to load the J7B+ driver, #ake a connection to the database, and then create the table structure diagra##ed above. To connect with the database, you call the static #ethod river1anager!get-onnection A B, %assing it the database 45D, the user na#e, and a %assword to get into the database. /ou get back a -onnection ob0ect that you can use to Auery and #ani%ulate the database. )nce the connection is #ade you can si#%ly %ush the SeD to the database, in this case by #arching through the -I )3+ array. (owever, the "irst ti#e this %rogra# is run, the !dro% table$ co##and will "ail, causing an e&ce%tion, which is caught, re%orted, and then ignored. The reason "or the !dro% table$ co##and is to allow easy e&%eri#entation= you can #odi"y the SeD that de"ines the tables and then rerun the %rogra#, causing the old tables to be re%laced by the new. RFSURFSTIJLT+(6PTE5MHTIM@HU

;88

In this e&a#%le, it #akes sense to let the e&ce%tions be thrown out to the console=

//3 c(,3H!bc3C$DCreateTables.Hava // Creates !atabase tables for the // co##unity interests !atabase. i#"ort Hava.s=l.B< "ublic class C$DCreateTables @ "ublic static voi! #ain-%tringNO args. thro:s %/LE6ce"tion, Class&otLoun!E6ce"tion, $llegal0ccessE6ce"tion @ // Loa! the !river -registers itself. Class.for&a#e-C$DConnect.!bDriver.< Connection c ? DriverJanager.getConnectionC$DConnect.!bY5L, C$DConnect.user, C$DConnect."ass:or!.< %tate#ent s ? c.create%tate#ent-.< for-int i ? '< i P C$D%/L.s=l.length< iKK. @ %yste#.out."rintln-C$D%/L.s=lNiO.< try @ s.e6ecuteY"!ate-C$D%/L.s=lNiO.< A catch-%/LE6ce"tion s=lE6. @ %yste#.err."rintln8Probably a 2!ro" table2 faile!8.< A A s.close-.< c.close-.< A A ///3>
Cote that all changes in the database can be controlled by changing

)trings in the -I )3+ table, without #odi"ying -I -reateTables. RF


SURFSTIJLT+(6PTE5MHTIM@3U

e4ec*teUp'ateA B will usually return the nu#ber o" rows that were a""ected by the SeD state#ent. e4ec*teUp'ateA B is #ore co##only used to e&ecute $&%E5T, YPD0TE, or DELETE state#ents that #odi"y one or #ore rows. Eor state#ents such as C5E0TE T0BLE, D5GP T0BLE, and

;8:

Thinking in Java

,,,'0ruceEckel'com

C5E0TE $&DE9, e4ec*teUp'ateA B always returns 1ero. RFSURF


STIJLT+(6PTE5MHTIM@GU To test the database, it is loaded with so#e sa#%le data. This reAuires a series o" $&%E5Ts "ollowed by a %ELECT to %roduce result set. To #ake additions and changes to the test data easy, the test data is set u% as a two'di#ensional array o" .b8ects, and the e4ec*teInsertA B #ethod can then use the in"or#ation in one row o" the table to create the a%%ro%riate SeD co##and.

//3 c(,3H!bc3Loa!DB.Hava // Loa!s an! tests the !atabase. i#"ort Hava.s=l.B< class Test%et @ GbHectNONO !ata ? @ @ 8JEJBE5%8, ne: $nteger-(., 8!bartlett8, 8Bartlett8, 8Davi!8, 8( ) Jockingbir! Lane8, 8aettysburg8, 8P08, 8(C)( 8, 8( ).I,+.*1C'8, 8bartRyou.net8 A, @ 8JEJBE5%8, ne: $nteger- ., 8beckel8, 8Eckel8, 8Bruce8, 8( ) Gver 5ainbo: Lane8, 8Creste! Butte8, 8CG8, 81( I8, 8( ).I,+.*1C'8, 8beckelRyou.net8 A, @ 8JEJBE5%8, ne: $nteger-)., 8rcastane!a8, 8Castane!a8, 85obert8, 8( ) Do:nun!er Lane8, 8%y!ney8, 8&%\8, 8( )I,8, 8( ).I,+.*1C'8, 8rcastane!aRyou.net8 A, @ 8LGC0T$G&%8, ne: $nteger-(., 8Center for 0rts8, 8Betty \right8, 8( ) Elk 0ve.8, 8Creste! Butte8, 8CG8, 81( I8, 8( ).I,+.*1C'8, 8ao this :ay then that.8 A, @ 8LGC0T$G&%8, ne: $nteger- ., 8\itts En! Conference Center8, 8John \ittig8, 8( ) Jusic Drive8, 8Toneville8, 8P08, 8(C( )8,

;8;

8( ).I,+.*1C'8, 8ao that :ay then this.8 A, @ 8EWE&T%8, ne: $nteger-(., 8ProHect Janage#ent Jyths8, 8%oft:are Develo"#ent8, ne: $nteger-(., ne: Lloat- .,'., 8 '''-'*-(* (C3)'3''8 A, @ 8EWE&T%8, ne: $nteger- ., 8Life of the Creste! Dog8, 80rcheology8, ne: $nteger- ., ne: Lloat-'.''., 8 '''-'*-(C (C3''3''8 A, // Jatch so#e "eo"le :ith events @ 8EWTJEJ%8, ne: $nteger-(., // Dave is going to ne: $nteger-(., // the %oft:are event. ne: $nteger-'. A, @ 8EWTJEJ%8, ne: $nteger- ., // Bruce is going to ne: $nteger- ., // the 0rcheology event. ne: $nteger-'. A, @ 8EWTJEJ%8, ne: $nteger-)., // 5obert is going to ne: $nteger-(., // the %oft:are event. ne: $nteger-(. A, @ 8EWTJEJ%8, ne: $nteger-)., // ... an! ne: $nteger- ., // the 0rcheology event. ne: $nteger-(. A, A< // Yse the !efault !ata set3 "ublic Test%et-. @A // Yse a !ifferent !ata set3 "ublic Test%et-GbHectNONO !at. @ !ata ? !at< A A "ublic class Loa!DB @ %tate#ent state#ent< Connection connection< Test%et tset< "ublic Loa!DB-Test%et t. thro:s %/LE6ce"tion @

;:=

Thinking in Java

,,,'0ruceEckel'com

tset ? t< try @ // Loa! the !river -registers itself. Class.for&a#e-C$DConnect.!bDriver.< A catch-Hava.lang.Class&otLoun!E6ce"tion e. @ e."rint%tackTrace-%yste#.err.< A connection ? DriverJanager.getConnectionC$DConnect.!bY5L, C$DConnect.user, C$DConnect."ass:or!.< state#ent ? connection.create%tate#ent-.< A "ublic voi! cleanu"-. thro:s %/LE6ce"tion @ state#ent.close-.< connection.close-.< A "ublic voi! e6ecute$nsert-GbHectNO !ata. @ %tring s=l ? 8insert into 8 K !ataN'O K 8 values-8< for-int i ? (< i P !ata.length< iKK. @ if-!ataNiO instanceof %tring. s=l K? 828 K !ataNiO K 828< else s=l K? !ataNiO< if-i P !ata.length - (. s=l K? 8, 8< A s=l K? 2.2< %yste#.out."rintln-s=l.< try @ state#ent.e6ecuteY"!ate-s=l.< A catch-%/LE6ce"tion s=lE6. @ %yste#.err."rintln-8$nsert faile!.8.< :hile -s=lE6 4? null. @ %yste#.err."rintln-s=lE6.to%tring-..< s=lE6 ? s=lE6.get&e6tE6ce"tion-.< A A A "ublic voi! loa!-. @ for-int i ? '< iP tset.!ata.length< iKK.

;:1

e6ecute$nsert-tset.!ataNiO.< A // Thro: e6ce"tions out to console3 "ublic static voi! #ain-%tringNO args. thro:s %/LE6ce"tion @ Loa!DB !b ? ne: Loa!DB-ne: Test%et-..< !b.loa!-.< try @ // aet a 5esult%et fro# the loa!e! !atabase3 5esult%et rs ? !b.state#ent.e6ecute/uery8select 8 K 8e.EWTbT$TLE, #.JEJbL&0JE, #.JEJbL&0JE 8K 8fro# EWE&T% e, JEJBE5% #, EWTJEJ% e# 8 K 8:here e#.EWTb$D ? 8 K 8an! e.EWTb$D ? e#.EWTb$D 8 K 8an! #.JEJb$D ? e#.JEJb$D8.< :hile -rs.ne6t-.. %yste#.out."rintlnrs.get%tring-(. K 8 8 K rs.get%tring- . K 8, 8 K rs.get%tring-)..< A finally @ !b.cleanu"-.< A A A ///3>
The Test)et class contains a de"ault set o" data that is %roduced i" you use the de"ault constructor; however, you can also create a Test)et ob0ect using an alternate data set with the second constructor. The set o" data is held in a two'di#ensional array o" .b8ect because it can be any ty%e, including )tring or nu#erical ty%es. The e4ec*teInsertA B #ethod uses 5TTI to distinguish between )tring data *which #ust be Auoted, and non' )tring data as it builds the SeD co##and "ro# the data. 6"ter %rinting this co##and to the console, e4ec*teUp'ateA B is used to send it to the database. RFSURFSTIJLT+(6PTE5MHTIM@IU The constructor "or +oa' 2 #akes the connection, and loa'A B ste%s through the data and calls e4ec*teInsertA B "or each record. clean*pA B closes the state#ent and the connection; to guarantee that this is called, it is %laced inside a "inally clause. RFSURFSTIJLT+(6PTE5MHTIM@2U

;:2

Thinking in Java

,,,'0ruceEckel'com

)nce the database is loaded, an e4ec*te3*eryA B state#ent %roduces a sa#%le result set. Since the Auery co#bines several tables, it is an e&a#%le o" a 0oin. RFSURFSTIJLT+(6PTE5MHTIMM@U There is #ore J7B+ in"or#ation available in the electronic docu#ents that co#e as %art o" the Java distribution "ro# Sun. In addition, you can "ind #ore in the book J%0C %atabase "ccess ,ith Java *(a#ilton, +attel, and Eisher, 6ddison':esley, M22G,. )ther J7B+ books a%%ear regularly. RFSURFSTIJLT+(6PTE5MHTIMMMU

1ervlets
+lient access "ro# the Internet or cor%orate intranets is a sure way to allow #any users to access data and resources easily @. This ty%e o" access is based on clients using the :orld :ide :eb standards o" (y%erte&t Marku% Danguage *(TMD, and (y%erte&t Trans"er Protocol *(TTP,. The Servlet 6PI set abstracts a co##on solution "ra#ework "or res%onding to (TTP reAuests. RFSURFSTIJLT+(6PTE5MHTIMMKU Traditionally, the way to handle a %roble# such as allowing an Internet client to u%date a database is to create an (TMD %age with te&t "ields and a !sub#it$ button. The user ty%es the a%%ro%riate in"or#ation into the te&t "ields and %resses the !sub#it$ button. The data is sub#itted along with a 45D that tells the server what to do with the data by s%eci"ying the location o" a +o##on 8ateway Inter"ace *+8I, %rogra# that the server runs, %roviding the %rogra# with the data as it is invoked. The +8I %rogra# is ty%ically written in Perl, Python, +, +<<, or any language that can read "ro# standard in%ut and write to standard out%ut. That s all that is %rovided by the :eb server= the +8I %rogra# is invoked, and standard strea#s *or, o%tionally "or in%ut, an environ#ent variable, are used "or in%ut and out%ut. The +8I %rogra# is res%onsible "or everything else. Eirst it looks at the data and decides whether the "or#at is correct. I" not, the +8I %rogra# #ust %roduce (TMD to describe the %roble#; this %age is handed to the :eb server *via standard out%ut "ro# the +8I %rogra#,, which sends it back to the user. The user #ust usually back u% a %age and try again. I" the data is correct, the +8I %rogra# %rocesses the data in an
@ 7ave Bartlett was instru#ental in the develo%#ent o" this #aterial, and also the JSP section.

;:3

a%%ro%riate way, %erha%s adding it to a database. It #ust then %roduce an a%%ro%riate (TMD %age "or the :eb server to return to the user. RFSURF STIJLT+(6PTE5MHTIMMLU It would be ideal to go to a co#%letely Java'based solution to this %roble#9an a%%let on the client side to validate and send the data, and a servlet on the server side to receive and %rocess the data. 4n"ortunately, although a%%lets are a %roven technology with %lenty o" su%%ort, they have been %roble#atic to use on the :eb because you cannot rely on a %articular version o" Java being available on a client s :eb browser; in "act, you can t rely on a :eb browser su%%orting Java at all. In an intranet, you can reAuire that certain su%%ort be available, which allows a lot #ore "le&ibility in what you can do, but on the :eb the sa"est a%%roach is to handle all the %rocessing on the server side and deliver %lain (TMD to the client. That way, no client will be denied the use o" your site because they do not have the %ro%er so"tware installed. RFSURF STIJLT+(6PTE5MHTIMM?U Because servlets %rovide an e&cellent solution "or server'side %rogra##ing su%%ort, they are one o" the #ost %o%ular reasons "or #oving to Java. Cot only do they %rovide a "ra#ework that re%laces +8I %rogra##ing *and eli#inates a nu#ber o" thorny +8I %roble#s,, but all your code has the %lat"or# %ortability gained "ro# using Java, and you have access to all the Java 6PIs *e&ce%t, o" course, the ones that %roduce 84Is, like Swing,. RFSURFSTIJLT+(6PTE5MHTIMMHU

#he basic servlet


The architecture o" the servlet 6PI is that o" a classic service %rovider with a serviceA B #ethod through which all client reAuests will be sent by the servlet container so"tware, and li"e cycle #ethods initA B and 'estroyA B, which are called only when the servlet is loaded and unloaded *this ha%%ens rarely,. RFSURFSTIJLT+(6PTE5MHTIMM3U

"ublic interface %ervlet @ "ublic voi! init-%ervletConfig config. thro:s %ervletE6ce"tion< "ublic %ervletConfig get%ervletConfig-.< "ublic voi! service-%ervlet5e=uest re=,

;:4

Thinking in Java

,,,'0ruceEckel'com

%ervlet5es"onse res. thro:s %ervletE6ce"tion, $GE6ce"tion< "ublic %tring get%ervlet$nfo-.< "ublic voi! !estroy-.< A get)ervlet-onfigA B s sole %ur%ose is to return a )ervlet-onfig ob0ect that contains initiali1ation and startu% %ara#eters "or this servlet. get)ervletInfoA B returns a string containing in"or#ation about the servlet, such as author, version, and co%yright. RFSURF STIJLT+(6PTE5MHTIMMGU
The "eneric)ervlet class is a shell i#%le#entation o" this inter"ace and is ty%ically not used. The Http)ervlet class is an e&tension o" "eneric)ervlet and is designed s%eci"ically to handle the (TTP %rotocol9 Http)ervlet is the one that you ll use #ost o" the ti#e. RF SURFSTIJLT+(6PTE5MHTIMMIU The #ost convenient attribute o" the servlet 6PI is the au&iliary ob0ects that co#e along with the (tt%Servlet class to su%%ort it. I" you look at the serviceA B #ethod in the )ervlet inter"ace, you ll see it has two %ara#eters= )ervlet$eC*est and )ervlet$esponse. :ith the Http)ervlet class these two ob0ect are e&tended "or (TTP= Http)ervlet$eC*est and Http)ervlet$esponse. (ere s a si#%le e&a#%le that shows the use o" Http)ervlet$esponse=

//3 c(,3servlets3%ervlets5ule.Hava i#"ort Hava6.servlet.B< i#"ort Hava6.servlet.htt".B< i#"ort Hava.io.B< "ublic class %ervlets5ule e6ten!s Mtt"%ervlet @ int i ? '< // %ervlet 8"ersistence8 "ublic voi! service-Mtt"%ervlet5e=uest re=, Mtt"%ervlet5es"onse res. thro:s $GE6ce"tion @ res.setContentTy"e-8te6t/ht#l8.< Print\riter out ? res.get\riter-.< out."rint-8PME0DQPT$TLEQ8.< out."rint-80 server-si!e strategy8.< out."rint-8P/T$TLEQP/ME0DQPBGD;Q8.< out."rint-8Ph(Q%ervlets 5ule4 8 K iKK.<

;:5

out."rint-8P/h(QP/BGD;Q8.< out.close-.< A A ///3> )ervlets$*le is about as si#%le as a servlet can get. The servlet is initiali1ed only once by calling its initA B #ethod, on loading the servlet
a"ter the servlet container is "irst booted u%. :hen a client #akes a reAuest to a 45D that ha%%ens to re%resent a servlet, the servlet container interce%ts this reAuest and #akes a call to the serviceA B #ethod, a"ter setting u% the Http)ervlet$eC*est and Http)ervlet$esponse ob0ects. RFSURFSTIJLT+(6PTE5MHTIMM2U The #ain res%onsibility o" the serviceA B #ethod is to interact with the (TTP reAuest that the client has sent, and to build an (TTP res%onse based on the attributes contained within the reAuest. )ervlets$*le only #ani%ulates the res%onse ob0ect without looking at what the client #ay have sent. RFSURFSTIJLT+(6PTE5MHTIMK@U 6"ter setting the content ty%e o" the res%onse *which #ust always be done be"ore the 0riter or .*tp*t)tream is %rocured,, the get0riterA B #ethod o" the res%onse ob0ect %roduces a #rint0riter ob0ect, which is used "or writing character'based res%onse data *alternatively, get.*tp*t)treamA B %roduces an .*tp*t)tream, used "or binary res%onse, which is only utili1ed in #ore s%eciali1ed solutions,. RFSURF STIJLT+(6PTE5MHTIMKMU The rest o" the %rogra# si#%ly sends (TMD back to the client *it s assu#ed you understand (TMD, so that %art is not e&%lained, as a seAuence o" )trings. (owever, notice the inclusion o" the !hit counter$ re%resented by the variable i. This is auto#atically converted to a )tring in the printA B state#ent. RFSURFSTIJLT+(6PTE5MHTIMKKU :hen you run the %rogra#, you ll notice that the value o" i is retained between reAuests to the servlet. This is an essential %ro%erty o" servlets= since only one servlet o" a %articular class is loaded into the container, and it is never unloaded *unless the servlet container is ter#inated, which is so#ething that only nor#ally ha%%ens i" you reboot the server co#%uter,, any "ields o" that servlet class e""ectively beco#e %ersistent ob0ects. This #eans that you can e""ortlessly #aintain values between

;:7

Thinking in Java

,,,'0ruceEckel'com

servlet reAuests, whereas with +8I you had to write values to disk in order to %reserve the#, which reAuired a "air a#ount o" "ooling around to get it right, and resulted in a non'cross'%lat"or# solution. RFSURF STIJLT+(6PTE5MHTIMKLU )" course, so#eti#es the :eb server, and thus the servlet container, #ust be rebooted as %art o" #aintenance or during a %ower "ailure. To avoid losing any %ersistent in"or#ation, the servlet s initA B and 'estroy A B #ethods are auto#atically called whenever the servlet is loaded or unloaded, giving you the o%%ortunity to save data during shutdown, and restore it a"ter rebooting. The servlet container calls the 'estroyA B #ethod as it is ter#inating itsel", so you always get an o%%ortunity to save valuable data as long as the server #achine is con"igured in an intelligent way. RFSURFSTIJLT+(6PTE5MHTIMK?U There s one other issue when using Http)ervlet. This class %rovides 'o"etA B and 'o#ostA B #ethods that di""erentiate between a +8I !8ET$ sub#ission "ro# the client, and a +8I !P)ST.$ 8ET and P)ST vary only in the details o" the way that they sub#it the data, which is so#ething that I %ersonally would %re"er to ignore. (owever, #ost %ublished in"or#ation that I ve seen see#s to "avor the creation o" se%arate 'o"et A B and 'o#ostA B #ethods instead o" a single generic serviceA B #ethod, which handles both cases. This "avoritis# see#s Auite co##on, but I ve never seen it e&%lained in a "ashion that leads #e to believe that it s anything #ore than inertia "ro# +8I %rogra##ers who are used to %aying attention to whether a 8ET or P)ST is being used. So in the s%irit o" !doing the si#%lest thing that could %ossibly work,$ @ I will 0ust use the serviceA B #ethod in these e&a#%les, and let it care about 8ETs vs. P)STs. (owever, kee% in #ind that I #ight have #issed so#ething and so there #ay in "act be a good reason to use 'o"etA B and 'o#ostA B instead. RFSURFSTIJLT+(6PTE5MHTIMKHU :henever a "or# is sub#itted to a servlet, the Http)ervlet$eC*est co#es %reloaded with all the "or# data, stored as key'value %airs. I" you know the na#es o" the "ields, you can 0ust use the# directly with the get#arameterA B #ethod to look u% the values. /ou can also get an &n*meration *the old "or# o" the Iterator, to the "ield na#es, as is shown in the "ollowing e&a#%le. This e&a#%le also de#onstrates how a
@ 6 %ri#ary tenet o" E&tre#e Progra##ing *ZP,. See ,,,'* rogramming'com.

;:8

single servlet can be used to %roduce the %age that contains the "or#, and to res%ond to the %age *a better solution will be seen later, with JSPs,. I" the &n*meration is e#%ty, there are no "ields; this #eans no "or# was sub#itted. In this case, the "or# is %roduced, and the sub#it button will re'call the sa#e servlet. I" "ields do e&ist, however, they are dis%layed.

//3 c(,3servlets3EchoLor#.Hava // Du#"s the na#e-value "airs of any MTJL for# i#"ort Hava6.servlet.B< i#"ort Hava6.servlet.htt".B< i#"ort Hava.io.B< i#"ort Hava.util.B< "ublic class EchoLor# e6ten!s Mtt"%ervlet @ "ublic voi! service-Mtt"%ervlet5e=uest re=, Mtt"%ervlet5es"onse res. thro:s $GE6ce"tion @ res.setContentTy"e-8te6t/ht#l8.< Print\riter out ? res.get\riter-.< Enu#eration fl!s ? re=.getPara#eter&a#es-.< if-4fl!s.hasJoreEle#ents-.. @ // &o for# sub#itte! -- create one3 out."rint-8Pht#lQ8.< out."rint-8Pfor# #etho!?_8PG%T_88 K 8 action?_8EchoLor#_8Q8.< for-int i ? '< i P ('< iKK. out."rint-8PbQLiel!8 K i K 8P/bQ 8 K 8Pin"ut ty"e?_8te6t_88K 8 siUe?_8 '_8 na#e?_8Liel!8 K i K 8_8 value?_8Walue8 K i K 8_8QPbrQ8.< out."rint-8P$&PYT T;PE?sub#it na#e?sub#it8K 8 Walue?_8%ub#it_8QP/for#QP/ht#lQ8.< A else @ out."rint-8Ph(Q;our for# containe!3P/h(Q8.< :hile-fl!s.hasJoreEle#ents-.. @ %tring fiel!? -%tring.fl!s.ne6tEle#ent-.< %tring value? re=.getPara#eter-fiel!.< out."rint-fiel! K 8 ? 8 K valueK 8PbrQ8.< A A out.close-.< A

;::

Thinking in Java

,,,'0ruceEckel'com

A ///3>
)ne drawback you ll notice here is that Java does not see# to be designed with string %rocessing in #ind9the "or#atting o" the return %age is %ain"ul because o" line breaks, esca%ing Auote #arks, and the !<$ signs necessary to build )tring ob0ects. :ith a larger (TMD %age it beco#es unreasonable to code it directly into Java. )ne solution is to kee% the %age as a se%arate te&t "ile, then o%en it and hand it to the :eb server. I" you have to %er"or# any kind o" substitution to the contents o" the %age, it s not #uch better since Java has treated string %rocessing so %oorly. In these cases you re %robably better o"" using a #ore a%%ro%riate solution *Python would be #y choice; there s a version that e#beds itsel" in Java called JPython, to generate the res%onse %age. RFSURF STIJLT+(6PTE5MHTIMK3U

1ervlets and multithreading


The servlet container has a %ool o" threads that it will dis%atch to handle client reAuests. It is Auite likely that two clients arriving at the sa#e ti#e could be %rocessing through your serviceA B at the sa#e ti#e. There"ore the serviceA B #ethod #ust written in a thread'sa"e #anner. 6ny access to co##on resources *"iles, databases, will need to be guarded by using the synchroni7e' keyword. RFSURFSTIJLT+(6PTE5MHTIMKGU The "ollowing si#%le e&a#%le %uts a synchroni7e' clause around the thread s sleepA B #ethod. This will block all other threads until the allotted ti#e *"ive seconds, is all used u%. :hen testing this you should start several browser instances and hit this servlet as Auickly as %ossible in each one9you ll see that each one has to wait until its turn co#es u%.

//3 c(,3servlets3Threa!%ervlet.Hava i#"ort Hava6.servlet.B< i#"ort Hava6.servlet.htt".B< i#"ort Hava.io.B< "ublic class Threa!%ervlet e6ten!s Mtt"%ervlet @ int i< "ublic voi! service-Mtt"%ervlet5e=uest re=, Mtt"%ervlet5es"onse res. thro:s $GE6ce"tion @ res.setContentTy"e-8te6t/ht#l8.<

;:;

Print\riter out ? res.get\riter-.< synchroniUe!-this. @ try @ Threa!.currentThrea!-..slee"-,'''.< A catch-$nterru"te!E6ce"tion e. @ %yste#.err."rintln-8$nterru"te!8.< A A out."rint-8Ph(QLinishe! 8 K iKK K 8P/h(Q8.< out.close-.< A A ///3>
It is also %ossible to synchroni1e the entire servlet by %utting the synchroni7e' keyword in "ront o" the serviceA B #ethod. In "act, the only reason to use the synchroni7e' clause instead is i" the critical section is in an e&ecution %ath that #ight not get e&ecuted. In that case, you #ight as well avoid the overhead o" synchroni1ing every ti#e by using a synchroni7e' clause. )therwise, all the threads will have to wait anyway so you #ight as well synchroni7e the whole #ethod. RFSURF STIJLT+(6PTE5MHTIMKIU

>andling sessions with servlets


(TTP is a !sessionless$ %rotocol, so you cannot tell "ro# one server hit to another i" you ve got the sa#e %erson re%eatedly Auerying your site, or i" it is a co#%letely di""erent %erson. 6 great deal o" e""ort has gone into #echanis#s that will allow :eb develo%ers to track sessions. +o#%anies could not do e'co##erce without kee%ing track o" a client and the ite#s they have %ut into their sho%%ing cart, "or e&a#%le. RFSURF STIJLT+(6PTE5MHTIMK2U There are several #ethods o" session tracking, but the #ost co##on #ethod is with %ersistent !cookies,$ which are an integral %art o" the Internet standards. The (TTP :orking 8rou% o" the Internet Engineering Task Eorce has written cookies into the o""icial standard in 5E+ KM@2 * ds'internic'net/r$c/r$c21=;'t*t or check ,,,'cookiecentral' com,. RFSURFSTIJLT+(6PTE5MHTIML@U

;;=

Thinking in Java

,,,'0ruceEckel'com

6 cookie is nothing #ore than a s#all %iece o" in"or#ation sent by a :eb server to a browser. The browser stores the cookie on the local disk, and whenever another call is #ade to the 45D that the cookie is associated with, the cookie is Auietly sent along with the call, thus %roviding the desired in"or#ation back to that server *generally, %roviding so#e way that the server can be told that it s you calling,. +lients can, however, turn o"" the browser s ability to acce%t cookies. I" your site #ust track a client who has turned o"" cookies, then another #ethod o" session tracking *45D rewriting or hidden "or# "ields, #ust be incor%orated by hand, since the session tracking ca%abilities built into the servlet 6PI are designed around cookies. RFSURFSTIJLT+(6PTE5MHTIMLMU

#he $ookie class


The servlet 6PI *version K.@ and u%, %rovides the -ookie class. This class incor%orates all the (TTP header details and allows the setting o" various cookie attributes. 4sing the cookie is si#%ly a #atter o" adding it to the res%onse ob0ect. The constructor takes a cookie na#e as the "irst argu#ent and a value as the second. +ookies are added to the res%onse ob0ect be"ore you send any content.

Cookie oreo ? ne: Cookie-8T$Java8, 8 '''8.< res.a!!Cookie-oreocookie.<


+ookies are recovered by calling the get-ookiesA B #ethod o" the Http)ervlet$eC*est ob0ect, which returns an array o" cookie ob0ects.

CookieNO cookies ? re=.getCookies-.<


/ou can then call getVal*eA B "or each cookie, to %roduce a )tring containing the cookie contents. In the above e&a#%le, getVal*e AMTIJavaMB will %roduce a )tring containing !K@@@.$ RFSURF STIJLT+(6PTE5MHTIMLKU

#he Session class


6 session is one or #ore %age reAuests by a client to a :eb site during a de"ined %eriod o" ti#e. I" you buy groceries online, "or e&a#%le, you want a session to be con"ined to the %eriod "ro# when you "irst add an ite# to !#y sho%%ing cart$ to the %oint where you check out. Each ite# you add to the sho%%ing cart will result in a new (TTP connection, which has no

;;1

knowledge o" %revious connections or ite#s in the sho%%ing cart. To co#%ensate "or this lack o" in"or#ation, the #echanics su%%lied by the cookie s%eci"ication allow your servlet to %er"or# session tracking. RF SURFSTIJLT+(6PTE5MHTIMLLU 6 servlet )ession ob0ect lives on the server side o" the co##unication channel; its goal is to ca%ture use"ul data about this client as the client #oves through and interacts with your :eb site. This data #ay be %ertinent "or the %resent session, such as ite#s in the sho%%ing cart, or it #ay be data such as authentication in"or#ation that was entered when the client "irst entered your :eb site, and which should not have to be reentered during a %articular set o" transactions. RFSURF STIJLT+(6PTE5MHTIML?U The )ession class o" the servlet 6PI uses the -ookie class to do its work. (owever, all the )ession ob0ect needs is so#e kind o" uniAue identi"ier stored on the client and %assed to the server. :eb sites #ay also use the other ty%es o" session tracking but these #echanis#s will be #ore di""icult to i#%le#ent as they are not enca%sulated into the servlet 6PI *that is, you #ust write the# by hand to deal with the situation when the client has disabled cookies,. RFSURFSTIJLT+(6PTE5MHTIMLHU (ere s an e&a#%le that i#%le#ents session tracking with the servlet 6PI=

//3 c(,3servlets3%essionPeek.Hava // Ysing the Mtt"%ession class. i#"ort Hava.io.B< i#"ort Hava.util.B< i#"ort Hava6.servlet.B< i#"ort Hava6.servlet.htt".B< "ublic class %essionPeek e6ten!s Mtt"%ervlet @ "ublic voi! service-Mtt"%ervlet5e=uest re=, Mtt"%ervlet5es"onse res. thro:s %ervletE6ce"tion, $GE6ce"tion @ // 5etrieve %ession GbHect before any // out"ut is sent to the client. Mtt"%ession session ? re=.get%ession-.< res.setContentTy"e-8te6t/ht#l8.< Print\riter out ? res.get\riter-.< out."rintln-8PME0DQPT$TLEQ %essionPeek 8.<

;;2

Thinking in Java

,,,'0ruceEckel'com

out."rintln-8 P/T$TLEQP/ME0DQPBGD;Q8.< out."rintln-8Ph(Q %essionPeek P/h(Q8.< // 0 si#"le hit counter for this session. $nteger ival ? -$nteger. session.get0ttribute-8sess"eek.cntr8.< if-ival??null. ival ? ne: $nteger-(.< else ival ? ne: $nteger-ival.intWalue-. K (.< session.set0ttribute-8sess"eek.cntr8, ival.< out."rintln-8;ou have hit this "age PbQ8 K ival K 8P/bQ ti#es.P"Q8.< out."rintln-8Ph Q8.< out."rintln-8%ave! %ession Data P/h Q8.< // Loo" through all !ata in the session3 Enu#eration ses&a#es ? session.get0ttribute&a#es-.< :hile-ses&a#es.hasJoreEle#ents-.. @ %tring na#e ? ses&a#es.ne6tEle#ent-..to%tring-.< GbHect value ? session.get0ttribute-na#e.< out."rintln-na#e K 8 ? 8 K value K 8PbrQ8.< A out."rintln-8Ph)Q %ession %tatistics P/h)Q8.< out."rintln-8%ession $D3 8 K session.get$!-. K 8PbrQ8.< out."rintln-8&e: %ession3 8 K session.is&e:-. K 8PbrQ8.< out."rintln-8Creation Ti#e3 8 K session.getCreationTi#e-..< out."rintln-8P$Q-8 K ne: Date-session.getCreationTi#e-.. K 8.P/$QPbrQ8.< out."rintln-8Last 0ccesse! Ti#e3 8 K session.getLast0ccesse!Ti#e-..< out."rintln-8P$Q-8 K ne: Date-session.getLast0ccesse!Ti#e-.. K 8.P/$QPbrQ8.< out."rintln-8%ession $nactive $nterval3 8 K session.getJa6$nactive$nterval-..< out."rintln-8%ession $D in 5e=uest3 8

;;3

K re=.get5e=ueste!%ession$!-. K 8PbrQ8.< out."rintln-8$s session i! fro# Cookie3 8 K re=.is5e=ueste!%ession$!Lro#Cookie-. K 8PbrQ8.< out."rintln-8$s session i! fro# Y5L3 8 K re=.is5e=ueste!%ession$!Lro#Y5L-. K 8PbrQ8.< out."rintln-8$s session i! vali!3 8 K re=.is5e=ueste!%ession$!Wali!-. K 8PbrQ8.< out."rintln-8P/BGD;Q8.< out.close-.< A "ublic %tring get%ervlet$nfo-. @ return 80 session tracking servlet8< A A ///3>
Inside the serviceA B #ethod, get)essionA B is called "or the reAuest ob0ect, which returns the )ession ob0ect associated with this reAuest. The )ession ob0ect does not travel across the network, but instead it lives on the server and is associated with a client and its reAuests. RFSURF STIJLT+(6PTE5MHTIML3U

get)essionA B co#es in two versions= no %ara#eter, as used here, and get)essionAbooleanB. get)essionAtr*eB is eAuivalent to get)ession A B. The only reason "or the boolean is to state whether you want the session ob0ect created i" it is not "ound. get)essionAtr*eB is the #ost likely call, hence get)essionA B. RFSURFSTIJLT+(6PTE5MHTIMLGU
The )ession ob0ect, i" it is not new, will give us details about the client "ro# %revious visits. I" the )ession ob0ect is new then the %rogra# will start to gather in"or#ation about this client s activities on this visit. +a%turing this client in"or#ation is done through the setAttrib*teA B and getAttrib*teA B #ethods o" the session ob0ect. RFSURF STIJLT+(6PTE5MHTIMLIU

Hava.lang.GbHect get0ttribute-Hava.lang.%tring. voi! set0ttribute-Hava.lang.%tring na#e, Hava.lang.GbHect value.

;;4

Thinking in Java

,,,'0ruceEckel'com

The )ession ob0ect uses a si#%le na#e'value %airing "or loading in"or#ation. The na#e is a )tring, and the value can be any ob0ect derived "ro# 8ava!lang!.b8ect. )ession#eek kee%s track o" how #any ti#es the client has been back during this session. This is done with an Integer ob0ect na#ed sesspeek!cntr. I" the na#e is not "ound an Integer is created with value o" one, otherwise an Integer is created with the incre#ented value o" the %reviously held Integer. The new Integer is %laced into the )ession ob0ect. I" you use sa#e key in a setAttrib*teA B call, then the new ob0ect overwrites the old one. The incre#ented counter is used to dis%lay the nu#ber o" ti#es that the client has visited during this session. RFSURFSTIJLT+(6PTE5MHTIML2U

getAttrib*te/amesA B is related to getAttrib*teA B and setAttrib*te A B; it returns an enu#eration o" the na#es o" the ob0ects that are bound to the )ession ob0ect. 6 (hile loo% in )ession#eek shows this #ethod
in action. RFSURFSTIJLT+(6PTE5MHTIM?@U /ou #ay wonder how long a )ession ob0ect hangs around. The answer de%ends on the servlet container you are using; they usually de"ault to L@ #inutes *MI@@ seconds,, which is what you should see "ro# the )ervlet#eek call to get1a4InactiveIntervalA B. Tests see# to %roduce #i&ed results between servlet containers. So#eti#es the )ession ob0ect can hang around overnight, but I have never seen a case where the )ession ob0ect disa%%ears in less than the ti#e s%eci"ied by the inactive interval. /ou can try this by setting the inactive interval with set1a4InactiveIntervalA B to H seconds and see i" your )ession ob0ect hangs around or i" it is cleaned u% at the a%%ro%riate ti#e. This #ay be an attribute you will want to investigate while choosing a servlet container. RFSURFSTIJLT+(6PTE5MHTIM?MU

$unning the servlet e0am.les


I" you are not already working with an a%%lication server that handles Sun s servlet and JSP technologies "or you, you #ay download the To#cat i#%le#entation o" Java servlets and JSPs, which is a "ree, o%en'source i#%le#entation o" servlets, and is the o""icial re"erence i#%le#entation sanctioned by Sun. It can be "ound at >akarta'a ache'org. RFSURF STIJLT+(6PTE5MHTIM?KU

;;5

Eollow the instructions "or installing the To#cat i#%le#entation, then edit the server!4ml "ile to %oint to the location in your directory tree where your servlets will be %laced. )nce you start u% the To#cat %rogra# you can test your servlet %rogra#s. RFSURFSTIJLT+(6PTE5MHTIM?LU This has only been a brie" introduction to servlets; there are entire books on the sub0ect. (owever, this introduction should give you enough ideas to get you started. In addition, #any o" the ideas in the ne&t section are backward co#%atible with servlets. RFSURFSTIJLT+(6PTE5MHTIM??U

"ava 1erver ages


Java Server Pages *JSP, is a standard Java e&tension that is de"ined on to% o" the servlet E&tensions. The goal o" JSPs is the si#%li"ied creation and #anage#ent o" dyna#ic :eb %ages. RFSURF STIJLT+(6PTE5MHTIM?HU The %reviously #entioned, "reely available To#cat re"erence i#%le#entation "ro# >akarta'a ache'org auto#atically su%%orts JSPs. RFSURFSTIJLT+(6PTE5MHTIM?3U JSPs allow you to co#bine the (TMD o" a :eb %age with %ieces o" Java code in the sa#e docu#ent. The Java code is surrounded by s%ecial tags that tell the JSP container that it should use the code to generate a servlet, or %art o" one. The bene"it o" JSPs is that you can #aintain a single docu#ent that re%resents both the %age and the Java code that enables it. The downside is that the #aintainer o" the JSP %age #ust be skilled in both (TMD and Java *however, 84I builder environ#ents "or JSPs should be "orthco#ing,. RFSURFSTIJLT+(6PTE5MHTIM?GU The "irst ti#e a JSP is loaded by the JSP container *which is ty%ically associated with, or even %art o", a :eb server,, the servlet code necessary to "ul"ill the JSP tags is auto#atically generated, co#%iled, and loaded into the servlet container. The static %ortions o" the (TMD %age are %roduced by sending static )tring ob0ects to (riteA B. The dyna#ic %ortions are included directly into the servlet. RFSURF STIJLT+(6PTE5MHTIM?IU

;;7

Thinking in Java

,,,'0ruceEckel'com

Ero# then on, as long as the JSP source "or the %age is not #odi"ied, it behaves as i" it were a static (TMD %age with associated servlets *all the (TMD code is actually generated by the servlet, however,. I" you #odi"y the source code "or the JSP, it is auto#atically reco#%iled and reloaded the ne&t ti#e that %age is reAuested. )" course, because o" all this dyna#is# you ll see a slow res%onse "or the "irst'ti#e access to a JSP. (owever, since a JSP is usually used #uch #ore than it is changed, you will nor#ally not be a""ected by this delay. RFSURF STIJLT+(6PTE5MHTIM?2U The structure o" a JSP %age is a cross between a servlet and an (TMD %age. The JSP tags begin and end with angle brackets, 0ust like (TMD tags, but the tags also include %ercent signs, so all JSP tags are denoted by

PV J%P co!e here VQ


The leading %ercent sign #ay be "ollowed by other characters that deter#ine the %recise ty%e o" JSP code in the tag. RFSURF STIJLT+(6PTE5MHTIMH@U (ere s an e&tre#ely si#%le JSP e&a#%le that uses a standard Java library call to get the current ti#e in #illiseconds, which is then divided by M@@@ to %roduce the ti#e in seconds. Since a JSP e* ression *the NSP , is used, the result o" the calculation is coerced into a )tring and %laced on the generated :eb %age=

//34 c(,3Hs"3%ho:%econ!s.Hs" Pht#lQPbo!yQ PM(QThe ti#e in secon!s is3 PV? %yste#.currentTi#eJillis-./(''' VQP/M(Q P/bo!yQP/ht#lQ ///3>
In the JSP e&a#%les in this book, the "irst and last lines are not included in the actual code "ile that is e&tracted and %laced in the book s source' code tree. RFSURFSTIJLT+(6PTE5MHTIMHMU :hen the client creates a reAuest "or the JSP %age, the :eb server #ust have been con"igured to relay the reAuest to the JSP container, which then invokes the %age. 6s #entioned above, the "irst ti#e the %age is invoked, the co#%onents s%eci"ied by the %age are generated and

;;8

co#%iled by the JSP container as one or #ore servlets. In the above e&a#%le, the servlet will contain code to con"igure the Http)ervlet$esponse ob0ect, %roduce a #rint0riter ob0ect *which is always na#ed o*t,, and then turn the ti#e calculation into a )tring which is sent to o*t. 6s you can see, all this is acco#%lished with a very succinct state#ent, but the average (TMD %rogra##erF:eb designer will not have the skills to write such code. RFSURF STIJLT+(6PTE5MHTIMHKU

Im.licit ob3ects
Servlets include classes that %rovide convenient utilities, such as Http)ervlet$eC*est, Http)ervlet$esponse, )ession, etc. )b0ects o" these classes are built into the JSP s%eci"ication and auto#atically available "or use in your JSP without writing any e&tra lines o" code. The i#%licit ob0ects in a JSP are detailed in the table below.
Implicit variable reC*est .f Type A8ava4! servletB %rotocol de%endent subty%e o" Http)ervlet$eC*est %rotocol de%endent subty%e o" Http)ervlet$espons e 8sp!#age-onte4t escription The reAuest that triggers the service invocation. The res%onse to the reAuest. )cope reAuest

response

%age

page-onte 4t

session

Protocol de%endent subty%e o" http! Http)ession

The %age conte&t enca%sulates i#%le#entation' de%endent "eatures and %rovides convenience #ethods and na#es%ace access "or this JSP. The session ob0ect created "or the reAuesting client. See servlet Session ob0ect.

%age

session

;;:

Thinking in Java

,,,'0ruceEckel'com

application

)ervlet-onte4t

o*t

8sp!Jsp0riter

config page

)ervlet-onfig 8ava!lang!.b8ect

The servlet conte&t obtained "ro# the servlet con"iguration ob0ect *e.g., get)ervlet-onfigAB, get-onte4tA B. The ob0ect that writes into the out%ut strea#. The )ervlet-onfig "or this JSP. The instance o" this %age s i#%le#entation class %rocessing the current reAuest.

a%%

%age

%age %age

The sco%e o" each ob0ect can vary signi"icantly. Eor e&a#%le, the session ob0ect has a sco%e which e&ceeds that o" a %age, as it #any s%an several client reAuests and %ages. The application ob0ect can %rovide services to a grou% o" JSP %ages that together re%resent a :eb a%%lication.

"1 directives
7irectives are #essages to the JSP container and are denoted by the ! 9$= RFSURFSTIJLT+(6PTE5MHTIMHLU

PVR !irective @attr?8value8AB VQ


7irectives do not send anything to the o*t strea#, but they are i#%ortant in setting u% your JSP %age s attributes and de%endencies with the JSP container. Eor e&a#%le, the line= RFSURFSTIJLT+(6PTE5MHTIMH?U

PVR "age language?8Hava8 VQ


says that the scri%ting language being used within the JSP %age is Java. In "act, the JSP s%eci"ication onl) describes the se#antics o" scri%ts "or the language attribute eAual to !Java.$ The intent o" this directive is to build "le&ibility into the JSP technology. In the "uture, i" you were to choose another language, say Python *a good scri%ting choice,, then that language would have to su%%ort the Java 5un'ti#e Environ#ent by e&%osing the Java technology ob0ect #odel to the scri%ting environ#ent,

;;;

es%ecially the i#%licit variables de"ined above, JavaBeans %ro%erties, and %ublic #ethods. RFSURFSTIJLT+(6PTE5MHTIMHHU The #ost i#%ortant directive is the %age directive. It de"ines a nu#ber o" %age de%endent attributes and co##unicates these attributes to the JSP container. These attributes include= lang*age, e4ten's, import, session, b*ffer, a*toFl*sh, isThrea')afe, info and error#age. Eor e&a#%le=

PVR "age session?FtrueF i#"ort?FHava.util.BF VQ


This line "irst indicates that the %age reAuires %artici%ation in an (TTP session. Since we have not set the language directive the JSP container de"aults to using Java and the i#%licit scri%t language variable na#ed session is o" ty%e 8ava4!servlet!http!Http)ession. I" the directive had been "alse then the i#%licit variable session would be unavailable. I" the session variable is not s%eci"ied, then it de"aults to !true.$ RFSURF STIJLT+(6PTE5MHTIMH3U The import attribute describes the ty%es that are available to the scri%ting environ#ent. This attribute is used 0ust as it would be in the Java %rogra##ing language, i.e., a co##a'se%arated list o" ordinary import e&%ressions. This list is i#%orted by the translated JSP %age i#%le#entation and is available to the scri%ting environ#ent. 6gain, this is currently only de"ined when the value o" the language directive is !0ava. $ RFSURFSTIJLT+(6PTE5MHTIMHGU

"1 scri.ting elements


)nce the directives have been used to set u% the scri%ting environ#ent you can utili1e the scri%ting language ele#ents. JSP M.M has three scri%ting language ele#ents9 declarations, scri tlets, and e* ressions. 6 declaration will declare ele#ents, a scri%tlet is a state#ent "rag#ent, and an e&%ression is a co#%lete language e&%ression. In JSP each scri%ting ele#ent begins with a ! NS$. The synta& "or each is=

PV4 !eclaration VQ PV scri"tlet VQ PV? e6"ression VQ

1===

Thinking in Java

,,,'0ruceEckel'com

:hite s%ace is o%tional a"ter !R^.$, !R^$, !R^\$, and be"ore !^U.$ RF SURFSTIJLT+(6PTE5MHTIMHIU 6ll these tags are based u%on ZMD; you could even say that a JSP %age can be #a%%ed to a ZMD docu#ent. The ZMD eAuivalent synta& "or the scri%ting ele#ents above would be=

PHs"3!eclarationQ !eclaration P/Hs"3!eclarationQ PHs"3scri"tletQ scri"tlet P/Hs"3scri"tletQ PHs"3e6"ressionQ e6"ression P/Hs"3e6"ressionQ


In addition, there are two ty%es o" co##ents=

PV-- Hs" co##ent --VQ P4-- ht#l co##ent --Q


The "irst "or# allows you to add co##ents to JSP source %ages that will not a%%ear in any "or# in the (TMD that is sent to the client. )" course, the second "or# o" co##ent is not s%eci"ic to JSPs9it s 0ust an ordinary (TMD co##ent. :hat s interesting is that you can insert JSP code inside an (TMD co##ent and the co##ent will be %roduced in the resulting %age, including the result "ro# the JSP code. RFSURF STIJLT+(6PTE5MHTIMH2U 7eclarations are used to declare variables and #ethods in the scri%ting language *currently Java only, used in a JSP %age. The declaration #ust be a co#%lete Java state#ent and cannot %roduce any out%ut in the o*t strea#. In the Hello!8sp e&a#%le below, the declarations "or the variables loa'Time, loa' ate and hit-o*nt are all co#%lete Java state#ents that declare and initiali1e new variables.

//34 c(,3Hs"3Mello.Hs" PV-- This J%P co##ent :ill not a""ear in the generate! ht#l --VQ PV-- This is a J%P !irective3 --VQ PVR "age i#"ort?8Hava.util.B8 VQ PV-- These are !eclarations3 --VQ PV4 long loa!Ti#e? %yste#.currentTi#eJillis-.< Date loa!Date ? ne: Date-.< int hitCount ? '< VQ

1==1

Pht#lQPbo!yQ PV-- The ne6t several lines are the result of a J%P e6"ression inserte! in the generate! ht#l< the 2?2 in!icates a J%P e6"ression --VQ PM(QThis "age :as loa!e! at PV? loa!Date VQ P/M(Q PM(QMello, :orl!4 $t2s PV? ne: Date-. VQP/M(Q PM QMere2s an obHect3 PV? ne: GbHect-. VQP/M Q PM QThis "age has been u" PV? -%yste#.currentTi#eJillis-.-loa!Ti#e./(''' VQ secon!sP/M Q PM)QPage has been accesse! PV? KKhitCount VQ ti#es since PV? loa!Date VQP/M)Q PV-- 0 8scri"tlet8 that :rites to the server console an! to the client "age. &ote that the 2<2 is re=uire!3 --VQ PV %yste#.out."rintln-8aoo!bye8.< out."rintln-8Cheerio8.< VQ P/bo!yQP/ht#lQ ///3>
:hen you run this %rogra# you ll see that the variables loa'Time, loa' ate and hit-o*nt hold their values between hits to the %age, so they are clearly "ields and not local variables. RFSURF STIJLT+(6PTE5MHTIM3@U 6t the end o" the e&a#%le is a scri%tlet that writes !8oodbye$ to the :eb server console and !+heerio$ to the i#%licit Jsp0riter ob0ect o*t. Scri%tlets can contain any code "rag#ents that are valid Java state#ents. Scri%tlets are e&ecuted at reAuest'%rocessing ti#e. :hen all the scri%tlet "rag#ents in a given JSP are co#bined in the order they a%%ear in the JSP %age, they should yield a valid state#ent as de"ined by the Java %rogra##ing language. :hether or not they %roduce any out%ut into the o*t strea# de%ends u%on the code in the scri%tlet. /ou should be aware that scri%tlets can %roduce side e""ects by #odi"ying the ob0ects that are visible to the#. RFSURFSTIJLT+(6PTE5MHTIM3MU JSP e&%ressions can "ound inter#ingled with the (TMD in the #iddle section o" Hello!8sp. E&%ressions #ust be co#%lete Java state#ents, which are evaluated, coerced to a )tring, and sent to o*t. I" the result o"

1==2

Thinking in Java

,,,'0ruceEckel'com

the e&%ression cannot be coerced to a )tring then a -lass-ast&4ception is thrown. RFSURFSTIJLT+(6PTE5MHTIM3KU

/0tracting fields and values


The "ollowing e&a#%le is si#ilar to one shown earlier in the servlet section. The "irst ti#e you hit the %age it detects that you have no "ields and returns a %age containing a "or#, using the sa#e code as in the servlet e&a#%le, but in JSP "or#at. :hen you sub#it the "or# with the "illed'in "ields to the sa#e JSP 45D, it detects the "ields and dis%lays the#. This is a nice techniAue because it allows you to have both the %age containing the "or# "or the user to "ill out and the res%onse code "or that %age in a single "ile, thus #aking it easier to create and #aintain.

//34 c(,3Hs"3Dis"layLor#Data.Hs" PV-- Letching the !ata fro# an MTJL for#. --VQ PV-- This J%P also generates the for#. --VQ PVR "age i#"ort?8Hava.util.B8 VQ Pht#lQPbo!yQ PM(QDis"layLor#DataP/M(QPM)Q PV Enu#eration fl!s ? re=uest.getPara#eter&a#es-.< if-4fl!s.hasJoreEle#ents-.. @ // &o fiel!s VQ Pfor# #etho!?8PG%T8 action?8Dis"layLor#Data.Hs"8Q PV for-int i ? '< i P ('< iKK. @ VQ Liel!PV?iVQ3 Pin"ut ty"e?8te6t8 siUe?8 '8 na#e?8Liel!PV?iVQ8 value?8WaluePV?iVQ8QPbrQ PV A VQ P$&PYT T;PE?sub#it na#e?sub#it value?8%ub#it8QP/for#Q PVA else @ :hile-fl!s.hasJoreEle#ents-.. @ %tring fiel! ? -%tring.fl!s.ne6tEle#ent-.< %tring value ? re=uest.getPara#eter-fiel!.< VQ PliQPV? fiel! VQ ? PV? value VQP/liQ PV A A VQ P/M)QP/bo!yQP/ht#lQ

1==3

///3>
The #ost interesting "eature o" this e&a#%le is that it de#onstrates how scri%tlet code can be inter#i&ed with (TMD code, even to the %oint o" generating (TMD within a Java for loo%. This is es%ecially convenient "or building any kind o" "or# where re%etitive (TMD code would otherwise be reAuired. RFSURFSTIJLT+(6PTE5MHTIM3LU

"1 .age attributes and sco.e


By %oking around in the (TMD docu#entation "or servlets and JSPs, you will "ind "eatures that re%ort in"or#ation about the servlet or JSP that is currently running. The "ollowing e&a#%le dis%lays a "ew o" these %ieces o" data.

//34 c(,3Hs"3PageConte6t.Hs" PV--Wie:ing the attributes in the "ageConte6t--VQ PV-- &ote that you can inclu!e any a#ount of co!e insi!e the scri"tlet tags --VQ PVR "age i#"ort?8Hava.util.B8 VQ Pht#lQPbo!yQ %ervlet &a#e3 PV? config.get%ervlet&a#e-. VQPbrQ %ervlet container su""orts servlet version3 PV out."rint-a""lication.getJaHorWersion-. K 8.8 K a""lication.getJinorWersion-..< VQPbrQ PV session.set0ttribute-8Jy !og8, 85al"h8.< for-int sco"e ? (< sco"e P? I< sco"eKK. @ VQ PM)Q%co"e3 PV? sco"e VQ P/M)Q PV Enu#eration e ? "ageConte6t.get0ttribute&a#es$n%co"e-sco"e.< :hile-e.hasJoreEle#ents-.. @ out."rintln-8_tPliQ8 K e.ne6tEle#ent-. K 8P/liQ8.< A A VQ P/bo!yQP/ht#lQ ///3>

1==4

Thinking in Java

,,,'0ruceEckel'com

This e&a#%le also shows the use o" both e#bedded (TMD and writing to

o*t in order to out%ut to the resulting (TMD %age. RFSURF


STIJLT+(6PTE5MHTIM3?U The "irst %iece o" in"or#ation %roduced is the na#e o" the servlet, which will %robably 0ust be !JSP$ but it de%ends on your i#%le#entation. /ou can also discover the current version o" the servlet container by using the a%%lication ob0ect. Einally, a"ter setting a session attribute, the !attribute na#es$ in a %articular sco%e are dis%layed. /ou don t use the sco%es very #uch in #ost JSP %rogra##ing; they were 0ust shown here to add interest to the e&a#%le. There are "our attribute sco%es, as "ollows= The age sco e *sco%e M,, the re#uest sco e *sco%e K,, the session sco e *sco%e L9here, the only ele#ent available in session sco%e is !My dog,$ added right be"ore the for loo%,, and the a lication sco e *sco%e ?,, based u%on the )ervlet-onte4t ob0ect. There is one )ervlet-onte4t %er !:eb a%%lication$ %er Java Virtual Machine. *6 !:eb a%%lication$ is a collection o" servlets and content installed under a s%eci"ic subset o" the server s 45D na#es%ace such as Fcatalog. This is generally set u% using a con"iguration "ile., 6t the a%%lication sco%e you will see ob0ects that re%resent %aths "or the working directory and te#%orary directory. RF SURFSTIJLT+(6PTE5MHTIM3HU

Mani.ulating sessions in "1


Sessions were introduced in the %rior section on servlets, and are also available within JSPs. The "ollowing e&a#%le e&ercises the session ob0ect and allows you to #ani%ulate the a#ount o" ti#e be"ore the session beco#es invalid.

//34 c(,3Hs"3%essionGbHect.Hs" PV--aetting an! setting session obHect values--VQ Pht#lQPbo!yQ PM(Q%ession i!3 PV? session.get$!-. VQP/M(Q PM)QPliQThis session :as create! at PV? session.getCreationTi#e-. VQP/liQP/M(Q PM)QPliQGl! Ja6$nactive$nterval ? PV? session.getJa6$nactive$nterval-. VQP/liQ PV session.setJa6$nactive$nterval-,.< VQ PliQ&e: Ja6$nactive$nterval? PV? session.getJa6$nactive$nterval-. VQP/liQ

1==5

P/M)Q PM Q$f the session obHect 8Jy !og8 is still aroun!, this value :ill be non-null3PM Q PM)QPliQ%ession value for 8Jy !og8 ? PV? session.get0ttribute-8Jy !og8. VQP/liQP/M)Q PV-- &o: a!! the session obHect 8Jy !og8 --VQ PV session.set0ttribute-8Jy !og8, ne: %tring-85al"h8..< VQ PM(QJy !og2s na#e is PV? session.get0ttribute-8Jy !og8. VQP/M(Q PV-- %ee if 8Jy !og8 :an!ers to another for# --VQ PLG5J T;PE?PG%T 0CT$G&?%essionGbHect .Hs"Q P$&PYT T;PE?sub#it na#e?sub#it Walue?8$nvali!ate8QP/LG5JQ PLG5J T;PE?PG%T 0CT$G&?%essionGbHect).Hs"Q P$&PYT T;PE?sub#it na#e?sub#it Walue?8`ee" 0roun!8QP/LG5JQ P/bo!yQP/ht#lQ ///3>
The session ob0ect is %rovided by de"ault so it is available without any e&tra coding. The calls to getI A B, get-reationTimeA B and get1a4InactiveIntervalA B are used to dis%lay in"or#ation about this session ob0ect. RFSURFSTIJLT+(6PTE5MHTIM33U :hen you "irst bring u% this session you will see a 1a4InactiveInterval o", "or e&a#%le, MI@@ seconds *L@ #inutes,. This will de%end on the way your JSPFservlet container is con"igured. The 1a4InactiveInterval is shortened to H seconds to #ake things interesting. I" you re"resh the %age be"ore the H second interval e&%ires, then you ll see=

%ession value for 8Jy !og8 ? 5al"h


But i" you wait longer than that, !5al%h$ will beco#e n*ll. RFSURF STIJLT+(6PTE5MHTIM3GU To see how the session in"or#ation can be carried through to other %ages, and also to see the e""ect o" invalidating a session ob0ect versus 0ust letting it e&%ire, two other JSPs are created. The "irst one *reached by %ressing

1==7

Thinking in Java

,,,'0ruceEckel'com

the !invalidate$ button in )ession.b8ect!8sp, reads the session in"or#ation and then e&%licitly invalidates that session=

//34 c(,3Hs"3%essionGbHect .Hs" PV--The session obHect carries through--VQ Pht#lQPbo!yQ PM(Q%ession i!3 PV? session.get$!-. VQP/M(Q PM(Q%ession value for 8Jy !og8 PV? session.getWalue-8Jy !og8. VQP/M(Q PV session.invali!ate-.< VQ P/bo!yQP/ht#lQ ///3>
To e&%eri#ent with this, re"resh )ession.b8ect!8sp, then i##ediately click the !invalidate$ button to bring you to )ession.b8ectI!8sp. 6t this %oint you will still see !5al%h,$ and right away *be"ore the H'second interval has e&%ired,, re"resh )ession.b8ectI!8sp to see that the session has been "orce"ully invalidated and !5al%h$ has disa%%eared. RFSURF STIJLT+(6PTE5MHTIM3IU I" you go back to )ession.b8ect!8sp, re"resh the %age so you have a new H'second interval, then %ress the !>ee% 6round$ button, it will take you to the "ollowing %age, )ession.b8ectJ!8sp, which does C)T invalidate the session=

//34 c(,3Hs"3%essionGbHect).Hs" PV--The session obHect carries through--VQ Pht#lQPbo!yQ PM(Q%ession i!3 PV? session.get$!-. VQP/M(Q PM(Q%ession value for 8Jy !og8 PV? session.getWalue-8Jy !og8. VQP/M(Q PLG5J T;PE?PG%T 0CT$G&?%essionGbHect.Hs"Q P$&PYT T;PE?sub#it na#e?sub#it Walue?85eturn8Q P/LG5JQ P/bo!yQP/ht#lQ ///3>
Because this %age doesn t invalidate the session, !5al%h$ will hang around as long as you kee% re"reshing the %age be"ore the H second ti#e interval e&%ires. This is not unlike a !To#agotchi$ %et9as long as you %lay with

1==8

!5al%h$ he will stick around, otherwise he e&%ires. RFSURF STIJLT+(6PTE5MHTIM32U

Creating and modif:ing cookies


+ookies were introduced in the %rior section on servlets. )nce again, the brevity o" JSPs #akes %laying with cookies #uch si#%ler here than when using servlets. The "ollowing e&a#%le shows this by "etching the cookies that co#e with the reAuest, reading and #odi"ying their #a&i#u# ages *e&%iration dates, and attaching a new cookie to the outgoing res%onse= //34 c(,3Hs"3Cookies.Hs" PV--This "rogra# has !ifferent behaviors un!er !ifferent bro:sers4 --VQ Pht#lQPbo!yQ PM(Q%ession i!3 PV? session.get$!-. VQP/M(Q PV CookieNO cookies ? re=uest.getCookies-.< for-int i ? '< i P cookies.length< iKK. @ VQ Cookie na#e3 PV? cookiesNiO.get&a#e-. VQ PbrQ value3 PV? cookiesNiO.getWalue-. VQPbrQ Gl! #a6 age in secon!s3 PV? cookiesNiO.getJa60ge-. VQPbrQ PV cookiesNiO.setJa60ge-,.< VQ &e: #a6 age in secon!s3 PV? cookiesNiO.getJa60ge-. VQPbrQ PV A VQ PV4 int count ? '< int !count ? '< VQ PV res"onse.a!!Cookie-ne: Cookie8Bob8 K countKK, 8Dog8 K !countKK..< VQ P/bo!yQP/ht#lQ ///3>
Since each browser stores cookies in its own way, you #ay see di""erent behaviors with di""erent browsers *not reassuring, but it #ight be so#e kind o" bug that could be "i&ed by the ti#e you read this,. 6lso, you #ay e&%erience di""erent results i" you shut down the browser and restart it, rather than 0ust visiting a di""erent %age and then returning to -ookies! 8sp. Cote that using session ob0ects see#s to be #ore robust than directly using cookies. RFSURFSTIJLT+(6PTE5MHTIMG@U

1==:

Thinking in Java

,,,'0ruceEckel'com

6"ter dis%laying the session identi"ier, each cookie in the array o" cookies that co#es in with the reC*est ob0ect is dis%layed, along with its #a&i#u# age. The #a&i#u# age is changed and dis%layed again to veri"y the new value, then a new cookie is added to the res%onse. (owever, your browser #ay see# to ignore the #a&i#u# age; it s worth %laying with this %rogra# and #odi"ying the #a&i#u# age value to see the behavior under di""erent browsers. RFSURF STIJLT+(6PTE5MHTIMGMU

"1 summar:
This section has only been a brie" coverage o" JSPs, and yet even with what was covered here *along with the Java you ve learned in the rest o" the book, and your own knowledge o" (TMD, you can begin to write so%histicated web %ages via JSPs. The JSP synta& isn t #eant to be %articularly dee% or co#%licated, so i" you understand what was %resented in this section you re ready to be %roductive with JSPs. /ou can "ind "urther in"or#ation in #ost current books on servlets, or at >ava' sun'com. RFSURFSTIJLT+(6PTE5MHTIMGKU It s es%ecially nice to have JSPs available, even i" your goal is only to %roduce servlets. /ou ll discover that i" you have a Auestion about the behavior o" a servlet "eature, it s #uch easier and "aster to write a JSP test %rogra# to answer that Auestion than it is to write a servlet. Part o" the bene"it co#es "ro# having to write less code and being able to #i& the dis%lay (TMD in with the Java code, but the leverage beco#es es%ecially obvious when you see that the JSP +ontainer handles all the reco#%ilation and reloading o" the JSP "or you whenever the source is changed. RFSURFSTIJLT+(6PTE5MHTIMGLU 6s terri"ic as JSPs are, however, it s worth kee%ing in #ind that JSP creation reAuires a higher level o" skill than 0ust %rogra##ing in Java or 0ust creating :eb %ages. In addition, debugging a broken JSP %age is not as easy as debugging a Java %rogra#, as *currently, the error #essages are #ore obscure. This should change as develo%#ent syste#s i#%rove, but we #ay also see other technologies built on to% o" Java and the :eb that are better ada%ted to the skills o" the web site designer. RFSURF STIJLT+(6PTE5MHTIMG?U

1==;

$MI 8$emote Method Invocation9


Traditional a%%roaches to e&ecuting code on other #achines across a network have been con"using as well as tedious and error'%rone to i#%le#ent. The nicest way to think about this %roble# is that so#e ob0ect ha%%ens to live on another #achine, and that you can send a #essage to the re#ote ob0ect and get a result as i" the ob0ect lived on your local #achine. This si#%li"ication is e&actly what Java -emote Method Invocation *5MI, allows you to do. This section walks you through the ste%s necessary to create your own 5MI ob0ects. RFSURF STIJLT+(6PTE5MHTIMGHU

$emote interfaces
5MI #akes heavy use o" inter"aces. :hen you want to create a re#ote ob0ect, you #ask the underlying i#%le#entation by %assing around an inter"ace. Thus, when the client gets a re"erence to a re#ote ob0ect, what they really get is an inter"ace re"erence, which ha ens to connect to so#e local stub code that talks across the network. But you don t think about this, you 0ust send #essages via your inter"ace re"erence. RFSURF STIJLT+(6PTE5MHTIMG3U :hen you create a re#ote inter"ace, you #ust "ollow these guidelines=

(4() The re#ote inter"ace #ust be p*blic *it cannot have !%ackage
access,$ that is, it cannot be !"riendly$,. )therwise, a client will get an error when atte#%ting to load a re#ote ob0ect that i#%le#ents the re#ote inter"ace.

(4!) The re#ote inter"ace #ust e&tend the inter"ace 8ava!rmi! $emote. (4*) Each #ethod in the re#ote inter"ace #ust declare 8ava!rmi! $emote&4ception in its thro(s clause in addition to any
a%%lication's%eci"ic e&ce%tions.

1=1=

Thinking in Java

,,,'0ruceEckel'com

(4+) 6 re#ote ob0ect %assed as an argu#ent or return value *either


directly or e#bedded within a local ob0ect, #ust be declared as the re#ote inter"ace, not the i#%le#entation class. (ere s a si#%le re#ote inter"ace that re%resents an accurate ti#e service= RFSURFSTIJLT+(6PTE5MHTIMGGU

//3 c(,3r#i3PerfectTi#e$.Hava // The PerfectTi#e re#ote interface. "ackage c(,.r#i< i#"ort Hava.r#i.B< "ublic interface PerfectTi#e$ e6ten!s 5e#ote @ long getPerfectTi#e-. thro:s 5e#oteE6ce"tion< A ///3>
It looks like any other inter"ace e&ce%t that it e&tends $emote and all o" its #ethods throw $emote&4ception. 5e#e#ber that all the #ethods o" an interface and all o" its #ethods are auto#atically p*blic. RFSURF STIJLT+(6PTE5MHTIMGIU

Im.lementing the remote interface


The server #ust contain a class that e&tends Unicast$emote.b8ect and i#%le#ents the re#ote inter"ace. This class can also have additional #ethods, but only the #ethods in the re#ote inter"ace are available to the client, o" course, since the client will get only a re"erence to the inter"ace, not the class that i#%le#ents it. RFSURFSTIJLT+(6PTE5MHTIMG2U /ou #ust e&%licitly de"ine the constructor "or the re#ote ob0ect even i" you re only de"ining a de"ault constructor that calls the base'class constructor. /ou #ust write it out since it #ust throw $emote&4ception. RFSURFSTIJLT+(6PTE5MHTIMI@U (ere s the i#%le#entation o" the re#ote inter"ace #erfectTimeI=

//3 c(,3r#i3PerfectTi#e.Hava // The i#"le#entation of // the PerfectTi#e re#ote obHect. "ackage c(,.r#i< i#"ort Hava.r#i.B<

1=11

i#"ort Hava.r#i.server.B< i#"ort Hava.r#i.registry.B< i#"ort Hava.net.B< "ublic class PerfectTi#e e6ten!s Ynicast5e#oteGbHect i#"le#ents PerfectTi#e$ @ // $#"le#entation of the interface3 "ublic long getPerfectTi#e-. thro:s 5e#oteE6ce"tion @ return %yste#.currentTi#eJillis-.< A // Just i#"le#ent constructor // to thro: 5e#oteE6ce"tion3 "ublic PerfectTi#e-. thro:s 5e#oteE6ce"tion @ // su"er-.< // Calle! auto#atically A // 5egistration for 5J$ serving. Thro: // e6ce"tions out to the console. "ublic static voi! #ain-%tringNO args. thro:s E6ce"tion @ %yste#.set%ecurityJanagerne: 5J$%ecurityJanager-..< PerfectTi#e "t ? ne: PerfectTi#e-.< &a#ing.bin!8//"e""y3 '',/PerfectTi#e8, "t.< %yste#.out."rintln-85ea!y to !o ti#e8.< A A ///3>
(ere, mainA B handles all the details o" setting u% the server. :hen you re serving 5MI ob0ects, at so#e %oint in your %rogra# you #ust= RF SURFSTIJLT+(6PTE5MHTIMIMU

(4,) +reate and install a security #anager that su%%orts 5MI. The only
one available "or 5MI as %art o" the Java distribution is $1I)ec*rity1anager. RFSURFSTIJLT+(6PTE5MHTIMIKU

(4-) +reate one or #ore instances o" a re#ote ob0ect. (ere, you can see the creation o" the #erfectTime ob0ect. RFSURF
STIJLT+(6PTE5MHTIMILU

1=12

Thinking in Java

,,,'0ruceEckel'com

(44) 5egister at least one o" the re#ote ob0ects with the 5MI re#ote
ob0ect registry "or bootstra%%ing %ur%oses. )ne re#ote ob0ect can have #ethods that %roduce re"erences to other re#ote ob0ects. This allows you to set it u% so the client #ust go to the registry only once, to get the "irst re#ote ob0ect. RFSURF STIJLT+(6PTE5MHTIMI?U

1etting u. the registr:


(ere, you see a call to the static #ethod /aming!bin'A B. (owever, this call reAuires that the registry be running as a se%arate %rocess on the co#%uter. The na#e o" the registry server is rmiregistry, and under LK' bit :indows you say= RFSURFSTIJLT+(6PTE5MHTIMIHU

start r#iregistry
to start it in the background. )n 4ni&, the co##and is=

r#iregistry D
Dike #any network %rogra#s, the rmiregistry is located at the IP address o" whatever #achine started it u%, but it #ust also be listening at a %ort. I" you invoke the rmiregistry as above, with no argu#ent, the registry s %ort will de"ault to M@22. I" you want it to be at so#e other %ort, you add an argu#ent on the co##and line to s%eci"y the %ort. Eor this e&a#%le, the %ort is located at K@@H, so the rmiregistry should be started like this under LK'bit :indows= RFSURF STIJLT+(6PTE5MHTIMI3U

start r#iregistry
or "or 4ni&=

'',

r#iregistry

'', D

The in"or#ation about the %ort #ust also be given to the bin'A B co##and, as well as the IP address o" the #achine where the registry is located. But this brings u% what can be a "rustrating %roble# i" you re e&%ecting to test 5MI %rogra#s locally the way the network %rogra#s have been tested so "ar in this cha%ter. In the J7> M.M.M release, there are a cou%le o" %roble#s= @ RFSURFSTIJLT+(6PTE5MHTIMIGU
@ Many brain cells died in agony to discover this in"or#ation.

1=13

(45) localhost does not work with 5MI. Thus, to e&%eri#ent with 5MI
on a single #achine, you #ust %rovide the na#e o" the #achine. To "ind out the na#e o" your #achine under LK'bit :indows, go to the control %anel and select !Cetwork.$ Select the !Identi"ication$ tab, and you ll see your co#%uter na#e. In #y case, I called #y co#%uter !Pe%%y.$ It a%%ears that ca%itali1ation is ignored. RF SURFSTIJLT+(6PTE5MHTIMIIU

(46) 5MI will not work unless your co#%uter has an active T+PFIP
connection, even i" all your co#%onents are 0ust talking to each other on the local #achine. This #eans that you #ust connect to your Internet service %rovider be"ore trying to run the %rogra# or you ll get so#e obscure e&ce%tion #essages. RFSURF STIJLT+(6PTE5MHTIMI2U :ith all this in #ind, the bin'A B co##and beco#es= RFSURF STIJLT+(6PTE5MHTIM2@U

&a#ing.bin!-8//"e""y3 '',/PerfectTi#e8, "t.<


I" you are using the de"ault %ort M@22, you don t need to s%eci"y a %ort, so you could say= RFSURFSTIJLT+(6PTE5MHTIM2MU

&a#ing.bin!-8//"e""y/PerfectTi#e8, "t.<
/ou should be able to %er"or# local testing by leaving o"" the IP address and using only the identi"ier= RFSURFSTIJLT+(6PTE5MHTIM2KU

&a#ing.bin!-8PerfectTi#e8, "t.<
The na#e "or the service is arbitrary; it ha%%ens to be Per"ectTi#e here, 0ust like the na#e o" the class, but you could call it anything you want. The i#%ortant thing is that it s a uniAue na#e in the registry that the client knows to look "or to %rocure the re#ote ob0ect. I" the na#e is already in the registry, you ll get an Alrea'y2o*n'&4ception. To %revent this, you can always use rebin'A B instead o" bin'A B, since rebin'A B either adds a new entry or re%laces the one that s already there. RFSURFSTIJLT+(6PTE5MHTIM2LU Even though mainA B e&its, your ob0ect has been created and registered so it s ke%t alive by the registry, waiting "or a client to co#e along and reAuest it. 6s long as the rmiregistry is running and you don t call

1=14

Thinking in Java

,,,'0ruceEckel'com

/aming!*nbin'A B on your na#e, the ob0ect will be there. Eor this


reason, when you re develo%ing your code you need to shut down the rmiregistry and restart it when you co#%ile a new version o" your re#ote ob0ect. RFSURFSTIJLT+(6PTE5MHTIM2?U /ou aren t "orced to start u% rmiregistry as an e&ternal %rocess. I" you know that your a%%lication is the only one that s going to use the registry, you can start it u% inside your %rogra# with the line=

Locate5egistry.create5egistry- '',.<
Dike be"ore, K@@H is the %ort nu#ber we ha%%en to be using in this e&a#%le. This is the eAuivalent o" running rmiregistry IDD@ "ro# a co##and line, but it can o"ten be #ore convenient when you re develo%ing 5MI code since it eli#inates the e&tra ste%s o" starting and sto%%ing the registry. )nce you ve e&ecuted this code, you can bin'A B using /aming as be"ore. RFSURFSTIJLT+(6PTE5MHTIM2HU

Creating stubs and skeletons


I" you co#%ile and run #erfectTime!8ava, it won t work even i" you have the rmiregistry running correctly. That s because the "ra#ework "or 5MI isn t all there yet. /ou #ust "irst create the stubs and skeletons that %rovide the network connection o%erations and allow you to %retend that the re#ote ob0ect is 0ust another local ob0ect on your #achine. RF SURFSTIJLT+(6PTE5MHTIM23U :hat s going on behind the scenes is co#%le&. 6ny ob0ects that you %ass into or return "ro# a re#ote ob0ect #ust implement )eriali7able *i" you want to %ass re#ote re"erences instead o" the entire ob0ects, the ob0ect argu#ents can implement $emote,, so you can i#agine that the stubs and skeletons are auto#atically %er"or#ing seriali1ation and deseriali1ation as they !#arshal$ all o" the argu#ents across the network and return the result. Eortunately, you don t have to know any o" this, but you do have to create the stubs and skeletons. This is a si#%le %rocess= you invoke the rmic tool on your co#%iled code, and it creates the necessary "iles. So the only reAuire#ent is that another ste% be added to your co#%ilation %rocess. RFSURFSTIJLT+(6PTE5MHTIM2GU

1=15

The rmic tool is %articular about %ackages and class%aths, however. #erfectTime!8ava is in the package c>@!rmi, and even i" you invoke rmic in the sa#e directory in which #erfectTime!class is located, rmic won t "ind the "ile, since it searches the class%ath. So you #ust s%eci"y the location o"" the class %ath, like so=

r#ic c(,.r#i.PerfectTi#e
/ou don t have to be in the directory containing #erfectTime!class when you e&ecute this co##and, but the results will be %laced in the current directory. RFSURFSTIJLT+(6PTE5MHTIM2IU :hen rmic runs success"ully, you ll have two new classes in the directory=

PerfectTi#eb%tub.class PerfectTi#eb%kel.class
corres%onding to the stub and skeleton. Cow you re ready to get the server and client to talk to each other. RFSURF STIJLT+(6PTE5MHTIM22U

Csing the remote ob3ect


The whole %oint o" 5MI is to #ake the use o" re#ote ob0ects si#%le. The only e&tra thing that you #ust do in your client %rogra# is to look u% and "etch the re#ote inter"ace "ro# the server. Ero# then on, it s 0ust regular Java %rogra##ing= sending #essages to ob0ects. (ere s the %rogra# that uses #erfectTime=

//3 c(,3r#i3Dis"layPerfectTi#e.Hava // Yses re#ote obHect PerfectTi#e. "ackage c(,.r#i< i#"ort Hava.r#i.B< i#"ort Hava.r#i.registry.B< "ublic class Dis"layPerfectTi#e @ "ublic static voi! #ain-%tringNO args. thro:s E6ce"tion @ %yste#.set%ecurityJanagerne: 5J$%ecurityJanager-..<

1=17

Thinking in Java

,,,'0ruceEckel'com

PerfectTi#e$ t ? -PerfectTi#e$.&a#ing.looku"8//"e""y3 '',/PerfectTi#e8.< for-int i ? '< i P ('< iKK. %yste#.out."rintln-8Perfect ti#e ? 8 K t.getPerfectTi#e-..< A A ///3>
The I7 string is the sa#e as the one used to register the ob0ect with /aming, and the "irst %art re%resents the 45D and %ort nu#ber. Since you re using a 45D, you can also s%eci"y a #achine on the Internet. RF SURFSTIJLT+(6PTE5MHTIK@@U :hat co#es back "ro# /aming!look*pA B #ust be cast to the re#ote inter"ace, not to the class. I" you use the class instead, you ll get an e&ce%tion. RFSURFSTIJLT+(6PTE5MHTIK@MU /ou can see in the #ethod call

t.getPerfectTi#e-.
that once you have a re"erence to the re#ote ob0ect, %rogra##ing with it is indistinguishable "ro# %rogra##ing with a local ob0ect *with one di""erence= re#ote #ethods throw $emote&4ception,. RFSURF STIJLT+(6PTE5MHTIK@KU

CO$;A
In large, distributed a%%lications, your needs #ight not be satis"ied by the %receding a%%roaches. Eor e&a#%le, you #ight want to inter"ace with legacy data stores, or you #ight need services "ro# a server ob0ect regardless o" its %hysical location. These situations reAuire so#e "or# o" 5e#ote Procedure +all *5P+,, and %ossibly language inde%endence. This is where +)5B6 can hel%. RFSURFSTIJLT+(6PTE5MHTIK@LU +)5B6 is not a language "eature; it s an integration technology. It s a s%eci"ication that vendors can "ollow to i#%le#ent +)5B6'co#%liant integration %roducts. +)5B6 is %art o" the )M8 s e""ort to de"ine a

1=18

standard "ra#ework "or distributed, language'inde%endent ob0ect intero%erability. RFSURFSTIJLT+(6PTE5MHTIK@?U +)5B6 su%%lies the ability to #ake re#ote %rocedure calls into Java ob0ects and non'Java ob0ects, and to inter"ace with legacy syste#s in a location'trans%arent way. Java adds networking su%%ort and a nice ob0ect'oriented language "or building gra%hical and non'gra%hical a%%lications. The Java and )M8 ob0ect #odel #a% nicely to each other; "or e&a#%le, both Java and +)5B6 i#%le#ent the inter"ace conce%t and a re"erence ob0ect #odel. RFSURFSTIJLT+(6PTE5MHTIK@HU

CO$;A fundamentals
The ob0ect intero%erability s%eci"ication develo%ed by the )M8 is co##only re"erred to as the )b0ect Manage#ent 6rchitecture *)M6,. The )M6 de"ines two co#%onents= the +ore )b0ect Model and the )M6 5e"erence 6rchitecture. The +ore )b0ect Model states the basic conce%ts o" ob0ect, inter"ace, o%eration, and so on. *+)5B6 is a re"ine#ent o" the +ore )b0ect Model., The )M6 5e"erence 6rchitecture de"ines an underlying in"rastructure o" services and #echanis#s that allow ob0ects to intero%erate. The )M6 5e"erence 6rchitecture includes the )b0ect 5eAuest Broker *)5B,, )b0ect Services *also known as +)5B6 services,, and co##on "acilities. RFSURFSTIJLT+(6PTE5MHTIK@3U The )5B is the co##unication bus by which ob0ects can reAuest services "ro# other ob0ects, regardless o" their %hysical location. This #eans that what looks like a #ethod call in the client code is actually a co#%le& o%eration. Eirst, a connection with the server ob0ect #ust e&ist, and to create a connection the )5B #ust know where the server i#%le#entation code resides. )nce the connection is established, the #ethod argu#ents #ust be #arshaled, i.e. converted in a binary strea# to be sent across a network. )ther in"or#ation that #ust be sent are the server #achine na#e, the server %rocess, and the identity o" the server ob0ect inside that %rocess. Einally, this in"or#ation is sent through a low'level wire %rotocol, the in"or#ation is decoded on the server side, and the call is e&ecuted. The )5B hides all o" this co#%le&ity "ro# the %rogra##er and #akes the o%eration al#ost as si#%le as calling a #ethod on local ob0ect. RFSURFSTIJLT+(6PTE5MHTIK@GU

1=1:

Thinking in Java

,,,'0ruceEckel'com

There is no s%eci"ication "or how an )5B +ore should be i#%le#ented, but to %rovide a basic co#%atibility a#ong di""erent vendors )5Bs, the )M8 de"ines a set o" services that are accessible through standard inter"aces. RFSURFSTIJLT+(6PTE5MHTIK@IU

CO$;A Interface Definition &anguage 8ID&9


+)5B6 is designed "or language trans%arency= a client ob0ect can call #ethods on a server ob0ect o" di""erent class, regardless o" the language they are i#%le#ented with. )" course, the client ob0ect #ust know the na#es and signatures o" #ethods that the server ob0ect e&%oses. This is where I7D co#es in. The +)5B6 I7D is a language'neutral way to s%eci"y data ty%es, attributes, o%erations, inter"aces, and #ore. The I7D synta& is si#ilar to the +<< or Java synta&. The "ollowing table shows the corres%ondence between so#e o" the conce%ts co##on to three languages that can be s%eci"ied through +)5B6 I7D=

-.$2A I +
Module Inter"ace Method

Java
Packag e Inter"a ce Metho d

-LL
Ca#es%ace Pure abstract class Me#ber "unction

The inheritance conce%t is su%%orted as well, using the colon o%erator as in +<<. The %rogra##er writes an I7D descri%tion o" the attributes, #ethods, and inter"aces that are i#%le#ented and used by the server and clients. The I7D is then co#%iled by a vendor'%rovided I7DFJava co#%iler, which reads the I7D source and generates Java code. The I7D co#%iler is an e&tre#ely use"ul tool= it doesn t 0ust generate a Java source eAuivalent o" the I7D, it also generates the code that will be used to #arshal #ethod argu#ents and to #ake re#ote calls. This code, called the stub and skeleton code, is organi1ed in #ulti%le Java source "iles and is usually %art o" the sa#e Java %ackage. RFSURF STIJLT+(6PTE5MHTIK@2U

1=1;

#he naming service


The na#ing service is one o" the "unda#ental +)5B6 services. 6 +)5B6 ob0ect is accessed through a re"erence, a %iece o" in"or#ation that s not #eaning"ul "or the hu#an reader. But re"erences can be assigned %rogra##er'de"ined, string na#es. This o%eration is known as stringi$)ing the re$erence, and one o" the )M6 co#%onents, the Ca#ing Service, is devoted to %er"or#ing string'to'ob0ect and ob0ect'to'string conversion and #a%%ing. Since the Ca#ing Service acts as a tele%hone directory that both servers and clients can consult and #ani%ulate, it runs as a se%arate %rocess. +reating an ob0ect'to'string #a%%ing is called binding an ob>ect, and re#oving the #a%%ing is called unbinding. 8etting an ob0ect re"erence %assing a string is called resolving the name. RFSURFSTIJLT+(6PTE5MHTIKM@U Eor e&a#%le, on startu%, a server a%%lication could create a server ob0ect, bind the ob0ect into the na#e service, and then wait "or clients to #ake reAuests. 6 client "irst obtains a server ob0ect re"erence, resolving the string na#e, and then can #ake calls into the server using the re"erence. RFSURFSTIJLT+(6PTE5MHTIKMMU 6gain, the Ca#ing Service s%eci"ication is %art o" +)5B6, but the a%%lication that i#%le#ents it is %rovided by the )5B vendor. The way you get access to the Ca#ing Service "unctionality can vary "ro# vendor to vendor. RFSURFSTIJLT+(6PTE5MHTIKMKU

An e0am.le
The code shown here will not be elaborate because di""erent )5Bs have di""erent ways to access +)5B6 services, so e&a#%les are vendor s%eci"ic. *The e&a#%le below uses JavaI7D, a "ree %roduct "ro# Sun that co#es with a light'weight )5B, a na#ing service, and an I7D'to'Java co#%iler., In addition, since Java is young and still evolving, not all +)5B6 "eatures are %resent in the various JavaF+)5B6 %roducts. RFSURF STIJLT+(6PTE5MHTIKMLU :e want to i#%le#ent a server, running on so#e #achine, that can be Aueried "or the e&act ti#e. :e also want to i#%le#ent a client that asks "or the e&act ti#e. In this case we ll be i#%le#enting both %rogra#s in

1=2=

Thinking in Java

,,,'0ruceEckel'com

Java, but we could also use two di""erent languages *which o"ten ha%%ens in real situations,. RFSURFSTIJLT+(6PTE5MHTIKM?U

Writing the ID& source


The "irst ste% is to write an I7D descri%tion o" the services %rovided. This is usually done by the server %rogra##er, who is then "ree to i#%le#ent the server in any language in which a +)5B6 I7D co#%iler e&ists. The I7D "ile is distributed to the client side %rogra##er and beco#es the bridge between languages. RFSURFSTIJLT+(6PTE5MHTIKMHU The e&a#%le below shows the I7D descri%tion o" our &4actTime server=

//3 c(,3corba3E6actTi#e.i!l //S ;ou #ust install i!ltoHava.e6e fro# //S Hava.sun.co# an! a!Hust the settings to use //S your local C "re"rocessor in or!er to co#"ile //S This file. %ee !ocs at Hava.sun.co#. #o!ule re#oteti#e @ interface E6actTi#e @ string getTi#e-.< A< A< ///3>
This is a declaration o" the &4actTime inter"ace inside the remotetime na#es%ace. The inter"ace is #ade u% o" one single #ethod that gives back the current ti#e in string "or#at. RFSURFSTIJLT+(6PTE5MHTIKM3U

Creating stubs and skeletons


The second ste% is to co#%ile the I7D to create the Java stub and skeleton code that we ll use "or i#%le#enting the client and the server. The tool that co#es with the JavaI7D %roduct is i'lto8ava=

i!ltoHava re#oteti#e.i!l
This will auto#atically generate code "or both the stub and the skeleton. I'lto8ava generates a Java package na#ed a"ter the I7D #odule, remotetime, and the generated Java "iles are %ut in the remotetime subdirectory. X&4actTimeImpl2ase!8ava is the skeleton that we ll use to i#%le#ent the server ob0ect, and X&4actTime)t*b!8ava will be used "or the client. There are Java re%resentations o" the I7D inter"ace in

1=21

&4actTime!8ava and a cou%le o" other su%%ort "iles used, "or e&a#%le, to
"acilitate access to the na#ing service o%erations. RFSURF STIJLT+(6PTE5MHTIKMGU

Im.lementing the server and the client


Below you can see the code "or the server side. The server ob0ect i#%le#entation is in the &4actTime)erver class. The $emoteTime)erver is the a%%lication that creates a server ob0ect, registers it with the )5B, gives a na#e to the ob0ect re"erence, and then sits Auietly waiting "or client reAuests.

//3 c(,3corba35e#oteTi#e%erver.Hava i#"ort re#oteti#e.B< i#"ort org.o#g.Cos&a#ing.B< i#"ort org.o#g.Cos&a#ing.&a#ingConte6tPackage.B< i#"ort org.o#g.CG5B0.B< i#"ort Hava.util.B< i#"ort Hava.te6t.B< // %erver obHect i#"le#entation class E6actTi#e%erver e6ten!s bE6actTi#e$#"lBase @ "ublic %tring getTi#e-.@ return DateLor#at. getTi#e$nstance-DateLor#at.LYLL.. for#at-ne: Date%yste#.currentTi#eJillis-...< A A // 5e#ote a""lication i#"le#entation "ublic class 5e#oteTi#e%erver @ // Thro: e6ce"tions to console3 "ublic static voi! #ain-%tringNO args. thro:s E6ce"tion @ // G5B creation an! initialiUation3 G5B orb ? G5B.init-args, null.< // Create the server obHect an! register it3 E6actTi#e%erver ti#e%erverGbH5ef ? ne: E6actTi#e%erver-.< orb.connect-ti#e%erverGbH5ef.<

1=22

Thinking in Java

,,,'0ruceEckel'com

// aet the root na#ing conte6t3 org.o#g.CG5B0.GbHect obH5ef ? orb.resolvebinitialbreferences8&a#e%ervice8.< &a#ingConte6t nc5ef ? &a#ingConte6tMel"er.narro:-obH5ef.< // 0ssign a string na#e to the // obHect reference -bin!ing.3 &a#eCo#"onent nc ? ne: &a#eCo#"onent-8E6actTi#e8, 88.< &a#eCo#"onentNO "ath ? @ nc A< nc5ef.rebin!-"ath, ti#e%erverGbH5ef.< // \ait for client re=uests3 Hava.lang.GbHect sync ? ne: Hava.lang.GbHect-.< synchroniUe!-sync.@ sync.:ait-.< A A A ///3>
6s you can see, i#%le#enting the server ob0ect is si#%le; it s a regular Java class that inherits "ro# the skeleton code generated by the I7D co#%iler. Things get a bit #ore co#%licated when it co#es to interacting with the )5B and other +)5B6 services. RFSURF STIJLT+(6PTE5MHTIKMIU

1ome CO$;A services


This is a short descri%tion o" what the JavaI7D'related code is doing *%ri#arily ignoring the %art o" the +)5B6 code that is vendor de%endent,. The "irst line in mainA B starts u% the )5B, and o" course, this is because our server ob0ect will need to interact with it. 5ight a"ter the )5B initiali1ation, a server ob0ect is created. 6ctually, the right ter# would be a transient servant ob>ect= an ob0ect that receives reAuests "ro# clients, and whose li"eti#e is the sa#e as the %rocess that creates it. )nce the transient servant ob0ect is created, it is registered with the )5B, which #eans that the )5B knows o" its e&istence and can now "orward reAuests to it. RFSURFSTIJLT+(6PTE5MHTIKM2U

1=23

4% to this %oint, all we have is time)erver.b8$ef, an ob0ect re"erence that is known only inside the current server %rocess. The ne&t ste% will be to assign a stringi"ied na#e to this servant ob0ect; clients will use that na#e to locate the servant ob0ect. :e acco#%lish this o%eration using the Ca#ing Service. Eirst, we need an ob0ect re"erence to the Ca#ing Service; the call to resolveXinitialXreferencesA B takes the stringi"ied ob0ect re"erence o" the Ca#ing Service that is !Ca#eService,$ in JavaI7D, and returns an ob0ect re"erence. This is cast to a s%eci"ic /aming-onte4t re"erence using the narro(A B #ethod. :e can use now the na#ing services. RFSURFSTIJLT+(6PTE5MHTIKK@U To bind the servant ob0ect with a stringi"ied ob0ect re"erence, we "irst create a /ame-omponent ob0ect, initiali1ed with !E&actTi#e,$ the na#e string we want to bind to the servant ob0ect. Then, using the rebin'A B #ethod, the stringi"ied re"erence is bound to the ob0ect re"erence. :e use rebin'A B to assign a re"erence, even i" it already e&ists, whereas bin'A B raises an e&ce%tion i" the re"erence already e&ists. 6 na#e is #ade u% in +)5B6 by a seAuence o" Ca#e+onte&ts9that s why we use an array to bind the na#e to the ob0ect re"erence. RFSURF STIJLT+(6PTE5MHTIKKMU The servant ob0ect is "inally ready "or use by clients. 6t this %oint, the server %rocess enters a wait state. 6gain, this is because it is a transient servant, so its li"eti#e is con"ined to the server %rocess. JavaI7D does not currently su%%ort %ersistent ob0ects9ob0ects that survive the e&ecution o" the %rocess that creates the#. RFSURFSTIJLT+(6PTE5MHTIKKKU Cow that we have an idea o" what the server code is doing, let s look at the client code=

//3 c(,3corba35e#oteTi#eClient.Hava i#"ort re#oteti#e.B< i#"ort org.o#g.Cos&a#ing.B< i#"ort org.o#g.CG5B0.B< "ublic class 5e#oteTi#eClient @ // Thro: e6ce"tions to console3 "ublic static voi! #ain-%tringNO args. thro:s E6ce"tion @ // G5B creation an! initialiUation3

1=24

Thinking in Java

,,,'0ruceEckel'com

G5B orb ? G5B.init-args, null.< // aet the root na#ing conte6t3 org.o#g.CG5B0.GbHect obH5ef ? orb.resolvebinitialbreferences8&a#e%ervice8.< &a#ingConte6t nc5ef ? &a#ingConte6tMel"er.narro:-obH5ef.< // aet -resolve. the stringifie! obHect // reference for the ti#e server3 &a#eCo#"onent nc ? ne: &a#eCo#"onent-8E6actTi#e8, 88.< &a#eCo#"onentNO "ath ? @ nc A< E6actTi#e ti#eGbH5ef ? E6actTi#eMel"er.narro:nc5ef.resolve-"ath..< // Jake re=uests to the server obHect3 %tring e6actTi#e ? ti#eGbH5ef.getTi#e-.< %yste#.out."rintln-e6actTi#e.< A A ///3>
The "irst "ew lines do the sa#e as they do in the server %rocess= the )5B is initiali1ed and a re"erence to the na#ing service server is resolved. Ce&t, we need an ob0ect re"erence "or the servant ob0ect, so we %ass the stringi"ied ob0ect re"erence to the resolveA B #ethod, and we cast the result into an &4actTime inter"ace re"erence using the narro(A B #ethod. Einally, we call getTimeA B. RFSURF STIJLT+(6PTE5MHTIKKLU

Activating the name service .rocess


Einally we have a server and a client a%%lication ready to intero%erate. /ou ve seen that both need the na#ing service to bind and resolve stringi"ied ob0ect re"erences. /ou #ust start the na#ing service %rocess be"ore running either the server or the client. In JavaI7D, the na#ing service is a Java a%%lication that co#es with the %roduct %ackage, but it can be di""erent with other %roducts. The JavaI7D na#ing service runs inside an instance o" the JVM and listens by de"ault to network %ort 2@@. RFSURFSTIJLT+(6PTE5MHTIKK?U

1=25

Activating the server and the client


Cow you are ready to start your server and client a%%lication *in this order, since our server is transient,. I" everything is set u% correctly, what you ll get is a single out%ut line on the client console window, giving you the current ti#e. )" course, this #ight be not very e&citing by itsel", but you should take one thing into account= even i" they are on the sa#e %hysical #achine, the client and the server a%%lication are running inside di""erent virtual #achines and they can co##unicate via an underlying integration layer, the )5B and the Ca#ing Service. RFSURF STIJLT+(6PTE5MHTIKKHU This is a si#%le e&a#%le, designed to work without a network, but an )5B is usually con"igured "or location trans%arency. :hen the server and the client are on di""erent #achines, the )5B can resolve re#ote stringi"ied re"erences using a co#%onent known as the Im lementation -e ositor). 6lthough the I#%le#entation 5e%ository is %art o" +)5B6, there is al#ost no s%eci"ication, so it di""ers "ro# vendor to vendor. RF SURFSTIJLT+(6PTE5MHTIKK3U 6s you can see, there is #uch #ore to +)5B6 than what has been covered here, but you should get the basic idea. I" you want #ore in"or#ation about +)5B6, the %lace to start is the )M8 :eb site, at ,,,'omg'org. There you ll "ind docu#entation, white %a%ers, %roceedings, and re"erences to other +)5B6 sources and %roducts. RF SURFSTIJLT+(6PTE5MHTIKKGU

"ava A..lets and CO$;A


Java a%%lets can act as +)5B6 clients. This way, an a%%let can access re#ote in"or#ation and services e&%osed as +)5B6 ob0ects. But an a%%let can connect only with the server "ro# which it was downloaded, so all the +)5B6 ob0ects the a%%let interacts with #ust be on that server. This is the o%%osite o" what +)5B6 tries to do= give you co#%lete location trans%arency. RFSURFSTIJLT+(6PTE5MHTIKKIU This is an issue o" network security. I" you re on an intranet, one solution is to loosen the security restrictions on the browser. )r, set u% a "irewall

1=27

Thinking in Java

,,,'0ruceEckel'com

%olicy "or connecting with e&ternal servers. RFSURF STIJLT+(6PTE5MHTIKK2U So#e Java )5B %roducts o""er %ro%rietary solutions to this %roble#. Eor e&a#%le, so#e i#%le#ent what is called (TTP Tunneling, while others have their s%ecial "irewall "eatures. RFSURFSTIJLT+(6PTE5MHTIKL@U This is too co#%le& a to%ic to be covered in an a%%endi&, but it is de"initely so#ething you should be aware o". RFSURF STIJLT+(6PTE5MHTIKLMU

CO$;A vs) $MI


/ou saw that one o" the #ain +)5B6 "eatures is 5P+ su%%ort, which allows your local ob0ects to call #ethods in re#ote ob0ects. )" course, there already is a native Java "eature that does e&actly the sa#e thing= 5MI *see +ha%ter MH,. :hile 5MI #akes 5P+ %ossible between Java ob0ects, +)5B6 #akes 5P+ %ossible between ob0ects i#%le#ented in any language. It s a big di""erence. RFSURFSTIJLT+(6PTE5MHTIKLKU (owever, 5MI can be used to call services on re#ote, non'Java code. 6ll you need is so#e kind o" wra%%er Java ob0ect around the non'Java code on the server side. The wra%%er ob0ect connects e&ternally to Java clients via 5MI, and internally connects to the non'Java code using one o" the techniAues shown above, such as JCI or JF7irect. RFSURF STIJLT+(6PTE5MHTIKLLU This a%%roach reAuires you to write a kind o" integration layer, which is e&actly what +)5B6 does "or you, but then you don t need a third'%arty )5B. RFSURFSTIJLT+(6PTE5MHTIKL?U

/nter.rise "ava;eans
Su%%ose @ you need to develo% a #ulti'tiered a%%lication to view and u%date records in a database through a :eb inter"ace. /ou can write a database a%%lication using J7B+, a :eb inter"ace using JSPFservlets, and a distributed syste# using +)5B6F5MI. But what e&tra considerations
@ This section was contributed by 5obert +astaneda, with hel% "ro# 7ave Bartlett.

1=28

#ust you #ake when develo%ing a distributed ob0ect syste# rather than 0ust knowing 6PI sO (ere are the issues= RFSURF STIJLT+(6PTE5MHTIKLHU

"erfor#ance. The distributed ob0ects you create #ust %er"or# well, as


they could %otentially service #any clients at a ti#e. /ou ll need to use o%ti#i1ation techniAues such as caching as well as %ooling resources like database connections. /ou ll also have to #anage the li"ecycle o" your distributed ob0ects. RFSURFSTIJLT+(6PTE5MHTIKL3U

*calabilit!= The distributed ob0ects #ust also be scalable. Scalability in


a distributed a%%lication #eans that the nu#ber o" instances o" your distributed ob0ects can be increased and #oved onto additional #achines without #odi"ying any code. RFSURFSTIJLT+(6PTE5MHTIKLGU

*ecurit!. 6 distributed ob0ect #ust o"ten #anage the authori1ation o"


the clients that access it. Ideally, you can add new users and roles to it without reco#%ilation. RFSURFSTIJLT+(6PTE5MHTIKLIU

Distributed Transactions. 6 distributed ob0ect should be able to


re"erence distributed transactions trans%arently. Eor e&a#%le, i" you are working with two se%arated databases, you should be able to u%date the# si#ultaneously within the sa#e transaction and roll the# both back i" a certain criteria is not #et. RFSURFSTIJLT+(6PTE5MHTIKL2U

Reusabilit!. The ideal distributed ob0ect can be e""ortlessly #oved onto another vendors a%%lication server. It would be nice i" you could resell a distributed ob0ect co#%onent without #aking s%ecial #odi"ications, or buy so#eone else s co#%onent and use it without having to reco#%ile or rewrite it. RFSURFSTIJLT+(6PTE5MHTIK?@U -vailabilit!. I" one o" the #achines in the syste# goes down, clients should auto#atically "ail'over to backu% co%ies o" the ob0ects running on other #achines. RFSURFSTIJLT+(6PTE5MHTIK?MU
These considerations, in addition the business %roble# that you set out to solve, can #ake "or a daunting develo%#ent %ro0ect. (owever, all the issues e*ce t "or your business %roble# are redundant9solutions #ust be reinvented "or every distributed business a%%lication. RFSURF STIJLT+(6PTE5MHTIK?KU

1=2:

Thinking in Java

,,,'0ruceEckel'com

Sun, along with other leading distributed ob0ect vendors, reali1ed that sooner or later every develo%#ent tea# would be reinventing these %articular solutions, so they created the Enter%rise JavaBeans s%eci"ication *EJB,. EJB describes a server'side co#%onent #odel that tackles all o" the considerations #entioned above using a standard a%%roach that allows develo%ers to create business co#%onents called EJBs that are isolated "ro# low'level !%lu#bing$ code and that "ocus solely on %roviding business logic. Because EJB s are de"ined in a standard way, they can vendor inde%endent. RFSURF STIJLT+(6PTE5MHTIK?LU

"ava;eans vs) /";s


Because o" the si#ilarity in na#es, there is #uch con"usion about the relationshi% between the JavaBeans co#%onent #odel and the Enter%rise JavaBeans s%eci"ication. :hile both the JavaBeans and Enter%rise JavaBeans s%eci"ications share the sa#e ob0ectives in %ro#oting reuse and %ortability o" Java code between develo%#ent and de%loy#ent tools with the use o" standard design %atterns, the #otives behind each s%eci"ication are geared to solve di""erent %roble#s. RFSURF STIJLT+(6PTE5MHTIK??U The standards de"ined in the JavaBeans co#%onent #odel are designed "or creating reusable co#%onents that are ty%ically used in I7E develo%#ent tools and are co##only, although not e&clusively, visual co#%onents. RFSURFSTIJLT+(6PTE5MHTIK?HU The Enter%rise JavaBeans s%eci"ication de"ines a co#%onent #odel "or develo%ing server side 0ava code. Because EJBs can %otentially run on #any di""erent server'side %lat"or#s9including #ain"ra#es that do not have visual dis%lays96n EJB cannot #ake use o" gra%hical libraries such as 6:T or Swing. RFSURFSTIJLT+(6PTE5MHTIK?3U

#he /"; s.ecification


The Enter%rise JavaBeans s%eci"ication describes a server'side co#%onent #odel. It de"ines si& roles that are used to %er"or# the tasks in develo%#ent and de%loy#ent as well as de"ining the co#%onents o" the syste#. These roles are used in the develo%#ent, de%loy#ent and

1=2;

running o" a distributed syste#. Vendors, ad#inistrators and develo%ers %lay the various roles, to allow the %artitioning o" technical and do#ain knowledge. The vendor %rovides a technically sound "ra#ework and the develo%ers create do#ain's%eci"ic co#%onents; "or e&a#%le, an !accounting$ co#%onent. The sa#e %arty can %er"or# one or #any roles. The roles de"ined in the EJB s%eci"ication are su##ari1ed in the "ollowing table=

$ole
Enter%rise Bean Provider

$esponsibility
The develo%er res%onsible "or creating reusable EJB co#%onents. These co#%onents are %ackaged into a s%ecial 0ar "ile *e0b'0ar "ile,. +reates and asse#bles a%%lications "ro# a collection o" e0b'0ar "iles. This includes writing a%%lications that utili1e the collection o" EJBs *e.g., servlets, JSP, Swing etc. etc.,. Takes the collection o" e0b'0ar "iles "ro# the 6sse#bler andFor Bean Provider and de%loys the# into a run'ti#e environ#ent= one or #ore EJB +ontainers. Provides a run'ti#e environ#ent and tools that are used to de%loy, ad#inister, and run EJB co#%onents. Manages the di""erent co#%onents and services so that they are con"igured and they interact correctly, as well as ensuring that the syste# is u% and running.

6%%lication 6sse#bler

7e%loyer

EJB +ontainerF Server Provider Syste# 6d#inistrator

/"; com.onents
EJB co#%onents are ele#ents o" reusable business logic that adhere to strict standards and design %atterns as de"ined in the EJB s%eci"ication. This allows the co#%onents to be %ortable. It also allows other services9 such as security, caching and distributed transactions9to be %er"or#ed on behal" o" the co#%onents. 6n Enter%rise Bean Provider is res%onsible "or develo%ing EJB co#%onents. RFSURFSTIJLT+(6PTE5MHTIK?GU

1=3=

Thinking in Java

,,,'0ruceEckel'com

/"; Container L 1erver


The EJ0 Container is a run'ti#e environ#ent that contains and runs EJB co#%onents and %rovides a set o" standard services to those co#%onents. The EJB +ontainer s res%onsibilities are tightly de"ined by the s%eci"ication to allow "or vendor neutrality. The EJB container %rovides the low'level !%lu#bing$ o" EJB, including distributed transactions, security, li"ecycle #anage#ent o" beans, caching, threading and session #anage#ent. The EJB +ontainer Provider is res%onsible "or %roviding an EJB +ontainer. RFSURFSTIJLT+(6PTE5MHTIK?IU 6n EJ0 Server is de"ined as an 6%%lication Server that contains and runs one or #ore EJB +ontainers. The EJB Server Provider is res%onsible "or %roviding an EJB Server. /ou can generally assu#e that the EJB +ontainer and EJB Server are the sa#e. RFSURF STIJLT+(6PTE5MHTIK?2U

"ava 2aming and Director: Interface 8"2DI9


Java Ca#ing and 7irectory Inter"ace *JC7I, is used in Enter%rise JavaBeans as the na#ing service "or EJB +o#%onents on the network and other container services such as transactions. JC7I #a%s very closely to other na#ing and directory standards such as +)5B6 +osCa#ing and can actually be i#%le#eted as a wra%%er on to% o" it. RFSURF STIJLT+(6PTE5MHTIKH@U

"ava #ransaction A ID"ava #ransaction 1ervice 8"#AD"#19


JT6FJTS is used in Enter%rise JavaBeans as the transactional 6PI. 6n Enter%rise Bean Provider can use the JTS to create transaction code, although the EJB +ontainer co##only i#%le#ents transactions in EJB on the EJB co#%onents behal". The de%loyer can de"ine the transactional attributes o" an EJB co#%onent at de%loy#ent ti#e. The EJB +ontainer is res%onsible "or handling the transaction whether it is local or distributed. The JTS s%eci"ication is the Java #a%%ing to the +)5B6 )TS *)b0ect Transaction Service, RFSURFSTIJLT+(6PTE5MHTIKHMU

1=31

CO$;A and $MIDIIO


The EJB s%eci"ication de"ines intero%erability with +)5B6 through co#%atibility with +)5B6 %rotocols. This is achieved by #a%%ing EJB services such as JTS and JC7I to corres%onding +)5B6 services and the i#%le#entation o" 5MI on to% o" the +)5B6 %rotocol II)P. RFSURF STIJLT+(6PTE5MHTIKHKU 4se o" +)5B6 and 5MIFII)P in Enter%rise JavaBeans is i#%le#ented in the EJB +ontainer and is the res%onsibility o" the EJB +ontainer %rovider. 4se o" +)5B6 and 5MIFII)P in the EJB +ontainer is hidden "ro# the EJB +o#%onent itsel". This #eans that the Enter%rise Bean Provider can write their EJB +o#%onent and de%loy it into any EJB +ontainer without any regard o" which co##unication %rotocol is being used. RFSURFSTIJLT+(6PTE5MHTIKHLU

#he .ieces of an /"; com.onent


6n EJB consists o" a nu#ber o" %ieces, including the Bean itsel", the i#%le#entation o" so#e inter"aces, and an in"or#ation "ile. Everything is %ackaged together into a s%ecial 0ar "ile. RFSURF STIJLT+(6PTE5MHTIKH?U

/nter.rise ;ean
The Enter%rise Bean is a Java class that the Enter%rise Bean Provider develo%s. It i#%le#ents an Enter%rise Bean inter"ace and %rovides the i#%le#entation o" the business #ethods that the co#%onent is to %er"or#. The class does not i#%le#ent any authori1ation, authentication, #ultithreading, or transactional code. RFSURF STIJLT+(6PTE5MHTIKHHU

>ome interface
Every Enter%rise Bean that is created #ust have an associated (o#e inter"ace. The (o#e inter"ace is used as a "actory "or your EJB. +lients use the (o#e inter"ace to "ind an instance o" your EJB or create a new instance o" your EJB. RFSURFSTIJLT+(6PTE5MHTIKH3U

1=32

Thinking in Java

,,,'0ruceEckel'com

$emote interface
The 5e#ote inter"ace is a Java Inter"ace that re"lects the #ethods o" your Enter%rise Bean that you wish to e&%ose to the outside world. The 5e#ote inter"ace %lays a si#ilar role to a +)5B6 I7D inter"ace. RFSURF STIJLT+(6PTE5MHTIKHGU

De.lo:ment descri.tor
The de%loy#ent descri%tor is an ZMD "ile that contains in"or#ation about your EJB. 4sing ZMD allows the de%loyer to easily change attributes about your EJB. The con"igurable attributes de"ined in the de%loy#ent descri%tor include=

The (o#e and 5e#ote inter"ace na#es that are reAuired by your EJB The na#e to %ublish into JC7I "or your EJBs (o#e inter"ace Transactional attributes "or each #ethod o" your EJB 6ccess +ontrol Dists "or authenticationRFSURF STIJLT+(6PTE5MHTIKHIU

/";@"ar file
The EJB'Jar "ile is a nor#al 0ava 0ar "ile that contains your EJB, (o#e and 5e#ote inter"aces, as well as the de%loy#ent descri%tor. RFSURF STIJLT+(6PTE5MHTIKH2U

/"; o.eration
)nce you have an EJB'Jar "ile containing the Bean, the (o#e and 5e#ote inter"aces, and the de%loy#ent descri%tor, you can "it all o" the %ieces together and in the %rocess understand why the (o#e and 5e#ote inter"aces are needed and how the EJB +ontainer uses the#. RFSURF STIJLT+(6PTE5MHTIK3@U The EJB +ontainer i#%le#ents the (o#e and 5e#ote inter"aces that are in the EJB'Jar "ile. 6s #entioned earlier, the (o#e inter"ace %rovides #ethods to create and "ind your EJB. This #eans that the EJB +ontainer

1=33

is res%onsible "or the li"ecycle #anage#ent o" your EJB. This level o" indirection allows "or o%ti#i1ations to occur. Eor e&a#%le, H clients #ight si#ultaneously reAuest the creation o" an EJB through a (o#e Inter"ace, and the EJB +ontainer would res%ond by creating only one EJB and sharing it between all H clients. This is achieved through the 5e#ote Inter"ace, which is also i#%le#ented by the EJB +ontainer. The i#%le#ented 5e#ote ob0ect %lays the role o" a %ro&y ob0ect to the EJB. RF SURFSTIJLT+(6PTE5MHTIK3MU 6ll calls to the EJB are [%ro&ied through the EJB +ontainer via the (o#e and 5e#ote inter"aces. This indirection is the reason why the EJB container can control security and transactional behavior. RFSURF STIJLT+(6PTE5MHTIK3KU

#:.es of /";s
The Enter%rise JavaBeans s%eci"ication de"ines di""erent ty%es o" EJBs that have di""erent characteristics and behaviors. Two categories o" EJBs have been de"ined in the s%eci"ication= Session 0eans and Entit) 0eans, and each categoriy has variations. RFSURFSTIJLT+(6PTE5MHTIK3LU

1ession ;eans
Session Beans are used to re%resent 4se'+ases or :ork"low on behal" o" a client. They re%resent o%erations on %ersistent data, but not the %ersistent data itsel". There are two ty%es o" Session Beans, Stateless and State$ul. 6ll Session Beans #ust i#%le#ent the 8ava4!e8b!)ession2ean inter"ace. The EJB +ontainer governs the li"e o" a Session Bean. RFSURF STIJLT+(6PTE5MHTIK3?U

)tateless )ession 2eans are the si#%lest ty%e o" EJB co#%onent to i#%le#ent. They do not #aintain any conversational state with clients between #ethod invocations so they are easily reusable on the server side and because they can be cached, they scale well on de#and. :hen using Stateless Session Beans, all state #ust be stored outside o" the EJB. RF SURFSTIJLT+(6PTE5MHTIK3HU )tatef*l )ession 2eans #aintain state between invocations. They have
a one'to'one logical #a%%ing to a client and can #aintain state within the#selves. The EJB +ontainer is res%onsible "or %ooling and caching o"

1=34

Thinking in Java

,,,'0ruceEckel'com

State"ul Session Beans, which is achieved through Passivation and "ctivation. I" the EJB +ontainer crashes, data "or all State"ul Session Beans could be lost. So#e high'end EJB +ontainers %rovide recovery "or State"ul Session Beans. RFSURFSTIJLT+(6PTE5MHTIK33U

/ntit: ;eans
Entity Beans are co#%onents that re%resent %ersistent data and behavior o" this data. Entity Beans can be shared a#ong #ulti%le clients, the sa#e way that data in a database can be shared. The EJB +ontainer is res%onsible "or caching Entity Beans and "or #aintaining the integrity o" the Entity Beans. The li"e o" an Entity Bean outlives the EJB +ontainer, so i" an EJB +ontainer crashes, the Entity Bean is still e&%ected to be available when the EJB +ontainer again beco#es available. RFSURF STIJLT+(6PTE5MHTIK3GU There are two ty%es o" Entity Beans= those with +ontainer Managed %ersistence and those with Bean'Managed %ersistence. RFSURF STIJLT+(6PTE5MHTIK3IU

-ontainer 1anage' #ersistence A-1#B. 6 +MP Entity Bean has its %ersistence i#%le#ented on its behal" by the EJB +ontainer. Through attributes s%eci"ied in the de%loy#ent descri%tor, the EJB +ontainer will #a% the Entity Bean s attributes to so#e %ersistent store *usually9but not always9a database,. +MP reduces the develo%#ent ti#e "or the EJB, as well as dra#atically reducing the a#ount o" code reAuired. RFSURF STIJLT+(6PTE5MHTIK32U 2ean 1anage' #ersistence A21#B. 6 BMP Entity Bean has its %ersistence i#%le#ented by the Enter%rise Bean Provider. The Enter%rise Bean Provider is res%onsible "or i#%le#enting the logic reAuired to create a new EJB, u%date so#e attributes o" the EJBS, delete an EJB and "ind an EJB "ro# %ersistent store. This usually involves writing J7B+ code to interact with a database or other %ersistent store. :ith BMP, the develo%er is in "ull control o" how the Entity Bean %ersistence is #anaged. RFSURFSTIJLT+(6PTE5MHTIKG@U
BMP also gives "le&ibility where a +MP i#%le#entation #ay not be available. Eor e&a#%le, i" you wanted to create an EJB that wra%%ed so#e

1=35

code on an e&isting #ain"ra#e syste#, you could write your %ersistence using +)5B6. RFSURFSTIJLT+(6PTE5MHTIKGMU

Develo.ing an /";
6s an e&a#%le, the !Per"ect Ti#e$ e&a#%le "ro# the %revious 5MI section will be i#%le#ented as an EJB co#%onent. The e&a#%le will be a si#%le Stateless Session Bean. RFSURFSTIJLT+(6PTE5MHTIKGKU 6s #entioned earlier, EJB co#%onents consist o" at least one class *the EJB, and two inter"aces= the 5e#ote and (o#e inter"aces. :hen you create a 5e#ote inter"ace "or an EJB , you #ust "ollow these guidelines= RFSURFSTIJLT+(6PTE5MHTIKGLU

(57) The re#ote inter"ace #ust be p*blic. (5() The re#ote inter"ace #ust e&tend the inter"ace 8ava4!e8b! &J2.b8ect. (5!) Each #ethod in the re#ote inter"ace #ust declare 8ava!rmi! $emote&4ception in its thro(s clause in addition to any
a%%lication's%eci"ic e&ce%tions.

(5*) 6ny ob0ect %assed as an argu#ent or return value *either directly


or e#bedded within a local ob0ect, #ust be a valid 5MI'II)P data ty%e *this includes other EJB ob0ects,.

(ere is the si#%le re#ote inter"ace "or the Per"ectTi#e EJB= //3 c(,3eHb3PerfectTi#e.Hava //S ;ou #ust install the J EE Java Enter"rise //S E!ition fro# Hava.sun.co# an! a!! H ee.Har //S to your CL0%%P0TM in or!er to co#"ile //S this file. %ee !etails at Hava.sun.co#. // 5e#ote $nterface of PerfectTi#eBean i#"ort Hava.r#i.B< i#"ort Hava6.eHb.B< "ublic interface PerfectTi#e e6ten!s EJBGbHect @ "ublic long getPerfectTi#e-. thro:s 5e#oteE6ce"tion<

1=37

Thinking in Java

,,,'0ruceEckel'com

A ///3>
The (o#e inter"ace is the "actory where the co#%onent will be created. It can de"ine create #ethods, to create instances o" EJBs, or $inder #ethods, which locate e&isting EJBs and are used "or Entity Beans only. :hen you create a (o#e inter"ace "or an EJB , you #ust "ollow these guidelines=

(5+) The (o#e inter"ace #ust be p*blic. RFSURF


STIJLT+(6PTE5MHTIKG?U

(5,) The (o#e inter"ace #ust e&tend the inter"ace 8ava4!e8b! &J2Home. RFSURFSTIJLT+(6PTE5MHTIKGHU (5-) Each create #ethod in the (o#e inter"ace #ust declare 8ava!rmi! $emote&4ception in its thro(s clause as well as a 8ava4!e8b! -reate&4ception. RFSURFSTIJLT+(6PTE5MHTIKG3U (54) The return value o" a create #ethod #ust be a 5e#ote Inter"ace.
RFSURFSTIJLT+(6PTE5MHTIKGGU

(55) The return value o" a $inder #ethod *Entity Beans only, #ust be a 5e#ote Inter"ace or 8ava!*til!&n*meration or 8ava!*til! -ollection. RFSURFSTIJLT+(6PTE5MHTIKGIU (56) 6ny ob0ect %assed as an argu#ent *either directly or e#bedded
within a local ob0ect, #ust be a valid 5MI'II)P data ty%e *this includes other EJB ob0ects, RFSURFSTIJLT+(6PTE5MHTIKG2U The standard na#ing convention "or (o#e inter"aces is to take the 5e#ote inter"ace na#e and a%%end !(o#e$ to the end. (ere is the (o#e inter"ace "or the Per"ectTi#e EJB= RFSURFSTIJLT+(6PTE5MHTIKI@U

//3 c(,3eHb3PerfectTi#eMo#e.Hava // Mo#e $nterface of PerfectTi#eBean. i#"ort Hava.r#i.B< i#"ort Hava6.eHb.B< "ublic interface PerfectTi#eMo#e e6ten!s EJBMo#e @ "ublic PerfectTi#e create-. thro:s CreateE6ce"tion, 5e#oteE6ce"tion< A ///3>

1=38

/ou can now i#%le#ent the business logic. :hen you create your EJB i#%le#entation class, you #ust "ollow these guidelines, *note that you should consult the EJB s%eci"ication "or a co#%lete list o" guidelines when develo%ing Enter%rise JavaBeans,= RFSURF STIJLT+(6PTE5MHTIKIMU

(67) The class #ust be p*blic. RFSURFSTIJLT+(6PTE5MHTIKIKU (6() The class #ust i#%le#ent an EJB inter"ace *either 8ava4!e8b! )ession2ean or 8ava4!e8b!&ntity2ean,. RFSURF
STIJLT+(6PTE5MHTIKILU

(6!) The class should de"ine #ethods that #a% directly to the #ethods
in the 5e#ote inter"ace. Cote that the class does not i#%le#ent the 5e#ote inter"ace; it #irrors the #ethods in the 5e#ote inter"ace but does not throw 8ava!rmi!$emote&4ception. RF SURFSTIJLT+(6PTE5MHTIKI?U

(6*) 7e"ine one or #ore e8b-reateA B #ethods to initiali1e your EJB.


RFSURFSTIJLT+(6PTE5MHTIKIHU

(6+) The return value and argu#ents o" all #ethods #ust be valid 5MI'
II)P data ty%es. RFSURFSTIJLT+(6PTE5MHTIKI3U

//3 c(,3eHb3PerfectTi#eBean.Hava // %i#"le %tateless %ession Bean // that returns current syste# ti#e. i#"ort Hava.r#i.B< i#"ort Hava6.eHb.B< "ublic class PerfectTi#eBean i#"le#ents %essionBean @ "rivate %essionConte6t sessionConte6t< //return current ti#e "ublic long getPerfectTi#e-. @ return %yste#.currentTi#eJillis-.< A // EJB #etho!s "ublic voi! eHbCreate-. thro:s CreateE6ce"tion @A "ublic voi! eHb5e#ove-. @A

1=3:

Thinking in Java

,,,'0ruceEckel'com

"ublic voi! eHb0ctivate-. @A "ublic voi! eHbPassivate-. @A "ublic voi! set%essionConte6t-%essionConte6t ct6. @ sessionConte6t ? ct6< A A///3>
Because this is a si#%le e&a#%le, the EJB #ethods * e8b-reateA B, e8b$emoveA B, e8bActivateA B, e8b#assivateA B , are all e#%ty. These #ethods are invoked by the EJB +ontainer and are used to control the state o" the co#%onent. The set)ession-onte4tA B #ethod %asses a 8ava4!e8b!)ession-onte4t ob0ect which contains in"or#ation about the co#%onent s conte&t, such as the current transaction and security in"or#ation. RFSURFSTIJLT+(6PTE5MHTIKIGU 6"ter we have created the Enter%rise JavaBean, we then need to create a de%loy#ent descri%tor. The de%loy#ent descri%tor is an ZMD "ile that describes the EJB co#%onent. The de%loy#ent descri%tor should be stored in a "ile called e8b68ar!4ml. RFSURFSTIJLT+(6PTE5MHTIKIIU

//34 c(,3eHb3eHb-Har.6#l P[6#l version?8(.'8 enco!ing?8C"( , 8[Q P4DGCT;PE eHb-Har PYBL$C 2-//%un Jicrosyste#s, $nc.// DTD Enter"rise JavaBeans (.(//E&2 2htt"3//Hava.sun. co#/H ee/!t!s/eHb-Harb(b(.!t!2Q PeHb-HarQ P!escri"tionQE6a#"le for Cha"ter (,P/!escri"tionQ P!is"lay-na#eQP/!is"lay-na#eQ Ps#all-iconQP/s#all-iconQ Plarge-iconQP/large-iconQ Penter"rise-beansQ PsessionQ PeHb-na#eQPerfectTi#eP/eHb-na#eQ Pho#eQPerfectTi#eMo#eP/ho#eQ Pre#oteQPerfectTi#eP/re#oteQ PeHb-classQPerfectTi#eBeanP/eHb-classQ Psession-ty"eQ%tatelessP/session-ty"eQ Ptransaction-ty"eQContainerP/transaction-ty"eQ P/sessionQ

1=3;

P/enter"rise-beansQ PeHb-client-HarQP/eHb-client-HarQ P/eHb-HarQ ///3>


/ou can see the +o#%onent, the 5e#ote inter"ace and the (o#e inter"ace de"ined inside the NsessionO tag o" this de%loy#ent descri%tor. 7e%loy#ent descri%tors #ay be auto#atically generated using EJB develo%#ent tools. RFSURFSTIJLT+(6PTE5MHTIKI2U 6long with the standard e8b68ar!4ml de%loy#ent descri%tor, the EJB s%eci"ication states that any vendor s%eci"ic tags should be stored in a se%arate "ile. This is to achieve high %ortability between co#%onents and di""erent brands o" EJB containers. RFSURFSTIJLT+(6PTE5MHTIK2@U The "iles #ust be archived inside a standard Java 6rchive *J65, "ile. The de%loy#ent descri%tors should be %laced inside the 51&TA6I/F sub' directory o" the Jar "ile. RFSURFSTIJLT+(6PTE5MHTIK2MU )nce the EJB co#%onent is de"ined in the de%loy#ent descri%tor, the de%loyer should then de%loy the EJB co#%onent into the EJB +ontainer. 6t the ti#e o" this writing, the de%loy#ent %rocess was Auite !84I intensive$ and s%eci"ic to each individual EJB +ontainer, so this overview does not docu#ent that %rocess. Every EJB +ontainer, however will have a docu#ented %rocess "or de%loying an EJB. RFSURF STIJLT+(6PTE5MHTIK2KU Because an EJB co#%onent is a distributed ob0ect, the de%loy#ent %rocess should also create so#e client stubs "or calling the EJB co#%onent. These classes should be %laced on the class%ath o" the client a%%lication. Because EJB co#%onents can be i#%le#ented on to% o" 5MI'II)P *+)5B6, or 5MI'J5MP, the stubs generated could vary between EJB +ontainers; nevertheless they are generated classes. RFSURF STIJLT+(6PTE5MHTIK2LU :hen a client %rogra# wishes to invoke an EJB, it #ust look u% the EJB co#%onent inside JC7I and obtain a re"erence to the ho#e inter"ace o" the EJB co#%onent. The (o#e inter"ace is used to create an instance o" the EJB. RFSURFSTIJLT+(6PTE5MHTIK2?U

1=4=

Thinking in Java

,,,'0ruceEckel'com

In this e&a#%le the client %rogra# is a si#%le Java %rogra#, but you should re#e#ber that it could 0ust as easily be a servlet, a JSP or even a +)5B6 or 5MI distributed ob0ect.

//3 c(,3eHb3PerfectTi#eClient.Hava // Client "rogra# for PerfectTi#eBean "ublic class PerfectTi#eClient @ "ublic static voi! #ain-%tringNO args. thro:s E6ce"tion @ // aet a J&D$ conte6t using // the J&D$ &a#ing service3 Hava6.na#ing.Conte6t conte6t ? ne: Hava6.na#ing.$nitialConte6t-.< // Look u" the ho#e interface in the // J&D$ &a#ing service3 GbHect ref ? conte6t.looku"-8"erfectTi#e8.< // Cast the re#ote obHect to the ho#e interface3 PerfectTi#eMo#e ho#e ? -PerfectTi#eMo#e. Hava6.r#i.Portable5e#oteGbHect.narro:ref, PerfectTi#eMo#e.class.< // Create a re#ote obHect fro# the ho#e interface3 PerfectTi#e "t ? ho#e.create-.< // $nvoke getPerfectTi#e-. %yste#.out."rintln8Perfect Ti#e EJB invoke!, ti#e is3 8 K "t.getPerfectTi#e-. .< A A ///3>
The seAuence o" the e&a#%le is e&%lained in the co##ents. Cote the use o" the narro(A B #ethod to %er"or# a kind o" casting o" the ob0ect be"ore a Java cast is %er"or#ed. This is very si#ilar to what ha%%ens in +)5B6. 6lso note that the (o#e ob0ect beco#es a "actory "or #erfectTime ob0ects. RFSURFSTIJLT+(6PTE5MHTIK2HU

/"; summar:
The Enter%rise JavaBeans s%eci"ication is a dra#atic ste% "orward in the standardi1ation and si#%li"ication o" distributed ob0ect co#%uting. It is a #a0or %iece o" the Java K Enter%rise Edition *JKEE, %lat"or# and is

1=41

receiving #uch su%%ort "ro# the distributed ob0ect co##unity. Many tools are currently available or will be available in the near "uture to hel% accelerate the develo%#ent o" EJB co#%onents. RFSURF STIJLT+(6PTE5MHTIK23U This overview was only a brie" tour o" EJBs. Eor #ore in"or#ation about the EJB s%eci"ication you should see the o""icial Enter%rise JavaBeans ho#e %age at >ava'sun'com/ roducts/e>b/D where you can download the latest s%eci"ication and the JKEE re"erence i#%le#entation. These can be used to develo% and de%loy your own EJB co#%onents. RFSURF STIJLT+(6PTE5MHTIK2GU

"ini: distributed services


This section @ gives an overview o" Sun Microsyste#s s Jini technology. It describes so#e Jini nuts and bolts and shows how Jini s architecture hel%s to raise the level o" abstraction in distributed syste#s %rogra##ing, e""ectively turning network %rogra##ing into ob0ect' oriented %rogra##ing. RFSURFSTIJLT+(6PTE5MHTIK2IU

"ini in conte0t
Traditionally, o%erating syste#s have been designed with the assu#%tion that a co#%uter will have a %rocessor, so#e #e#ory, and a disk. :hen you boot a co#%uter, the "irst thing it does is look "or a disk. I" it doesn t "ind a disk, it can t "unction as a co#%uter. Increasingly, however, co#%uters are a%%earing in a di""erent guise= as e#bedded devices that have a %rocessor, so#e #e#ory, and a network connection9but no disk. The "irst thing a cell %hone does when you boot it u%, "or e&a#%le, is look "or the tele%hone network. I" it doesn t "ind the network, it can t "unction as a cell %hone. This trend in the hardware environ#ent, "ro# disk' centric to network'centric, will a""ect how we organi1e the so"tware9and that s where Jini co#es in. RFSURFSTIJLT+(6PTE5MHTIK22U Jini is an atte#%t to rethink co#%uter architecture, given the rising i#%ortance o" the network and the %roli"eration o" %rocessors in devices that have no disk drive. These devices, which will co#e "ro# #any
@ This section was contributed by Bill Venners *www.arti#a.co#,.

1=42

Thinking in Java

,,,'0ruceEckel'com

di""erent vendors, will need to interact over a network. The network itsel" will be very dyna#ic9devices and services will be added and re#oved regularly. Jini %rovides #echanis#s to enable s#ooth adding, re#oval, and "inding o" devices and services on the network. In addition, Jini %rovides a %rogra##ing #odel that #akes it easier "or %rogra##ers to get their devices talking to each other. RFSURF STIJLT+(6PTE5MHTIL@@U Building on to% o" Java, ob0ect seriali1ation, and 5MI *which together enable ob0ects to #ove around the network "ro# virtual #achine to virtual #achine, Jini atte#%ts to e&tend the bene"its o" ob0ect'oriented %rogra##ing to the network. Instead o" reAuiring device vendors to agree on the network %rotocols through which their devices can interact, Jini enables the devices to talk to each other through inter"aces to ob0ects. RF SURFSTIJLT+(6PTE5MHTIL@MU

What is "iniA
Jini is a set o" 6PIs and network %rotocols that can hel% you build and de%loy distributed syste#s that are organi1ed as $ederations o$ services. 6 service can be anything that sits on the network and is ready to %er"or# a use"ul "unction. (ardware devices, so"tware, co##unications channels9 even hu#an users the#selves9can be services. 6 Jini'enabled disk drive, "or e&a#%le, could o""er a !storage$ service. 6 Jini'enabled %rinter could o""er a !%rinting$ service. 6 "ederation o" services, then, is a set o" services, currently available on the network, that a client *#eaning a %rogra#, service, or user, can bring together to hel% it acco#%lish so#e goal. RFSURFSTIJLT+(6PTE5MHTIL@KU To %er"or# a task, a client enlists the hel% o" services. Eor e&a#%le, a client %rogra# #ight u%load %ictures "ro# the i#age storage service in a digital ca#era, download the %ictures to a %ersistent storage service o""ered by a disk drive, and send a %age o" thu#bnail'si1ed versions o" the i#ages to the %rinting service o" a color %rinter. In this e&a#%le, the client %rogra# builds a distributed syste# consisting o" itsel", the i#age storage service, the %ersistent storage service, and the color'%rinting service. The client and services o" this distributed syste# work together to %er"or# the task= to o""load and store i#ages "ro# a digital ca#era and %rint a %age o" thu#bnails. RFSURFSTIJLT+(6PTE5MHTIL@LU

1=43

The idea behind the word $ederation is that the Jini view o" the network doesn t involve a central controlling authority. Because no one service is in charge, the set o" all services available on the network "or# a "ederation 9a grou% co#%osed o" eAual %eers. Instead o" a central authority, Jini s run'ti#e in"rastructure #erely %rovides a way "or clients and services to "ind each other *via a looku% service, which stores a directory o" currently available services,. 6"ter services locate each other, they are on their own. The client and its enlisted services %er"or# their task inde%endently o" the Jini run'ti#e in"rastructure. I" the Jini looku% service crashes, any distributed syste#s brought together via the looku% service be"ore it crashed can continue their work. Jini even includes a network %rotocol that clients can use to "ind services in the absence o" a looku% service. RF SURFSTIJLT+(6PTE5MHTIL@?U

>ow "ini works


Jini de"ines a run/time in$rastructure that resides on the network and %rovides #echanis#s that enable you to add, re#ove, locate, and access services. The run'ti#e in"rastructure resides in three %laces= in looku% services that sit on the network, in the service %roviders *such as Jini' enabled devices,, and in clients. (ooku services are the central organi1ing #echanis# "or Jini'based syste#s. :hen new services beco#e available on the network, they register the#selves with a looku% service. :hen clients wish to locate a service to assist with so#e task, they consult a looku% service. RFSURFSTIJLT+(6PTE5MHTIL@HU The run'ti#e in"rastructure uses one network'level %rotocol, called discover), and two ob0ect'level %rotocols, called >oin and looku . 7iscovery enables clients and services to locate looku% services. Join enables a service to register itsel" in a looku% service. Dooku% enables a client to Auery "or services that can hel% acco#%lish its goals. RFSURF STIJLT+(6PTE5MHTIL@3U

#he discover: .rocess


7iscovery works like this= I#agine you have a Jini'enabled disk drive that o""ers a %ersistent storage service. 6s soon as you connect the drive to the network, it broadcasts a resence announcement by dro%%ing a #ulticast

1=44

Thinking in Java

,,,'0ruceEckel'com

%acket onto a well'known %ort. Included in the %resence announce#ent is an IP address and %ort nu#ber where the disk drive can be contacted by a looku% service. RFSURFSTIJLT+(6PTE5MHTIL@GU Dooku% services #onitor the well'known %ort "or %resence announce#ent %ackets. :hen a looku% service receives a %resence announce#ent, it o%ens and ins%ects the %acket. The %acket contains in"or#ation that enables the looku% service to deter#ine whether or not it should contact the sender o" the %acket. I" so, it contacts the sender directly by #aking a T+P connection to the IP address and %ort nu#ber e&tracted "ro# the %acket. 4sing 5MI, the looku% service sends an ob0ect, called a service registrar, across the network to the originator o" the %acket. The %ur%ose o" the service registrar ob0ect is to "acilitate "urther co##unication with the looku% service. By invoking #ethods on this ob0ect, the sender o" the announce#ent %acket can %er"or# 0oin and looku% on the looku% service. In the case o" the disk drive, the looku% service would #ake a T+P connection to the disk drive and would send it a service registrar ob0ect, through which the disk drive would then register its %ersistent storage service via the 0oin %rocess. RFSURF STIJLT+(6PTE5MHTIL@IU

#he 3oin .rocess


)nce a service %rovider has a service registrar ob0ect, the end %roduct o" discovery, it is ready to do a 0oin9to beco#e %art o" the "ederation o" services that are registered in the looku% service. To do a 0oin, the service %rovider invokes the registerA B #ethod on the service registrar ob0ect, %assing as a %ara#eter an ob0ect called a service ite#, a bundle o" ob0ects that describe the service. The registerA B #ethod sends a co%y o" the service ite# u% to the looku% service, where the service ite# is stored. )nce this has co#%leted, the service %rovider has "inished the 0oin %rocess= its service has beco#e registered in the looku% service. RFSURF STIJLT+(6PTE5MHTIL@2U The service ite# is a container "or several ob0ects, including an ob0ect called a service ob>ect, which clients can use to interact with the service. The service ite# can also include any nu#ber o" attributes, which can be any ob0ect. So#e %otential attributes are icons, classes that %rovide 84Is

1=45

"or the service, and ob0ects that give #ore in"or#ation about the service. RFSURFSTIJLT+(6PTE5MHTILM@U Service ob0ects usually i#%le#ent one or #ore inter"aces through which clients interact with the service. Eor e&a#%le, a looku% service is a Jini service, and its service ob0ect is the service registrar. The registerA B #ethod invoked by service %roviders during 0oin is declared in the )ervice$egistrar inter"ace *a #e#ber o" the net!8ini!core!look*p %ackage,, which all service registrar ob0ects i#%le#ent. +lients and service %roviders talk to the looku% service through the service registrar ob0ect by invoking #ethods declared in the )ervice$egistrar inter"ace. Dikewise, a disk drive would %rovide a service ob0ect that i#%le#ented so#e well'known storage service inter"ace. +lients would look u% and interact with the disk drive by this storage service inter"ace. RFSURF STIJLT+(6PTE5MHTILMMU

#he looku. .rocess


)nce a service has registered with a looku% service via the 0oin %rocess, that service is available "or use by clients who Auery that looku% service. To build a distributed syste# o" services that will work together to %er"or# so#e task, a client #ust locate and enlist the hel% o" the individual services. To "ind a service, clients Auery looku% services via a %rocess called looku . RFSURFSTIJLT+(6PTE5MHTILMKU To %er"or# a looku%, a client invokes the look*p* , #ethod on a service registrar ob0ect. *6 client, like a service %rovider, gets a service registrar through the %reviously'described %rocess o" discovery., The client %asses as an argu#ent to look*pA B a service tem late, an ob0ect that serves as search criteria "or the Auery. The service te#%late can include a re"erence to an array o" -lass ob0ects. These -lass ob0ects indicate to the looku% service the Java ty%e *or ty%es, o" the service ob0ect desired by the client. The service te#%late can also include a service I%, which uniAuely identi"ies a service, and attributes, which #ust e&actly #atch the attributes u%loaded by the service %rovider in the service ite#. The service te#%late can also contain wildcards "or any o" these "ields. 6 wildcard in the service I7 "ield, "or e&a#%le, will #atch any service I7. The look*pA B #ethod sends the service te#%late to the looku% service, which %er"or#s the Auery and sends back 1ero to any #atching service

1=47

Thinking in Java

,,,'0ruceEckel'com

ob0ects. The client gets a re"erence to the #atching service ob0ects as the return value o" the look*pA B #ethod. RFSURF STIJLT+(6PTE5MHTILMLU In the general case, a client looks u% a service by Java ty%e, usually an inter"ace. Eor e&a#%le, i" a client needed to use a %rinter, it would co#%ose a service te#%late that included a -lass ob0ect "or a well'known inter"ace to %rinter services. 6ll %rinter services would i#%le#ent this well'known inter"ace. The looku% service would return a service ob0ect *or ob0ects, that i#%le#ented this inter"ace. 6ttributes can be included in the service te#%late to narrow the nu#ber o" #atches "or such a ty%e'based search. The client would use the %rinter service by invoking #ethods "ro# the well'known %rinter service inter"ace on the service ob0ect. RFSURF STIJLT+(6PTE5MHTILM?U

1e.aration of interface and im.lementation


Jini s architecture brings ob0ect'oriented %rogra##ing to the network by enabling network services to take advantage o" one o" the "unda#entals o" ob0ects= the se%aration o" inter"ace and i#%le#entation. Eor e&a#%le, a service ob0ect can grant clients access to the service in #any ways. The ob0ect can actually re%resent the entire service, which is downloaded to the client during looku% and then e&ecuted locally. 6lternatively, the service ob0ect can serve #erely as a %ro&y to a re#ote server. Then when the client invokes #ethods on the service ob0ect, it sends the reAuests across the network to the server, which does the real work. 6 third o%tion is "or the local service ob0ect and a re#ote server to each do %art o" the work. RFSURFSTIJLT+(6PTE5MHTILMHU )ne i#%ortant conseAuence o" Jini s architecture is that the network %rotocol used to co##unicate between a %ro&y service ob0ect and a re#ote server does not need to be known to the client. 6s illustrated in the "igure below, the network %rotocol is %art o" the service s i#%le#entation. This %rotocol is a %rivate #atter decided u%on by the develo%er o" the service. The client can co##unicate with the service via this %rivate %rotocol because the service in0ects so#e o" its own code *the service ob0ect, into the client s address s%ace. The in0ected service ob0ect

1=48

could co##unicate with the service via 5MI, +)5B6, 7+)M, so#e ho#e'brewed %rotocol built on to% o" sockets and strea#s, or anything else. The client si#%ly doesn t need to care about network %rotocols, because it can talk to the well'known inter"ace that the service ob0ect i#%le#ents. The service ob0ect takes care o" any necessary co##unication on the network. RFSURFSTIJLT+(6PTE5MHTILM3U

)*ell+%n$#n) inter,"!e Ser i!e $'(e!t

Client

Pri "te net#$r% &r$t$!$l

Ser i!e

The client talks to the service thro*gh a (ell6kno(n interface


7i""erent i#%le#entations o" the sa#e service inter"ace can use co#%letely di""erent a%%roaches and network %rotocols. 6 service can use s%eciali1ed hardware to "ul"ill client reAuests, or it can do all its work in so"tware. In "act, the i#%le#entation a%%roach taken by a single service can evolve over ti#e. The client can be sure it has a service ob0ect that understands the current i#%le#entation o" the service, because the client receives the service ob0ect *by way o" the looku% service, "ro# the service %rovider itsel". To the client, a service looks like the well'known inter"ace, regardless o" how the service is i#%le#ented. RFSURF STIJLT+(6PTE5MHTILMGU

Abstracting distributed s:stems


Jini atte#%ts to raise the level o" abstraction "or distributed syste#s %rogra##ing, "ro# the network %rotocol level to the ob0ect inter"ace level. In the e#erging %roli"eration o" e#bedded devices connected to networks, #any %ieces o" a distributed syste# #ay co#e "ro# di""erent vendors. Jini #akes it unnecessary "or vendors o" devices to agree on network level %rotocols that allow their devices to interact. Instead, vendors #ust agree on Java inter"aces through which their devices can

1=4:

Thinking in Java

,,,'0ruceEckel'com

interact. The %rocesses o" discovery, 0oin, and looku%, %rovided by the Jini run'ti#e in"rastructure, enable devices to locate each other on the network. )nce they locate each other, devices can co##unicate with each other through Java inter"aces. RFSURFSTIJLT+(6PTE5MHTILMIU

1ummar:
6long with Jini "or local device networks, this cha%ter has introduced so#e, but not all, o" the co#%onents that Sun re"ers to as JKEE= the Java 2 Enter rise Edition. The goal o" JKEE is to build create a set o" tools that allows the Java develo%er to build server'based a%%lications #uch #ore Auickly than be"ore, and in a %lat"or#'inde%endent way. It s not only di""icult and ti#e'consu#ing to build such a%%lications, but it s es%ecially hard to build the# so that they can be easily %orted to other %lat"or#s, and also to kee% the business logic se%arated "ro# the underlying details o" the i#%le#entation. JKEE %rovides a "ra#ework to assist in creating server'based a%%lications; these a%%lications are in de#and now, and that de#and a%%ears to be increasing. RFSURF STIJLT+(6PTE5MHTILM2U

/0ercises
Solutions to selected e&ercises can be "ound in the electronic docu#entThe Thinking in Java "nnotated Solution @uide, available "or a s#all "ee "ro# ,,,'0ruceEckel'com.

!,6) +o#%ile and run the Jabber)erver and Jabber-lient


%rogra#s in this cha%ter. Cow edit the "iles to re#ove all o" the bu""ering "or the in%ut and out%ut, then co#%ile and run the# again to observe the results. RFSURFSTIJLT+(6PTE5MHTILK@U

!-7) +reate a server that asks "or a %assword, then o%ens a "ile and
sends the "ile over the network connection. +reate a client that connects to this server, gives the a%%ro%riate %assword, then ca%tures and saves the "ile. Test the %air o" %rogra#s on your #achine using the localhost *the local loo%back IP address >IZ!D!D!> %roduced by calling InetA''ress!get2y/ame An*llB,. RFSURFSTIJLT+(6PTE5MHTILKMU

1=4;

!-() Modi"y the server in E&ercise K so that it uses #ultithreading to


handle #ulti%le clients. RFSURFSTIJLT+(6PTE5MHTILKKU

!-!) Modi"y Jabber-lient!8ava so that out%ut "lushing doesn t


occur and observe the e""ect. RFSURFSTIJLT+(6PTE5MHTILKLU

!-*) Modi"y 1*ltiJabber)erver so that it uses thread ooling.


Instead o" throwing away a thread each ti#e a client disconnects, the thread should %ut itsel" into an !available %ool$ o" threads. :hen a new client wants to connect, the server will look in the available %ool "or a thread to handle the reAuest, and i" one isn t available, #ake a new one. This way the nu#ber o" threads necessary will naturally grow to the reAuired Auantity. The value o" thread %ooling is that it doesn t reAuire the overhead o" creating and destroying a new thread "or each new client. RFSURF STIJLT+(6PTE5MHTILK?U

!-+) Starting with )ho(HT1+!8ava, create an a%%let that is a


%assword'%rotected gateway to a %articular %ortion o" your :eb site. RFSURFSTIJLT+(6PTE5MHTILKHU

!-,) Modi"y -I -reateTables!8ava so that it reads the SeD


strings "ro# a te&t "ile instead o" -I )3+. RFSURF STIJLT+(6PTE5MHTILK3U

!--) +on"igure your syste# so that you can success"ully e&ecute


-I -reateTables!8ava and +oa' 2!8ava. RFSURF
STIJLT+(6PTE5MHTILKGU

!-4) Modi"y )ervlets$*le!8ava by overriding the 'estroyA B


#ethod to save the value o" i to a "ile, and and the initA B #ethod to restore the value. 7e#onstrate that it works by rebooting the servlet container. I" you do not have an e&isting servlet container, you will need to download, install, and run To#cat "ro# >akarta' a ache'org in order to run servlets. RFSURF STIJLT+(6PTE5MHTILKIU

!-5) +reate a servlet that adds a cookie to the res%onse ob0ect,


thereby storing it on the client s site. 6dd code to the servlet that retrieves and dis%lays the cookie. I" you do not have an e&isting

1=5=

Thinking in Java

,,,'0ruceEckel'com

servlet container, you will need to download, install, and run To#cat "ro# >akarta'a ache'org in order to run servlets. RFSURF STIJLT+(6PTE5MHTILK2U

!-6) +reate a servlet that uses a )ession ob0ect to store session


in"or#ation o" your choosing. In the sa#e servlet, retrieve and dis%lay that session in"or#ation. I" you do not have an e&isting servlet container, you will need to download, install, and run To#cat "ro# >akarta'a ache'org in order to run servlets. RFSURF STIJLT+(6PTE5MHTILL@U

!47) +reate a servlet that changes the inactive interval o" a session to
H seconds by calling get1a4InactiveIntervalA B. Test to see that the session does indeed e&%ire a"ter H seconds. I" you do not have an e&isting servlet container, you will need to download, install, and run To#cat "ro# >akarta'a ache'org in order to run servlets. RFSURFSTIJLT+(6PTE5MHTILLMU

!4() +reate a JSP %age that %rints a line o" te&t using the R(MU tag.
Set the color o" this te&t rando#ly, using Java code e#bedded in the JSP %age. I" you do not have an e&isting JSP container, you will need to download, install, and run To#cat "ro# >akarta' a ache'org in order to run JSPs. RFSURF STIJLT+(6PTE5MHTILLKU

!4!) Modi"y the #a&i#u# age value in -ookies!8sp and observe


the behavior under two di""erent browsers. 6lso note the di""erence between 0ust re'visiting the %age, and shutting down and restarting the browser. I" you do not have an e&isting JSP container, you will need to download, install, and run To#cat "ro# >akarta'a ache'org in order to run JSPs. RFSURF STIJLT+(6PTE5MHTILLLU

!4*) +reate a JSP with a "ield that allows the user to enter the
session e&%iration ti#e and and a second "ield that holds data that is stored in the session. The sub#it button re"reshes the %age and "etches the current e&%iration ti#e and session data and %uts the# in as de"ault values o" the a"ore#entioned "ields. I" you do not have an e&isting JSP container, you will need to download,

1=51

install, and run To#cat "ro# >akarta'a ache'org in order to run JSPs. RFSURFSTIJLT+(6PTE5MHTILL?U

!4+) *More challenging, Take the V+ook*p!8ava %rogra# and


#odi"y it so that when you click on the resulting na#e it auto#atically takes that na#e and co%ies it to the cli%board *so you can si#%ly %aste it into your e#ail,. /ou ll need to look back at +ha%ter ML to re#e#ber how to use the cli%board in JE+. RFSU

1=52

Thinking in Java

,,,'0ruceEckel'com

A: assing L $eturning Ob3ects


RFSTIJLT6PPEC7IZ6TI@UBy now you should be reasonably co#"ortable with the idea that when you re !%assing$ an ob0ect, you re actually %assing a re"erence.
In #any %rogra##ing languages you can use that language s !regular$ way to %ass ob0ects around, and #ost o" the ti#e everything works "ine. But it always see#s that there co#es a %oint at which you #ust do so#ething irregular and suddenly things get a bit #ore co#%licated *or in the case o" +<<, Auite co#%licated,. Java is no e&ce%tion, and it s i#%ortant that you understand e&actly what s ha%%ening as you %ass ob0ects around and #ani%ulate the#. This a%%endi& will %rovide that insight. RFSURFSTIJLT6PPEC7IZ6TIMU 6nother way to %ose the Auestion o" this a%%endi&, i" you re co#ing "ro# a %rogra##ing language so eAui%%ed, is !7oes Java have %ointersO$ So#e have clai#ed that %ointers are hard and dangerous and there"ore bad, and since Java is all goodness and light and will li"t your earthly %rogra##ing burdens, it cannot %ossibly contain such things. (owever, it s #ore accurate to say that Java has %ointers; indeed, every ob0ect identi"ier in Java *e&ce%t "or %ri#itives, is one o" these %ointers, but their use is restricted and guarded not only by the co#%iler but by the run'ti#e syste#. )r to %ut it another way, Java has %ointers, but no %ointer arith#etic. These are what I ve been calling !re"erences,$ and you can think o" the# as !sa"ety %ointers,$ not unlike the sa"ety scissors o" ele#entary school9they aren t shar%, so you cannot hurt yoursel" without great e""ort, but they can so#eti#es be slow and tedious. RFSURF STIJLT6PPEC7IZ6TIKU

1=53

assing references around


:hen you %ass a re"erence into a #ethod, you re still %ointing to the sa#e ob0ect. 6 si#%le e&%eri#ent de#onstrates this=

//3 a""en!i6a3Pass5eferences.Hava // Passing references aroun!. "ublic class Pass5eferences @ static voi! f-Pass5eferences h. @ %yste#.out."rintln-8h insi!e f-.3 8 K h.< A "ublic static voi! #ain-%tringNO args. @ Pass5eferences " ? ne: Pass5eferences-.< %yste#.out."rintln-8" insi!e #ain-.3 8 K ".< f-".< A A ///3>
The #ethod to)tringA B is auto#atically invoked in the %rint state#ents, and #ass$eferences inherits directly "ro# .b8ect with no rede"inition o" to)tringA B. Thus, .b8ect s version o" to)tringA B is used, which %rints out the class o" the ob0ect "ollowed by the address where that ob0ect is located *not the re"erence, but the actual ob0ect storage,. The out%ut looks like this=

" insi!e #ain-.3 Pass5eferencesR(+,)*I1 h insi!e f-.3 Pass5eferencesR(+,)*I1


/ou can see that both p and h re"er to the sa#e ob0ect. This is "ar #ore e""icient than du%licating a new #ass$eferences ob0ect 0ust so that you can send an argu#ent to a #ethod. But it brings u% an i#%ortant issue. RFSURFSTIJLT6PPEC7IZ6TILU

Aliasing
6liasing #eans that #ore than one re"erence is tied to the sa#e ob0ect, as in the above e&a#%le. The %roble# with aliasing occurs when so#eone

1=54

Thinking in Java

,,,'0ruceEckel'com

,rites to that ob0ect. I" the owners o" the other re"erences aren t
e&%ecting that ob0ect to change, they ll be sur%rised. This can be de#onstrated with a si#%le e&a#%le=

//3 a""en!i6a30lias(.Hava // 0liasing t:o references to one obHect. "ublic class 0lias( @ int i< 0lias(-int ii. @ i ? ii< A "ublic static voi! #ain-%tringNO args. @ 0lias( 6 ? ne: 0lias(-*.< 0lias( y ? 6< // 0ssign the reference %yste#.out."rintln-863 8 K 6.i.< %yste#.out."rintln-8y3 8 K y.i.< %yste#.out."rintln-8$ncre#enting 68.< 6.iKK< %yste#.out."rintln-863 8 K 6.i.< %yste#.out."rintln-8y3 8 K y.i.< A A ///3>
In the line=

0lias( y ? 6< // 0ssign the reference


a new Alias> re"erence is created, but instead o" being assigned to a "resh ob0ect created with ne(, it s assigned to an e&isting re"erence. So the contents o" re"erence 4, which is the address o" the ob0ect 4 is %ointing to, is assigned to y, and thus both 4 and y are attached to the sa#e ob0ect. So when 4 s i is incre#ented in the state#ent= RFSURF STIJLT6PPEC7IZ6TI?U

6.iKK< y s i will be a""ected as well. This can be seen in the out%ut= 63 * y3 * $ncre#enting 6 63 1 y3 1

1=55

)ne good solution in this case is to si#%ly not do it= don t consciously alias #ore than one re"erence to an ob0ect at the sa#e sco%e. /our code will be #uch easier to understand and debug. (owever, when you re %assing a re"erence in as an argu#ent9which is the way Java is su%%osed to work9you auto#atically alias because the local re"erence that s created can #odi"y the !outside ob0ect$ *the ob0ect that was created outside the sco%e o" the #ethod,. (ere s an e&a#%le= RFSURF STIJLT6PPEC7IZ6TIHU

//3 a""en!i6a30lias .Hava // Jetho! calls i#"licitly alias their // argu#ents. "ublic class 0lias @ int i< 0lias -int ii. @ i ? ii< A static voi! f-0lias reference. @ reference.iKK< A "ublic static voi! #ain-%tringNO args. @ 0lias 6 ? ne: 0lias -*.< %yste#.out."rintln-863 8 K 6.i.< %yste#.out."rintln-8Calling f-6.8.< f-6.< %yste#.out."rintln-863 8 K 6.i.< A A ///3>
The out%ut is=

63 * Calling f-6. 63 1
The #ethod is changing its argu#ent, the outside ob0ect. :hen this kind o" situation arises, you #ust decide whether it #akes sense, whether the user e&%ects it, and whether it s going to cause %roble#s. RFSURF STIJLT6PPEC7IZ6TI3U In general, you call a #ethod in order to %roduce a return value andFor a change o" state in the ob0ect that the method is called $or. *6 #ethod is

1=57

Thinking in Java

,,,'0ruceEckel'com

how you !send a #essage$ to that ob0ect., It s #uch less co##on to call a #ethod in order to #ani%ulate its argu#ents; this is re"erred to as !calling a #ethod "or its side e$$ects.$ Thus, when you create a #ethod that #odi"ies its argu#ents the user #ust be clearly instructed and warned about the use o" that #ethod and its %otential sur%rises. Because o" the con"usion and %it"alls, it s #uch better to avoid changing the argu#ent. RFSURFSTIJLT6PPEC7IZ6TIGU I" you need to #odi"y an argu#ent during a #ethod call and you don t intend to #odi"y the outside argu#ent, then you should %rotect that argu#ent by #aking a co%y inside your #ethod. That s the sub0ect o" #uch o" this a%%endi&. RFSURFSTIJLT6PPEC7IZ6TIIU

Making local co.ies


To review= 6ll argu#ent %assing in Java is %er"or#ed by %assing re"erences. That is, when you %ass !an ob0ect,$ you re really %assing only a re"erence to an ob0ect that lives outside the #ethod, so i" you %er"or# any #odi"ications with that re"erence, you #odi"y the outside ob0ect. In addition=

6liasing ha%%ens auto#atically during argu#ent %assing. There are no local ob0ects, only local re"erences. 5e"erences have sco%es, ob0ects do not. )b0ect li"eti#e is never an issue in Java. There is no language su%%ort *e.g., !const$, to %revent ob0ects "ro# being
#odi"ied *that is, to %revent the negative e""ects o" aliasing,. I" you re only reading in"or#ation "ro# an ob0ect and not #odi"ying it, %assing a re"erence is the #ost e""icient "or# o" argu#ent %assing. This is nice; the de"ault way o" doing things is also the #ost e""icient. (owever, so#eti#es it s necessary to be able to treat the ob0ect as i" it were !local$ so that changes you #ake a""ect only a local co%y and do not #odi"y the outside ob0ect. Many %rogra##ing languages su%%ort the ability to

1=58

auto#atically #ake a local co%y o" the outside ob0ect, inside the #ethod @. Java does not, but it allows you to %roduce this e""ect. RFSURF STIJLT6PPEC7IZ6TI2U

ass b: value
This brings u% the ter#inology issue, which always see#s good "or an argu#ent. The ter# is !%ass by value,$ and the #eaning de%ends on how you %erceive the o%eration o" the %rogra#. The general #eaning is that you get a local co%y o" whatever you re %assing, but the real Auestion is how you think about what you re %assing. :hen it co#es to the #eaning o" !%ass by value,$ there are two "airly distinct ca#%s=

(6,) Java %asses everything by value. :hen you re %assing %ri#itives


into a #ethod, you get a distinct co%y o" the %ri#itive. :hen you re %assing a re"erence into a #ethod, you get a co%y o" the re"erence. Ergo, everything is %ass'by'value. )" course, the assu#%tion is that you re always thinking *and caring, that re"erences are being %assed, but it see#s like the Java design has gone a long way toward allowing you to ignore *#ost o" the ti#e, that you re working with a re"erence. That is, it see#s to allow you to think o" the re"erence as !the ob0ect,$ since it i#%licitly dere"erences it whenever you #ake a #ethod call. RFSURF STIJLT6PPEC7IZ6TIM@U

(6-) Java %asses %ri#itives by value *no argu#ent there,, but ob0ects
are %assed by re"erence. This is the world view that the re"erence is an alias "or the ob0ect, so you donJt think about %assing re"erences, but instead say !I # %assing the ob0ect.$ Since you don t get a local co%y o" the ob0ect when you %ass it into a #ethod, ob0ects are clearly not %assed by value. There a%%ears to be so#e su%%ort "or this view within Sun, since at one ti#e, one o" the !reserved but not i#%le#ented$ keywords was byval*e. * There s no knowing,

however, whether that keyword will ever see the light o" day.This will %robably never be i#%le#ented, . RFSURF
STIJLT6PPEC7IZ6TIMMU
@ In +, which generally handles s#all bits o" data, the de"ault is %ass'by'value. +<< had to "ollow this "or#, but with ob0ects %ass'by'value isn t usually the #ost e""icient way. In addition, coding classes to su%%ort %ass'by'value in +<< is a big headache.

1=5:

Thinking in Java

,,,'0ruceEckel'com

(aving given both ca#%s a good airing, and a"ter saying !It de%ends on how you think o" a re"erence,$ I will atte#%t to sideste% the issue. In the end, it isn t that i#%ortant9what is i#%ortant is that you understand that %assing a re"erence allows the caller s ob0ect to be changed une&%ectedly. RFSURFSTIJLT6PPEC7IZ6TIMKU

Cloning ob3ects
The #ost likely reason "or #aking a local co%y o" an ob0ect is i" you re going to #odi"y that ob0ect and you don t want to #odi"y the caller s ob0ect. I" you decide that you want to #ake a local co%y, you si#%ly use the cloneA B #ethod to %er"or# the o%eration. This is a #ethod that s de"ined as protecte' in the base class .b8ect, and which you #ust override as p*blic in any derived classes that you want to clone. Eor e&a#%le, the standard library class Array+ist overrides cloneA B, so we can call cloneA B "or Array+ist=

//3 a""en!i6a3Cloning.Hava // The clone-. o"eration :orks for only a fe: // ite#s in the stan!ar! Java library. i#"ort Hava.util.B< class $nt @ "rivate int i< "ublic $nt-int ii. @ i ? ii< A "ublic voi! incre#ent-. @ iKK< A "ublic %tring to%tring-. @ return $nteger.to%tring-i.< A A "ublic class Cloning @ "ublic static voi! #ain-%tringNO args. @ 0rrayList v ? ne: 0rrayList-.< for-int i ? '< i P ('< iKK . v.a!!-ne: $nt-i..< %yste#.out."rintln-8v3 8 K v.< 0rrayList v ? -0rrayList.v.clone-.< // $ncre#ent all v 2s ele#ents3 for-$terator e ? v .iterator-.<

1=5;

e.has&e6t-.< . --$nt.e.ne6t-...incre#ent-.< // %ee if it change! v2s ele#ents3 %yste#.out."rintln-8v3 8 K v.< A A ///3>


The cloneA B #ethod %roduces an .b8ect, which #ust then be recast to the %ro%er ty%e. This e&a#%le shows how Array+ist s cloneA B #ethod does not auto#atically try to clone each o" the ob0ects that the Array+ist contains9the old Array+ist and the cloned Array+ist are aliased to the sa#e ob0ects. This is o"ten called a shallo, co )D since it s co%ying only the !sur"ace$ %ortion o" an ob0ect. The actual ob0ect consists o" this !sur"ace,$ %lus all the ob0ects that the re"erences are %ointing to, %lus all the ob0ects those ob0ects are %ointing to, etc. This is o"ten re"erred to as the !web o" ob0ects.$ +o%ying the entire #ess is called a dee co )' RF SURFSTIJLT6PPEC7IZ6TIMLU /ou can see the e""ect o" the shallow co%y in the out%ut, where the actions %er"or#ed on vI a""ect v=

v3 N', (, , ), I, ,, +, *, 1, CO v3 N(, , ), I, ,, +, *, 1, C, ('O


Cot trying to cloneA B the ob0ects contained in the Array+ist is %robably a "air assu#%tion because there s no guarantee that those ob0ects are cloneable @. RFSURFSTIJLT6PPEC7IZ6TIM?U

Adding cloneabilit: to a class


Even though the clone #ethod is de"ined in the base'o"'all'classes

.b8ect, cloning is not auto#atically available in every class @. This would


@ This is not the dictionary s%elling o" the word, but it s what is used in the Java library, so I ve used it here, too, in so#e ho%es o" reducing con"usion. @ /ou can a%%arently create a si#%le counter'e&a#%le to this state#ent, like this=

"ublic class Cloneit i#"le#ents Cloneable @ "ublic static voi! #ain -%tringNO args. thro:s Clone&ot%u""orte!E6ce"tion @ Cloneit a ? ne: Cloneit-.<

1=7=

Thinking in Java

,,,'0ruceEckel'com

see# to be counterintuitive to the idea that base'class #ethods are always available in derived classes. +loning in Java goes against this idea; i" you want it to e&ist "or a class, you #ust s%eci"ically add code to #ake cloning work. RFSURFSTIJLT6PPEC7IZ6TIMHU

Csing a trick with

rotected

To %revent de"ault cloneability in every class you create, the cloneA B #ethod is protecte' in the base class .b8ect. Cot only does this #ean that it s not available by de"ault to the client %rogra##er who is si#%ly using the class *not subclassing it,, but it also #eans that you cannot call cloneA B via a re"erence to the base class. *6lthough that #ight see# to be use"ul in so#e situations, such as to %oly#or%hically clone a bunch o" .b8ects., It is in e""ect a way to give you, at co#%ile'ti#e, the in"or#ation that your ob0ect is not cloneable9and oddly enough #ost classes in the standard Java library are not cloneable. Thus, i" you say=

$nteger 6 ? ne: $nteger-(.< 6 ? 6.clone-.<


/ou will get, at co#%ile'ti#e, an error #essage that says cloneA B is not accessible *since Integer doesn t override it and it de"aults to the protecte' version,. RFSURFSTIJLT6PPEC7IZ6TIM3U I", however, you re in a class derived "ro# .b8ect *as all classes are,, then you have %er#ission to call .b8ect!cloneA B because it s protecte' and you re an inheritor. The base class cloneA B has use"ul "unctionality9it %er"or#s the actual bitwise du%lication o$ the derived/class ob>ect, thus acting as the co##on cloning o%eration. (owever, you then need to #ake )our clone o%eration p*blic "or it to be accessible. So, two key issues when you clone are= RFSURFSTIJLT6PPEC7IZ6TIMGU

Virtually always call s*per!cloneA B Make your clone p*blic


Cloneit b ? -Cloneit.a.clone-.<

A A (owever, this only works because mainA B is a #ethod o" -loneit and thus has %er#ission to call the protecte' base'class #ethod cloneA B. I" you call it "ro# a di""erent class, it won t co#%ile.

1=71

/ou ll %robably want to override cloneA B in any "urther derived classes, otherwise your *now p*blic, cloneA B will be used, and that #ight not do the right thing *although, since .b8ect!cloneA B #akes a co%y o" the actual ob0ect, it #ight,. The protecte' trick works only once9the "irst ti#e you inherit "ro# a class that has no cloneability and you want to #ake a class that s cloneable. In any classes inherited "ro# your class the cloneA B #ethod is available since it s not %ossible in Java to reduce the access o" a #ethod during derivation. That is, once a class is cloneable, everything derived "ro# it is cloneable unless you use %rovided #echanis#s *described later, to !turn o""$ cloning. RFSURF STIJLT6PPEC7IZ6TIMIU

Im.lementing the $loneable interface


There s one #ore thing you need to do to co#%lete the cloneability o" an ob0ect= i#%le#ent the -loneable interface. This interface is a bit strange, because it s e#%ty.

interface Cloneable @A
The reason "or i#%le#enting this e#%ty interface is obviously not because you are going to u%cast to -loneable and call one o" its #ethods. The use o" interface here is considered by so#e to be a !hack$ because it s using a "eature "or so#ething other than its original intent. I#%le#enting the -loneable interface acts as a kind o" a "lag, wired into the ty%e o" the class. RFSURFSTIJLT6PPEC7IZ6TIM2U There are two reasons "or the e&istence o" the -loneable interface. Eirst, you #ight have an u%cast re"erence to a base ty%e and not know whether it s %ossible to clone that ob0ect. In this case, you can use the instanceof keyword *described in +ha%ter MK, to "ind out whether the re"erence is connected to an ob0ect that can be cloned=

if-#y5eference instanceof Cloneable. // ...


The second reason is that #i&ed into this design "or cloneability was the thought that #aybe you didn t want all ty%es o" ob0ects to be cloneable. So .b8ect!cloneA B veri"ies that a class i#%le#ents the -loneable inter"ace. I" not, it throws a -lone/ot)*pporte'&4ception e&ce%tion. So in general, you re "orced to implement -loneable as %art o" su%%ort "or cloning. RFSURFSTIJLT6PPEC7IZ6TIK@U

1=72

Thinking in Java

,,,'0ruceEckel'com

1uccessful cloning
)nce you understand the details o" i#%le#enting the cloneA B #ethod, you re able to create classes that can be easily du%licated to %rovide a local co%y=

//3 a""en!i6a3LocalCo"y.Hava // Creating local co"ies :ith clone-.. i#"ort Hava.util.B< class JyGbHect i#"le#ents Cloneable @ int i< JyGbHect-int ii. @ i ? ii< A "ublic GbHect clone-. @ GbHect o ? null< try @ o ? su"er.clone-.< A catch-Clone&ot%u""orte!E6ce"tion e. @ %yste#.err."rintln-8JyGbHect can2t clone8.< A return o< A "ublic %tring to%tring-. @ return $nteger.to%tring-i.< A A "ublic class LocalCo"y @ static JyGbHect g-JyGbHect v. @ // Passing a reference, // #o!ifies outsi!e obHect3 v.iKK< return v< A static JyGbHect f-JyGbHect v. @ v ? -JyGbHect.v.clone-.< // Local co"y v.iKK< return v< A "ublic static voi! #ain-%tringNO args. @ JyGbHect a ? ne: JyGbHect-((.<

1=73

JyGbHect b ? g-a.< // Testing reference e=uivalence, // not obHect e=uivalence3 if-a ?? b. %yste#.out."rintln-8a ?? b8.< else %yste#.out."rintln-8a 4? b8.< %yste#.out."rintln-8a ? 8 K a.< %yste#.out."rintln-8b ? 8 K b.< JyGbHect c ? ne: JyGbHect-I*.< JyGbHect ! ? f-c.< if-c ?? !. %yste#.out."rintln-8c ?? !8.< else %yste#.out."rintln-8c 4? !8.< %yste#.out."rintln-8c ? 8 K c.< %yste#.out."rintln-8! ? 8 K !.< A A ///3>
Eirst o" all, cloneA B #ust be accessible so you #ust #ake it p*blic. Second, "or the initial %art o" your cloneA B o%eration you should call the base'class version o" cloneA B. The cloneA B that s being called here is the one that s %rede"ined inside .b8ect, and you can call it because it s protecte' and thereby accessible in derived classes. RFSURF STIJLT6PPEC7IZ6TIKMU

.b8ect!cloneA B "igures out how big the ob0ect is, creates enough
#e#ory "or a new one, and co%ies all the bits "ro# the old to the new. This is called a bit,ise co )D and is ty%ically what you d e&%ect a cloneA B #ethod to do. But be"ore .b8ect!cloneA B %er"or#s its o%erations, it "irst checks to see i" a class is -loneable9that is, whether it i#%le#ents the -loneable inter"ace. I" it doesn t, .b8ect!cloneA B throws a -lone/ot)*pporte'&4ception to indicate that you can t clone it. Thus, you ve got to surround your call to s*per!cloneA B with a try'catch block, to catch an e&ce%tion that should never ha%%en *because you ve i#%le#ented the -loneable inter"ace,. RFSURF STIJLT6PPEC7IZ6TIKKU

1=74

Thinking in Java

,,,'0ruceEckel'com

In +ocal-opy, the two #ethods gA B and fA B de#onstrate the di""erence between the two a%%roaches "or argu#ent %assing. gA B shows %assing by re"erence in which it #odi"ies the outside ob0ect and returns a re"erence to that outside ob0ect, while fA B clones the argu#ent, thereby decou%ling it and leaving the original ob0ect alone. It can then %roceed to do whatever it wants, and even to return a re"erence to this new ob0ect without any ill e""ects to the original. Cotice the so#ewhat curious'looking state#ent=

v ? -JyGbHect.v.clone-.<
This is where the local co%y is created. To %revent con"usion by such a state#ent, re#e#ber that this rather strange coding idio# is %er"ectly "easible in Java because every ob0ect identi"ier is actually a re"erence. So the re"erence v is used to cloneA B a co%y o" what it re"ers to, and this returns a re"erence to the base ty%e .b8ect *because it s de"ined that way in .b8ect!cloneA B, that #ust then be cast to the %ro%er ty%e. RFSURF STIJLT6PPEC7IZ6TIKLU In mainA B, the di""erence between the e""ects o" the two di""erent argu#ent'%assing a%%roaches in the two di""erent #ethods is tested. The out%ut is=

a a b c c !

?? b ? ( ? ( 4? ! ? I* ? I1

It s i#%ortant to notice that the eAuivalence tests in Java do not look inside the ob0ects being co#%ared to see i" their values are the sa#e. The PP and =P o%erators are si#%ly co#%aring the re$erences. I" the addresses inside the re"erences are the sa#e, the re"erences are %ointing to the sa#e ob0ect and are there"ore !eAual.$ So what the o%erators are really testing is whether the re"erences are aliased to the sa#e ob0ect. RF SURFSTIJLT6PPEC7IZ6TIK?U

#he effect of Object.clone1 2


:hat actually ha%%ens when .b8ect!cloneA B is called that #akes it so essential to call s*per!cloneA B when you override cloneA B in your

1=75

classO The cloneA B #ethod in the root class is res%onsible "or creating the correct a#ount o" storage and #aking the bitwise co%y o" the bits "ro# the original ob0ect into the new ob0ect s storage. That is, it doesn t 0ust #ake storage and co%y an .b8ect9it actually "igures out the si1e o" the %recise ob0ect that s being co%ied and du%licates that. Since all this is ha%%ening "ro# the code in the cloneA B #ethod de"ined in the root class *that has no idea what s being inherited "ro# it,, you can guess that the %rocess involves 5TTI to deter#ine the actual ob0ect that s being cloned. This way, the cloneA B #ethod can create the %ro%er a#ount o" storage and do the correct bitco%y "or that ty%e. RFSURF STIJLT6PPEC7IZ6TIKHU :hatever you do, the "irst %art o" the cloning %rocess should nor#ally be a call to s*per!cloneA B. This establishes the groundwork "or the cloning o%eration by #aking an e&act du%licate. 6t this %oint you can %er"or# other o%erations necessary to co#%lete the cloning. RFSURF STIJLT6PPEC7IZ6TIK3U To know "or sure what those other o%erations are, you need to understand e&actly what .b8ect!cloneA B buys you. In %articular, does it auto#atically clone the destination o" all the re"erencesO The "ollowing e&a#%le tests this=

//3 a""en!i6a3%nake.Hava // Tests cloning to see if !estination // of references are also clone!. "ublic class %nake i#"le#ents Cloneable @ "rivate %nake ne6t< "rivate char c< // Walue of i ?? nu#ber of seg#ents %nake-int i, char 6. @ c ? 6< if---i Q '. ne6t ? ne: %nake-i, -char.-6 K (..< A voi! incre#ent-. @ cKK< if-ne6t 4? null. ne6t.incre#ent-.<

1=77

Thinking in Java

,,,'0ruceEckel'com

A "ublic %tring to%tring-. @ %tring s ? 838 K c< if-ne6t 4? null. s K? ne6t.to%tring-.< return s< A "ublic GbHect clone-. @ GbHect o ? null< try @ o ? su"er.clone-.< A catch-Clone&ot%u""orte!E6ce"tion e. @ %yste#.err."rintln-8%nake can2t clone8.< A return o< A "ublic static voi! #ain-%tringNO args. @ %nake s ? ne: %nake-,, 2a2.< %yste#.out."rintln-8s ? 8 K s.< %nake s ? -%nake.s.clone-.< %yste#.out."rintln-8s ? 8 K s .< s.incre#ent-.< %yste#.out."rintln8after s.incre#ent, s ? 8 K s .< A A ///3>
6 )nake is #ade u% o" a bunch o" seg#ents, each o" ty%e )nake. Thus, it s a singly linked list. The seg#ents are created recursively, decre#enting the "irst constructor argu#ent "or each seg#ent until 1ero is reached. To give each seg#ent a uniAue tag, the second argu#ent, a char, is incre#ented "or each recursive constructor call. RFSURF STIJLT6PPEC7IZ6TIKGU The incrementA B #ethod recursively incre#ents each tag so you can see the change, and the to)tringA B recursively %rints each tag. The out%ut is=

s ? 3a3b3c3!3e s ? 3a3b3c3!3e after s.incre#ent, s

? 3a3c3!3e3f

1=78

This #eans that only the "irst seg#ent is du%licated by .b8ect!cloneA B, there"ore it does a shallow co%y. I" you want the whole snake to be du%licated9a dee% co%y9you #ust %er"or# the additional o%erations inside your overridden cloneA B. RFSURFSTIJLT6PPEC7IZ6TIKIU /ou ll ty%ically call s*per!cloneA B in any class derived "ro# a cloneable class to #ake sure that all o" the base'class o%erations *including .b8ect! cloneA B, take %lace. This is "ollowed by an e&%licit call to cloneA B "or every re"erence in your ob0ect; otherwise those re"erences will be aliased to those o" the original ob0ect. It s analogous to the way constructors are called9base'class constructor "irst, then the ne&t'derived constructor, and so on to the #ost'derived constructor. The di""erence is that cloneA B is not a constructor, so there s nothing to #ake it ha%%en auto#atically. /ou #ust #ake sure to do it yoursel". RFSURFSTIJLT6PPEC7IZ6TIK2U

Cloning a com.osed ob3ect


There s a %roble# you ll encounter when trying to dee% co%y a co#%osed ob0ect. /ou #ust assu#e that the cloneA B #ethod in the #e#ber ob0ects will in turn %er"or# a dee% co%y on their re"erences, and so on. This is Auite a co##it#ent. It e""ectively #eans that "or a dee% co%y to work you #ust either control all o" the code in all o" the classes, or at least have enough knowledge about all o" the classes involved in the dee% co%y to know that they are %er"or#ing their own dee% co%y correctly. RFSURF STIJLT6PPEC7IZ6TIL@U This e&a#%le shows what you #ust do to acco#%lish a dee% co%y when dealing with a co#%osed ob0ect=

//3 a""en!i6a3Dee"Co"y.Hava // Cloning a co#"ose! obHect. class De"th5ea!ing i#"le#ents Cloneable @ "rivate !ouble !e"th< "ublic De"th5ea!ing-!ouble !e"th. @ this.!e"th ? !e"th< A "ublic GbHect clone-. @ GbHect o ? null< try @

1=7:

Thinking in Java

,,,'0ruceEckel'com

o ? su"er.clone-.< A catch-Clone&ot%u""orte!E6ce"tion e. @ e."rint%tackTrace-%yste#.err.< A return o< A A class Te#"erature5ea!ing i#"le#ents Cloneable @ "rivate long ti#e< "rivate !ouble te#"erature< "ublic Te#"erature5ea!ing-!ouble te#"erature. @ ti#e ? %yste#.currentTi#eJillis-.< this.te#"erature ? te#"erature< A "ublic GbHect clone-. @ GbHect o ? null< try @ o ? su"er.clone-.< A catch-Clone&ot%u""orte!E6ce"tion e. @ e."rint%tackTrace-%yste#.err.< A return o< A A class Gcean5ea!ing i#"le#ents Cloneable @ "rivate De"th5ea!ing !e"th< "rivate Te#"erature5ea!ing te#"erature< "ublic Gcean5ea!ing-!ouble t!ata, !ouble !!ata.@ te#"erature ? ne: Te#"erature5ea!ing-t!ata.< !e"th ? ne: De"th5ea!ing-!!ata.< A "ublic GbHect clone-. @ Gcean5ea!ing o ? null< try @ o ? -Gcean5ea!ing.su"er.clone-.< A catch-Clone&ot%u""orte!E6ce"tion e. @ e."rint%tackTrace-%yste#.err.< A // Just clone references3

1=7;

o.!e"th ? -De"th5ea!ing.o.!e"th.clone-.< o.te#"erature ? -Te#"erature5ea!ing.o.te#"erature.clone-.< return o< // Y"casts back to GbHect A A "ublic class Dee"Co"y @ "ublic static voi! #ain-%tringNO args. @ Gcean5ea!ing rea!ing ? ne: Gcean5ea!ing-)).C, (''.,.< // &o: clone it3 Gcean5ea!ing r ? -Gcean5ea!ing.rea!ing.clone-.< A A ///3> epth$ea'ing and Temperat*re$ea'ing are Auite si#ilar; they both contain only %ri#itives. There"ore, the cloneA B #ethod can be Auite si#%le= it calls s*per!cloneA B and returns the result. Cote that the cloneA B code "or both classes is identical. RFSURF
STIJLT6PPEC7IZ6TILMU

.cean$ea'ing is co#%osed o" epth$ea'ing and Temperat*re$ea'ing ob0ects and so, to %roduce a dee% co%y, its cloneA B #ust clone the re"erences inside .cean$ea'ing. To acco#%lish this, the result o" s*per!cloneA B #ust be cast to an .cean$ea'ing ob0ect *so you can access the 'epth and temperat*re
re"erences,. RFSURFSTIJLT6PPEC7IZ6TILKU

A dee. co.: with Array#ist


Det s revisit the Array+ist e&a#%le "ro# earlier in this a%%endi&. This ti#e the IntI class is cloneable, so the Array+ist can be dee% co%ied=

//3 a""en!i6a30!!ingClone.Hava // ;ou #ust go through a fe: gyrations // to a!! cloning to your o:n class. i#"ort Hava.util.B< class $nt i#"le#ents Cloneable @

1=8=

Thinking in Java

,,,'0ruceEckel'com

"rivate int i< "ublic $nt -int ii. @ i ? ii< A "ublic voi! incre#ent-. @ iKK< A "ublic %tring to%tring-. @ return $nteger.to%tring-i.< A "ublic GbHect clone-. @ GbHect o ? null< try @ o ? su"er.clone-.< A catch-Clone&ot%u""orte!E6ce"tion e. @ %yste#.err."rintln-8$nt can2t clone8.< A return o< A A // Gnce it2s cloneable, inheritance // !oesn2t re#ove cloneability3 class $nt) e6ten!s $nt @ "rivate int H< // 0uto#atically !u"licate! "ublic $nt)-int i. @ su"er-i.< A A "ublic class 0!!ingClone @ "ublic static voi! #ain-%tringNO args. @ $nt 6 ? ne: $nt -('.< $nt 6 ? -$nt .6.clone-.< 6 .incre#ent-.< %yste#.out."rintln86 ? 8 K 6 K 8, 6 ? 8 K 6 .< // 0nything inherite! is also cloneable3 $nt) 6) ? ne: $nt)-*.< 6) ? -$nt).6).clone-.< 0rrayList v ? ne: 0rrayList-.< for-int i ? '< i P ('< iKK . v.a!!-ne: $nt -i..< %yste#.out."rintln-8v3 8 K v.< 0rrayList v ? -0rrayList.v.clone-.< // &o: clone each ele#ent3

1=81

for-int i ? '< i P v.siUe-.< iKK. v .set-i, --$nt .v .get-i...clone-..< // $ncre#ent all v 2s ele#ents3 for-$terator e ? v .iterator-.< e.has&e6t-.< . --$nt .e.ne6t-...incre#ent-.< // %ee if it change! v2s ele#ents3 %yste#.out."rintln-8v3 8 K v.< %yste#.out."rintln-8v 3 8 K v .< A A ///3> IntJ is inherited "ro# IntI and a new %ri#itive #e#ber int 8 is added. /ou #ight think that you d need to override cloneA B again to #ake sure 8 is co%ied, but that s not the case. :hen IntI s cloneA B is called as IntJ s cloneA B, it calls .b8ect!cloneA B, which deter#ines that it s working with an IntJ and du%licates all the bits in the IntJ. 6s long as you don t add re"erences that need to be cloned, the one call to .b8ect!cloneA B
%er"or#s all o" the necessary du%lication, regardless o" how "ar down in the hierarchy cloneA B is de"ined. RFSURFSTIJLT6PPEC7IZ6TILLU /ou can see what s necessary in order to do a dee% co%y o" an Array+ist= a"ter the Array+ist is cloned, you have to ste% through and clone each one o" the ob0ects %ointed to by the Array+ist. /ou d have to do so#ething si#ilar to this to do a dee% co%y o" a Hash1ap. RFSURF STIJLT6PPEC7IZ6TIL?U The re#ainder o" the e&a#%le shows that the cloning did ha%%en by showing that, once an ob0ect is cloned, you can change it and the original ob0ect is le"t untouched. RFSURFSTIJLT6PPEC7IZ6TILHU

Dee. co.: via seriali?ation


:hen you consider Java s ob0ect seriali1ation *introduced in +ha%ter MM,, you #ight observe that an ob0ect that s seriali1ed and then deseriali1ed is, in e""ect, cloned. RFSURFSTIJLT6PPEC7IZ6TIL3U So why not use seriali1ation to %er"or# dee% co%yingO (ere s an e&a#%le that co#%ares the two a%%roaches by ti#ing the#=

//3 a""en!i6a3Co#"ete.Hava

1=82

Thinking in Java

,,,'0ruceEckel'com

i#"ort Hava.io.B< class Thing( i#"le#ents %erialiUable @A class Thing i#"le#ents %erialiUable @ Thing( o( ? ne: Thing(-.< A class Thing) i#"le#ents Cloneable @ "ublic GbHect clone-. @ GbHect o ? null< try @ o ? su"er.clone-.< A catch-Clone&ot%u""orte!E6ce"tion e. @ %yste#.err."rintln-8Thing) can2t clone8.< A return o< A A class ThingI i#"le#ents Cloneable @ Thing) o) ? ne: Thing)-.< "ublic GbHect clone-. @ ThingI o ? null< try @ o ? -ThingI.su"er.clone-.< A catch-Clone&ot%u""orte!E6ce"tion e. @ %yste#.err."rintln-8ThingI can2t clone8.< A // Clone the fiel!, too3 o.o) ? -Thing).o).clone-.< return o< A A "ublic class Co#"ete @ static final int %$TE ? ,'''< "ublic static voi! #ain-%tringNO args. thro:s E6ce"tion @ Thing NO a ? ne: Thing N%$TEO< for-int i ? '< i P a.length< iKK. aNiO ? ne: Thing -.<

1=83

ThingINO b ? ne: ThingIN%$TEO< for-int i ? '< i P b.length< iKK. bNiO ? ne: ThingI-.< long t( ? %yste#.currentTi#eJillis-.< Byte0rrayGut"ut%trea# buf ? ne: Byte0rrayGut"ut%trea#-.< GbHectGut"ut%trea# o ? ne: GbHectGut"ut%trea#-buf.< for-int i ? '< i P a.length< iKK. o.:riteGbHect-aNiO.< // &o: get co"ies3 GbHect$n"ut%trea# in ? ne: GbHect$n"ut%trea#ne: Byte0rray$n"ut%trea#buf.toByte0rray-...< Thing NO c ? ne: Thing N%$TEO< for-int i ? '< i P c.length< iKK. cNiO ? -Thing .in.rea!GbHect-.< long t ? %yste#.currentTi#eJillis-.< %yste#.out."rintln8Du"lication via serialiUation3 8 K -t - t(. K 8 Jillisecon!s8.< // &o: try cloning3 t( ? %yste#.currentTi#eJillis-.< ThingINO ! ? ne: ThingIN%$TEO< for-int i ? '< i P !.length< iKK. !NiO ? -ThingI.bNiO.clone-.< t ? %yste#.currentTi#eJillis-.< %yste#.out."rintln8Du"lication via cloning3 8 K -t - t(. K 8 Jillisecon!s8.< A A ///3> ThingI and ThingQ contain #e#ber ob0ects so that there s so#e dee% co%ying going on. It s interesting to notice that while )eriali7able classes are easy to set u%, there s #uch #ore work going on to du%licate the#. +loning involves a lot o" work to set u% the class, but the actual du%lication o" ob0ects is relatively si#%le. The results really tell the tale. (ere is the out%ut "ro# three di""erent runs=

1=84

Thinking in Java

,,,'0ruceEckel'com

Du"lication via serialiUation3 CI' Jillisecon!s Du"lication via cloning3 ,' Jillisecon!s Du"lication via serialiUation3 *(' Jillisecon!s Du"lication via cloning3 +' Jillisecon!s Du"lication via serialiUation3 **' Jillisecon!s Du"lication via cloning3 ,' Jillisecon!s
7es%ite the signi"icant ti#e di""erence between seriali1ation and cloning, you ll also notice that the seriali1ation techniAue see#s to vary #ore in its duration, while cloning tends to be #ore stable. RFSURF STIJLT6PPEC7IZ6TILGU

Adding cloneabilit: further down a hierarch:


I" you create a new class, its base class de"aults to .b8ect, which de"aults to noncloneability *as you ll see in the ne&t section,. 6s long as you don t e&%licitly add cloneability, you won t get it. But you can add it in at any layer and it will then be cloneable "ro# that layer downward, like this=

//3 a""en!i6a3MorrorLlick.Hava // ;ou can insert Cloneability // at any level of inheritance. i#"ort Hava.util.B< class Person @A class Mero e6ten!s Person @A class %cientist e6ten!s Person i#"le#ents Cloneable @ "ublic GbHect clone-. @ try @ return su"er.clone-.< A catch-Clone&ot%u""orte!E6ce"tion e. @ // this shoul! never ha""en3 // $t2s Cloneable alrea!y4 thro: ne: $nternalError-.< A A

1=85

A class Ja!%cientist e6ten!s %cientist @A "ublic class MorrorLlick @ "ublic static voi! #ain-%tringNO args. @ Person " ? ne: Person-.< Mero h ? ne: Mero-.< %cientist s ? ne: %cientist-.< Ja!%cientist # ? ne: Ja!%cientist-.< // " ? -Person.".clone-.< // Co#"ile error // h ? -Mero.h.clone-.< // Co#"ile error s ? -%cientist.s.clone-.< # ? -Ja!%cientist.#.clone-.< A A ///3>
Be"ore cloneability was added, the co#%iler sto%%ed you "ro# trying to clone things. :hen cloneability is added in )cientist, then )cientist and all its descendants are cloneable. RFSURFSTIJLT6PPEC7IZ6TILIU

Wh: this strange designA


I" all this see#s to be a strange sche#e, that s because it is. /ou #ight wonder why it worked out this way. :hat is the #eaning behind this designO RFSURFSTIJLT6PPEC7IZ6TIL2U )riginally, Java was designed as a language to control hardware bo&es, and de"initely not with the Internet in #ind. In a general'%ur%ose language like this, it #akes sense that the %rogra##er be able to clone any ob0ect. Thus, cloneA B was %laced in the root class .b8ect, but it was a p*blic #ethod so you could always clone any ob0ect. This see#ed to be the #ost "le&ible a%%roach, and a"ter all, what could it hurtO RFSURF STIJLT6PPEC7IZ6TI?@U :ell, when Java was seen as the ulti#ate Internet %rogra##ing language, things changed. Suddenly, there are security issues, and o" course, these issues are dealt with using ob0ects, and you don t necessarily want anyone to be able to clone your security ob0ects. So what you re seeing is a lot o" %atches a%%lied on the original si#%le and

1=87

Thinking in Java

,,,'0ruceEckel'com

straight"orward sche#e= cloneA B is now protecte' in .b8ect. /ou #ust override it and implement -loneable and deal with the e&ce%tions. RFSURFSTIJLT6PPEC7IZ6TI?MU It s worth noting that you #ust use the -loneable inter"ace onl) i" you re going to call .b8ect s cloneA B, #ethod, since that #ethod checks at run' ti#e to #ake sure that your class i#%le#ents -loneable. But "or consistency *and since -loneable is e#%ty anyway, you should i#%le#ent it. RFSURFSTIJLT6PPEC7IZ6TI?KU

Controlling cloneabilit:
/ou #ight suggest that, to re#ove cloneability, the cloneA B #ethod si#%ly be #ade private, but this won t work since you cannot take a base'class #ethod and #ake it less accessible in a derived class. So it s not that si#%le. 6nd yet, it s necessary to be able to control whether an ob0ect can be cloned. There are actually a nu#ber o" attitudes you can take to this in a class that you design=

(64) Indi""erence. /ou don t do anything about cloning, which #eans


that your class can t be cloned but a class that inherits "ro# you can add cloning i" it wants. This works only i" the de"ault .b8ect! cloneA B will do so#ething reasonable with all the "ields in your class. RFSURFSTIJLT6PPEC7IZ6TI?LU

(65) Su%%ort cloneA B. Eollow the standard %ractice o" i#%le#enting -loneable and overriding cloneA B. In the overridden cloneA B, you call s*per!cloneA B and catch all e&ce%tions *so your overridden cloneA B doesn t throw any e&ce%tions,. RFSURF
STIJLT6PPEC7IZ6TI??U

(66) Su%%ort cloning conditionally. I" your class holds re"erences to


other ob0ects that #ight or #ight not be cloneable *a container class, "or e&a#%le,, your cloneA B can try to clone all o" the ob0ects "or which you have re"erences, and i" they throw e&ce%tions 0ust %ass those e&ce%tions out to the %rogra##er. Eor e&a#%le, consider a s%ecial sort o" Array+ist that tries to clone all the ob0ects it holds. :hen you write such an Array+ist, you don t know what sort o" ob0ects the client %rogra##er #ight %ut into

1=88

your Array+ist, so you don t know whether they can be cloned. RF SURFSTIJLT6PPEC7IZ6TI?HU

!77) 7on t i#%le#ent -loneable but override cloneA B as protecte',


%roducing the correct co%ying behavior "or any "ields. This way, anyone inheriting "ro# this class can override cloneA B and call s*per!cloneA B to %roduce the correct co%ying behavior. Cote that your i#%le#entation can and should invoke s*per!cloneA B even though that #ethod e&%ects a -loneable ob0ect *it will throw an e&ce%tion otherwise,, because no one will directly invoke it on an ob0ect o" your ty%e. It will get invoked only through a derived class, which, i" it is to work success"ully, i#%le#ents -loneable. RF SURFSTIJLT6PPEC7IZ6TI?3U

!7() Try to %revent cloning by not i#%le#enting -loneable and overriding cloneA B to throw an e&ce%tion. This is success"ul only i" any class derived "ro# this calls s*per!cloneA B in its rede"inition o" cloneA B. )therwise, a %rogra##er #ay be able to
get around it. RFSURFSTIJLT6PPEC7IZ6TI?GU

!7!) Prevent cloning by #aking your class final. I" cloneA B has not
been overridden by any o" your ancestor classes, then it can t be. I" it has, then override it again and throw -lone/ot)*pporte'&4ception. Making the class final is the only way to guarantee that cloning is %revented. In addition, when dealing with security ob0ects or other situations in which you want to control the nu#ber o" ob0ects created you should #ake all constructors private and %rovide one or #ore s%ecial #ethods "or creating ob0ects. That way, these #ethods can restrict the nu#ber o" ob0ects created and the conditions in which they re created. *6 %articular case o" this is the singleton %attern shown in Thinking in Patterns ,ith Java, downloadable at ,,,'0ruceEckel'com., RF SURFSTIJLT6PPEC7IZ6TI?IU (ere s an e&a#%le that shows the various ways cloning can be i#%le#ented and then, later in the hierarchy, !turned o""$= RFSURF STIJLT6PPEC7IZ6TI?2U

//3 a""en!i6a3CheckCloneable.Hava // Checking to see if a reference can be clone!.

1=8:

Thinking in Java

,,,'0ruceEckel'com

// Can2t clone this because it !oesn2t // overri!e clone-.3 class Gr!inary @A // Gverri!es clone, but !oesn2t i#"le#ent // Cloneable3 class \rongClone e6ten!s Gr!inary @ "ublic GbHect clone-. thro:s Clone&ot%u""orte!E6ce"tion @ return su"er.clone-.< // Thro:s e6ce"tion A A // Does all the right things for cloning3 class $sCloneable e6ten!s Gr!inary i#"le#ents Cloneable @ "ublic GbHect clone-. thro:s Clone&ot%u""orte!E6ce"tion @ return su"er.clone-.< A A // Turn off cloning by thro:ing the e6ce"tion3 class &oJore e6ten!s $sCloneable @ "ublic GbHect clone-. thro:s Clone&ot%u""orte!E6ce"tion @ thro: ne: Clone&ot%u""orte!E6ce"tion-.< A A class TryJore e6ten!s &oJore @ "ublic GbHect clone-. thro:s Clone&ot%u""orte!E6ce"tion @ // Calls &oJore.clone-., thro:s e6ce"tion3 return su"er.clone-.< A A class BackGn e6ten!s &oJore @ "rivate BackGn !u"licate-BackGn b. @

1=8;

// %o#eho: #ake a co"y of b // an! return that co"y. This is a !u##y // co"y, Hust to #ake the "oint3 return ne: BackGn-.< A "ublic GbHect clone-. @ // Doesn2t call &oJore.clone-.3 return !u"licate-this.< A A // Can2t inherit fro# this, so can2t overri!e // the clone #etho! like in BackGn3 final class 5eally&oJore e6ten!s &oJore @A "ublic class CheckCloneable @ static Gr!inary tryToClone-Gr!inary or!. @ %tring i! ? or!.getClass-..get&a#e-.< %yste#.out."rintln-80tte#"ting 8 K i!.< Gr!inary 6 ? null< if-or! instanceof Cloneable. @ try @ %yste#.out."rintln-80tte#"ting 8 K i!.< 6 ? -Gr!inary.--$sCloneable.or!..clone-.< %yste#.out."rintln-8Clone! 8 K i!.< A catch-Clone&ot%u""orte!E6ce"tion e. @ %yste#.err."rintln-8Coul! not clone 8Ki!.< A A else @ %yste#.out."rintln8&ot instance of Cloneable8.< A return 6< A "ublic static voi! #ain-%tringNO args. @ // Y"casting3 Gr!inaryNO or! ? @ ne: $sCloneable-., ne: \rongClone-., ne: &oJore-., ne: TryJore-.,

1=:=

Thinking in Java

,,,'0ruceEckel'com

ne: BackGn-., ne: 5eally&oJore-., A< Gr!inary 6 ? ne: Gr!inary-.< // This :on2t co#"ile, since clone-. is // "rotecte! in GbHect3 //4 6 ? -Gr!inary.6.clone-.< // tryToClone-. checks first to see if // a class i#"le#ents Cloneable3 for-int i ? '< i P or!.length< iKK. tryToClone-or!NiO.< A A ///3>
The "irst class, .r'inary, re%resents the kinds o" classes we ve seen throughout this book= no su%%ort "or cloning, but as it turns out, no %revention o" cloning either. But i" you have a re"erence to an .r'inary ob0ect that #ight have been u%cast "ro# a #ore derived class, you can t tell i" it can be cloned or not. RFSURFSTIJLT6PPEC7IZ6TIH@U The class 0rong-lone shows an incorrect way to i#%le#ent cloning. It does override .b8ect!cloneA B and #akes that #ethod p*blic, but it doesn t i#%le#ent -loneable, so when s*per!cloneA B is called *which results in a call to .b8ect!cloneA B,, -lone/ot)*pporte'&4ception is thrown so the cloning doesn t work. RFSURFSTIJLT6PPEC7IZ6TIHMU In Is-loneable you can see all the right actions %er"or#ed "or cloning= cloneA B is overridden and -loneable is i#%le#ented. (owever, this cloneA B #ethod and several others that "ollow in this e&a#%le do not catch -lone/ot)*pporte'&4ception, but instead %ass it through to the caller, who #ust then %ut a try'catch block around it. In your own cloneA B #ethods you will ty%ically catch -lone/ot)*pporte'&4ception inside cloneA B rather than %assing it through. 6s you ll see, in this e&a#%le it s #ore in"or#ative to %ass the e&ce%tions through. RFSURFSTIJLT6PPEC7IZ6TIHKU +lass /o1ore atte#%ts to !turn o""$ cloning in the way that the Java designers intended= in the derived class cloneA B, you throw -lone/ot)*pporte'&4ception. The cloneA B #ethod in class Try1ore %ro%erly calls s*per!cloneA B, and this resolves to /o1ore!

1=:1

cloneA B, which throws an e&ce%tion and %revents cloning. RFSURF


STIJLT6PPEC7IZ6TIHLU But what i" the %rogra##er doesn t "ollow the !%ro%er$ %ath o" calling

s*per!cloneA B inside the overridden cloneA B #ethodO In 2ack.n,


you can see how this can ha%%en. This class uses a se%arate #ethod '*plicateA B to #ake a co%y o" the current ob0ect and calls this #ethod inside cloneA B instead o" calling s*per!cloneA B. The e&ce%tion is never thrown and the new class is cloneable. /ou can t rely on throwing an e&ce%tion to %revent #aking a cloneable class. The only sure'"ire solution is shown in $eally/o1ore, which is final and thus cannot be inherited. That #eans i" cloneA B throws an e&ce%tion in the final class, it cannot be #odi"ied with inheritance and the %revention o" cloning is assured. */ou cannot e&%licitly call .b8ect!cloneA B "ro# a class that has an arbitrary level o" inheritance; you are li#ited to calling s*per!clone A B, which has access to only the direct base class., Thus, i" you #ake any ob0ects that involve security issues, you ll want to #ake those classes final. RFSURFSTIJLT6PPEC7IZ6TIH?U The "irst #ethod you see in class -heck-loneable is tryTo-loneA B, which takes any .r'inary ob0ect and checks to see whether it s cloneable with instanceof. I" so, it casts the ob0ect to an Is-loneable, calls clone A B and casts the result back to .r'inary, catching any e&ce%tions that are thrown. Cotice the use o" run'ti#e ty%e identi"ication *see +ha%ter MK, to %rint the class na#e so you can see what s ha%%ening. RFSURF STIJLT6PPEC7IZ6TIHHU In mainA B, di""erent ty%es o" .r'inary ob0ects are created and u%cast to .r'inary in the array de"inition. The "irst two lines o" code a"ter that create a %lain .r'inary ob0ect and try to clone it. (owever, this code will not co#%ile because cloneA B is a protecte' #ethod in .b8ect. The re#ainder o" the code ste%s through the array and tries to clone each ob0ect, re%orting the success or "ailure o" each. The out%ut is= RFSURF STIJLT6PPEC7IZ6TIH3U

0tte#"ting $sCloneable Clone! $sCloneable 0tte#"ting &oJore Coul! not clone &oJore 0tte#"ting TryJore

1=:2

Thinking in Java

,,,'0ruceEckel'com

Coul! not clone TryJore 0tte#"ting BackGn Clone! BackGn 0tte#"ting 5eally&oJore Coul! not clone 5eally&oJore
So to su##ari1e, i" you want a class to be cloneable= RFSURF STIJLT6PPEC7IZ6TIHGU

!7*) I#%le#ent the -loneable inter"ace. !7+) )verride cloneA B. !7,) +all s*per!cloneA B inside your cloneA B. !7-) +a%ture e&ce%tions inside your cloneA B.
This will %roduce the #ost convenient e""ects. RFSURF STIJLT6PPEC7IZ6TIHIU

#he co.: constructor


+loning can see# to be a co#%licated %rocess to set u%. It #ight see# like there should be an alternative. )ne a%%roach that #ight occur to you *es%ecially i" you re a +<< %rogra##er, is to #ake a s%ecial constructor whose 0ob it is to du%licate an ob0ect. In +<<, this is called the co ) constructor. 6t "irst, this see#s like the obvious solution, but in "act it doesn t work. (ere s an e&a#%le=

//3 a""en!i6a3Co"yConstructor.Hava // 0 constructor for co"ying an obHect of the sa#e // ty"e, as an atte#"t to create a local co"y. class Lruit/ualities @ "rivate int :eight< "rivate int color< "rivate int fir#ness< "rivate int ri"eness< "rivate int s#ell< // etc. Lruit/ualities-. @ // Default constructor // !o so#ething #eaningful...

1=:3

A // Gther constructors3 // ... // Co"y constructor3 Lruit/ualities-Lruit/ualities f. @ :eight ? f.:eight< color ? f.color< fir#ness ? f.fir#ness< ri"eness ? f.ri"eness< s#ell ? f.s#ell< // etc. A A class %ee! @ // Je#bers... %ee!-. @ /B Default constructor B/ A %ee!-%ee! s. @ /B Co"y constructor B/ A A class Lruit @ "rivate Lruit/ualities f=< "rivate int see!s< "rivate %ee!NO s< Lruit-Lruit/ualities =, int see!Count. @ f= ? =< see!s ? see!Count< s ? ne: %ee!Nsee!sO< for-int i ? '< i P see!s< iKK. sNiO ? ne: %ee!-.< A // Gther constructors3 // ... // Co"y constructor3 Lruit-Lruit f. @ f= ? ne: Lruit/ualities-f.f=.< see!s ? f.see!s< // Call all %ee! co"y-constructors3 for-int i ? '< i P see!s< iKK. sNiO ? ne: %ee!-f.sNiO.< // Gther co"y-construction activities...

1=:4

Thinking in Java

,,,'0ruceEckel'com

A // To allo: !erive! constructors -or other // #etho!s. to "ut in !ifferent =ualities3 "rotecte! voi! a!!/ualities-Lruit/ualities =. @ f= ? =< A "rotecte! Lruit/ualities get/ualities-. @ return f=< A A class To#ato e6ten!s Lruit @ To#ato-. @ su"er-ne: Lruit/ualities-., (''.< A To#ato-To#ato t. @ // Co"y-constructor su"er-t.< // Y"cast for base co"y-constructor // Gther co"y-construction activities... A A class Tebra/ualities e6ten!s Lruit/ualities @ "rivate int stri"e!ness< Tebra/ualities-. @ // Default constructor // !o so#ething #eaningful... A Tebra/ualities-Tebra/ualities U. @ su"er-U.< stri"e!ness ? U.stri"e!ness< A A class areenTebra e6ten!s To#ato @ areenTebra-. @ a!!/ualities-ne: Tebra/ualities-..< A areenTebra-areenTebra g. @ su"er-g.< // Calls To#ato-To#ato. // 5estore the right =ualities3 a!!/ualities-ne: Tebra/ualities-..< A

1=:5

voi! evaluate-. @ Tebra/ualities U= ? -Tebra/ualities.get/ualities-.< // Do so#ething :ith the =ualities // ... A A "ublic class Co"yConstructor @ "ublic static voi! ri"en-To#ato t. @ // Yse the 8co"y constructor83 t ? ne: To#ato-t.< %yste#.out."rintln-8$n ri"en, t is a 8 K t.getClass-..get&a#e-..< A "ublic static voi! slice-Lruit f. @ f ? ne: Lruit-f.< // M###... :ill this :ork[ %yste#.out."rintln-8$n slice, f is a 8 K f.getClass-..get&a#e-..< A "ublic static voi! #ain-%tringNO args. @ To#ato to#ato ? ne: To#ato-.< ri"en-to#ato.< // G` slice-to#ato.< // GGP%4 areenTebra g ? ne: areenTebra-.< ri"en-g.< // GGP%4 slice-g.< // GGP%4 g.evaluate-.< A A ///3>
This see#s a bit strange at "irst. Sure, "ruit has Aualities, but why not 0ust %ut data #e#bers re%resenting those Aualities directly into the Fr*it classO There are two %otential reasons. The "irst is that you #ight want to easily insert or change the Aualities. Cote that Fr*it has a protecte' a''3*alitiesA B #ethod to allow derived classes to do this. */ou #ight think the logical thing to do is to have a protecte' constructor in Fr*it that takes a Fr*it3*alities argu#ent, but constructors don t inherit so it wouldn t be available in second or greater level classes., By #aking the "ruit Aualities into a se%arate class, you have greater "le&ibility, including

1=:7

Thinking in Java

,,,'0ruceEckel'com

the ability to change the Aualities #idway through the li"eti#e o" a %articular Fr*it ob0ect. RFSURFSTIJLT6PPEC7IZ6TIH2U The second reason "or #aking Fr*it3*alities a se%arate ob0ect is in case you want to add new Aualities or to change the behavior via inheritance and %oly#or%his#. Cote that "or "reenZebra *which reall) is a ty%e o" to#ato9I ve grown the# and they re "abulous,, the constructor calls a''3*alitiesA B and %asses it a Zebra3*alities ob0ect, which is derived "ro# Fr*it3*alities so it can be attached to the Fr*it3*alities re"erence in the base class. )" course, when "reenZebra uses the Fr*it3*alities it #ust downcast it to the correct ty%e *as seen in eval*ateA B,, but it always knows that ty%e is Zebra3*alities. RFSURFSTIJLT6PPEC7IZ6TI3@U /ou ll also see that there s a )ee' class, and that Fr*it *which by de"inition carries its own seeds, @ contains an array o" )ee's. RFSURF STIJLT6PPEC7IZ6TI3MU Einally, notice that each class has a co%y constructor, and that each co%y constructor #ust take care to call the co%y constructors "or the base class and #e#ber ob0ects to %roduce a dee% co%y. The co%y constructor is tested inside the class -opy-onstr*ctor. The #ethod ripenA B takes a Tomato argu#ent and %er"or#s co%y'construction on it in order to du%licate the ob0ect=

t ? ne: To#ato-t.<
while sliceA B takes a #ore generic Fr*it ob0ect and also du%licates it=

f ? ne: Lruit-f.<
These are tested with di""erent kinds o" Fr*it in mainA B. (ere s the out%ut=

$n $n $n $n

ri"en, slice, ri"en, slice,

t f t f

is is is is

a a a a

To#ato Lruit To#ato Lruit

This is where the %roble# shows u%. 6"ter the co%y'construction that ha%%ens to the Tomato inside sliceA B, the result is no longer a Tomato
@ E&ce%t "or the %oor avocado, which has been reclassi"ied to si#%ly !"at.$

1=:8

ob0ect, but 0ust a Fr*it. It has lost all o" its to#ato'ness. Eurther, when you take a "reenZebra, both ripenA B and sliceA B turn it into a Tomato and a Fr*it, res%ectively. Thus, un"ortunately, the co%y constructor sche#e is no good to us in Java when atte#%ting to #ake a local co%y o" an ob0ect. RFSURFSTIJLT6PPEC7IZ6TI3KU

Wh: does it work in CFF and not "avaA


The co%y constructor is a "unda#ental %art o" +<<, since it auto#atically #akes a local co%y o" an ob0ect. /et the e&a#%le above %roves that it does not work "or Java. :hyO In Java everything that we #ani%ulate is a re"erence, while in +<< you can have re"erence'like entities and you can also %ass around the ob0ects directly. That s what the +<< co%y constructor is "or= when you want to take an ob0ect and %ass it in by value, thus du%licating the ob0ect. So it works "ine in +<<, but you should kee% in #ind that this sche#e "ails in Java, so don t use it. RFSURF STIJLT6PPEC7IZ6TI3LU

$ead@onl: classes
:hile the local co%y %roduced by cloneA B gives the desired results in the a%%ro%riate cases, it is an e&a#%le o" "orcing the %rogra##er *the author o" the #ethod, to be res%onsible "or %reventing the ill e""ects o" aliasing. :hat i" you re #aking a library that s so general %ur%ose and co##only used that you cannot #ake the assu#%tion that it will always be cloned in the %ro%er %lacesO )r #ore likely, what i" you ,ant to allow aliasing "or e""iciency9to %revent the needless du%lication o" ob0ects9but you don t want the negative side e""ects o" aliasingO RFSURF STIJLT6PPEC7IZ6TI3?U )ne solution is to create immutable ob>ects which belong to read'only classes. /ou can de"ine a class such that no #ethods in the class cause changes to the internal state o" the ob0ect. In such a class, aliasing has no i#%act since you can read only the internal state, so i" #any %ieces o" code are reading the sa#e ob0ect there s no %roble#. RFSURF STIJLT6PPEC7IZ6TI3HU 6s a si#%le e&a#%le o" i##utable ob0ects, Java s standard library contains !wra%%er$ classes "or all the %ri#itive ty%es. /ou #ight have

1=::

Thinking in Java

,,,'0ruceEckel'com

already discovered that, i" you want to store an int inside a container such as an Array+ist *which takes only .b8ect references,, you can wra% your int inside the standard library Integer class=

//3 a""en!i6a3$##utable$nteger.Hava // The $nteger class cannot be change!. i#"ort Hava.util.B< "ublic class $##utable$nteger @ "ublic static voi! #ain-%tringNO args. @ 0rrayList v ? ne: 0rrayList-.< for-int i ? '< i P ('< iKK. v.a!!-ne: $nteger-i..< // But ho: !o you change the int // insi!e the $nteger[ A A ///3>
The Integer class *as well as all the %ri#itive !wra%%er$ classes, i#%le#ents i##utability in a si#%le "ashion= they have no #ethods that allow you to change the ob0ect. RFSURFSTIJLT6PPEC7IZ6TI33U I" you do need an ob0ect that holds a %ri#itive ty%e that can be #odi"ied, you #ust create it yoursel". Eortunately, this is trivial=

//3 a""en!i6a3Jutable$nteger.Hava // 0 changeable :ra""er class. i#"ort Hava.util.B< class $ntWalue @ int n< $ntWalue-int 6. @ n ? 6< A "ublic %tring to%tring-. @ return $nteger.to%tring-n.< A A "ublic class Jutable$nteger @ "ublic static voi! #ain-%tringNO args. @ 0rrayList v ? ne: 0rrayList-.< for-int i ? '< i P ('< iKK. v.a!!-ne: $ntWalue-i..<

1=:;

%yste#.out."rintln-v.< for-int i ? '< i P v.siUe-.< iKK. --$ntWalue.v.get-i...nKK< %yste#.out."rintln-v.< A A ///3>


Cote that n is "riendly to si#%li"y coding. RFSURF STIJLT6PPEC7IZ6TI3GU

IntVal*e can be even si#%ler i" the de"ault initiali1ation to 1ero is


adeAuate *then you don t need the constructor, and you don t care about %rinting it out *then you don t need the to)tringA B,=

class $ntWalue @ int n< A


Eetching the ele#ent out and casting it is a bit awkward, but that s a "eature o" Array+ist, not o" IntVal*e. RFSURF STIJLT6PPEC7IZ6TI3IU

Creating read@onl: classes


It s %ossible to create your own read'only class. (ere s an e&a#%le=

//3 a""en!i6a3$##utable(.Hava // GbHects that cannot be #o!ifie! // are i##une to aliasing. "ublic class $##utable( @ "rivate int !ata< "ublic $##utable(-int initWal. @ !ata ? initWal< A "ublic int rea!-. @ return !ata< A "ublic boolean nonUero-. @ return !ata 4? '< A "ublic $##utable( =ua!ru"le-. @ return ne: $##utable(-!ata B I.< A static voi! f-$##utable( i(. @ $##utable( =ua! ? i(.=ua!ru"le-.< %yste#.out."rintln-8i( ? 8 K i(.rea!-..< %yste#.out."rintln-8=ua! ? 8 K =ua!.rea!-..<

1=;=

Thinking in Java

,,,'0ruceEckel'com

A "ublic static voi! #ain-%tringNO args. @ $##utable( 6 ? ne: $##utable(-I*.< %yste#.out."rintln-86 ? 8 K 6.rea!-..< f-6.< %yste#.out."rintln-86 ? 8 K 6.rea!-..< A A ///3>
6ll data is private, and you ll see that none o" the p*blic #ethods #odi"y that data. Indeed, the #ethod that does a%%ear to #odi"y an ob0ect is C*a'r*pleA B, but this creates a new Imm*table> ob0ect and leaves the original one untouched. RFSURFSTIJLT6PPEC7IZ6TI32U The #ethod fA B takes an Imm*table> ob0ect and %er"or#s various o%erations on it, and the out%ut o" mainA B de#onstrates that there is no change to 4. Thus, 4 s ob0ect could be aliased #any ti#es without har# because the Imm*table> class is designed to guarantee that ob0ects cannot be changed. RFSURFSTIJLT6PPEC7IZ6TIG@U

#he drawback to immutabilit:


+reating an i##utable class see#s at "irst to %rovide an elegant solution. (owever, whenever you do need a #odi"ied ob0ect o" that new ty%e you #ust su""er the overhead o" a new ob0ect creation, as well as %otentially causing #ore "reAuent garbage collections. Eor so#e classes this is not a %roble#, but "or others *such as the )tring class, it is %rohibitively e&%ensive. RFSURFSTIJLT6PPEC7IZ6TIGMU The solution is to create a co#%anion class that can be #odi"ied. Then, when you re doing a lot o" #odi"ications, you can switch to using the #odi"iable co#%anion class and switch back to the i##utable class when you re done. RFSURFSTIJLT6PPEC7IZ6TIGKU The e&a#%le above can be #odi"ied to show this=

//3 a""en!i6a3$##utable .Hava // 0 co#"anion class for #aking // changes to i##utable obHects. class Jutable @

1=;1

"rivate int !ata< "ublic Jutable-int initWal. @ !ata ? initWal< A "ublic Jutable a!!-int 6. @ !ata K? 6< return this< A "ublic Jutable #ulti"ly-int 6. @ !ata B? 6< return this< A "ublic $##utable #ake$##utable -. @ return ne: $##utable -!ata.< A A "ublic class $##utable @ "rivate int !ata< "ublic $##utable -int initWal. @ !ata ? initWal< A "ublic int rea!-. @ return !ata< A "ublic boolean nonUero-. @ return !ata 4? '< A "ublic $##utable a!!-int 6. @ return ne: $##utable -!ata K 6.< A "ublic $##utable #ulti"ly-int 6. @ return ne: $##utable -!ata B 6.< A "ublic Jutable #akeJutable-. @ return ne: Jutable-!ata.< A "ublic static $##utable #o!ify(-$##utable y.@ $##utable val ? y.a!!-( .< val ? val.#ulti"ly-).< val ? val.a!!-((.< val ? val.#ulti"ly- .< return val< A // This "ro!uces the sa#e result3

1=;2

Thinking in Java

,,,'0ruceEckel'com

"ublic static $##utable #o!ify -$##utable y.@ Jutable # ? y.#akeJutable-.< #.a!!-( ..#ulti"ly-)..a!!-((..#ulti"ly- .< return #.#ake$##utable -.< A "ublic static voi! #ain-%tringNO args. @ $##utable i ? ne: $##utable -I*.< $##utable r( ? #o!ify(-i .< $##utable r ? #o!ify -i .< %yste#.out."rintln-8i ? 8 K i .rea!-..< %yste#.out."rintln-8r( ? 8 K r(.rea!-..< %yste#.out."rintln-8r ? 8 K r .rea!-..< A A ///3> Imm*tableI contains #ethods that, as be"ore, %reserve the i##utability o" the ob0ects by %roducing new ob0ects whenever a #odi"ication is desired. These are the a''A B and m*ltiplyA B #ethods. The co#%anion class is called 1*table, and it also has a''A B and m*ltiplyA B #ethods, but these #odi"y the 1*table ob0ect rather than #aking a new one. In addition, 1*table has a #ethod to use its data to %roduce an Imm*tableI ob0ect and vice versa. RFSURF STIJLT6PPEC7IZ6TIGLU
The two static #ethods mo'ify>A B and mo'ifyIA B show two di""erent a%%roaches to %roducing the sa#e result. In mo'ify>A B, everything is done within the Imm*tableI class and you can see that "our new Imm*tableI ob0ects are created in the %rocess. *6nd each ti#e val is reassigned, the %revious ob0ect beco#es garbage., RFSURF STIJLT6PPEC7IZ6TIG?U In the #ethod mo'ifyIA B, you can see that the "irst action is to take the Imm*tableI y and %roduce a 1*table "ro# it. *This is 0ust like calling cloneA B as you saw earlier, but this ti#e a di""erent ty%e o" ob0ect is created., Then the 1*table ob0ect is used to %er"or# a lot o" change o%erations ,ithout reAuiring the creation o" #any new ob0ects. Einally, it s turned back into an Imm*tableI. (ere, two new ob0ects are created *the 1*table and the result Imm*tableI, instead o" "our. RFSURF STIJLT6PPEC7IZ6TIGHU This a%%roach #akes sense, then, when=

1=;3

!74) /ou need i##utable ob0ects and !75) /ou o"ten need to #ake a lot o" #odi"ications or !76) It s e&%ensive to create new i##utable ob0ects.

Immutable Strings
+onsider the "ollowing code= RFSURFSTIJLT6PPEC7IZ6TIG3U

//3 a""en!i6a3%tringer.Hava "ublic class %tringer @ static %tring u"case-%tring s. @ return s.toY""erCase-.< A "ublic static voi! #ain-%tringNO args. @ %tring = ? ne: %tring-8ho:!y8.< %yste#.out."rintln-=.< // ho:!y %tring == ? u"case-=.< %yste#.out."rintln-==.< // MG\D; %yste#.out."rintln-=.< // ho:!y A A ///3>
:hen C is %assed in to *pcaseA B it s actually a co%y o" the re"erence to C. The ob0ect this re"erence is connected to stays %ut in a single %hysical location. The re"erences are co%ied as they are %assed around. RFSURF STIJLT6PPEC7IZ6TIGGU Dooking at the de"inition "or *pcaseA B, you can see that the re"erence that s %assed in has the na#e s, and it e&ists "or only as long as the body o" *pcaseA B is being e&ecuted. :hen *pcaseA B co#%letes, the local re"erence s vanishes. *pcaseA B returns the result, which is the original string with all the characters set to u%%ercase. )" course, it actually returns a re"erence to the result. But it turns out that the re"erence that it returns is "or a new ob0ect, and the original C is le"t alone. (ow does this ha%%enO RFSURFSTIJLT6PPEC7IZ6TIGIU

1=;4

Thinking in Java

,,,'0ruceEckel'com

Im.licit constants
I" you say=

%tring s ? 8as!f8< %tring 6 ? %tringer.u"case-s.<


do you really want the *pcaseA B #ethod to change the argu#entO In general, you don t, because an argu#ent usually looks to the reader o" the code as a %iece o" in"or#ation %rovided to the #ethod, not so#ething to be #odi"ied. This is an i#%ortant guarantee, since it #akes code easier to write and understand. RFSURFSTIJLT6PPEC7IZ6TIG2U In +<<, the availability o" this guarantee was i#%ortant enough to %ut in a s%ecial keyword, const, to allow the %rogra##er to ensure that a re"erence *%ointer or re"erence in +<<, could not be used to #odi"y the original ob0ect. But then the +<< %rogra##er was reAuired to be diligent and re#e#ber to use const everywhere. It can be con"using and easy to "orget. RFSURFSTIJLT6PPEC7IZ6TII@U

Overloading SF and the StringBu!!er


)b0ects o" the )tring class are designed to be i##utable, using the co#%anion'class techniAue shown %reviously. I" you e&a#ine the online docu#entation "or the )tring class *which is su##ari1ed a little later in this a%%endi&,, you ll see that every #ethod in the class that a%%ears to #odi"y a )tring really creates and returns a brand new )tring ob0ect containing the #odi"ication. The original )tring is le"t untouched. Thus, there s no "eature in Java like +<< s const to #ake the co#%iler su%%ort the i##utability o" your ob0ects. I" you want it, you have to wire it in yoursel", like )tring does. RFSURFSTIJLT6PPEC7IZ6TIIMU Since )tring ob0ects are i##utable, you can alias to a %articular )tring as #any ti#es as you want. Because it s read'only there s no %ossibility that one re"erence will change so#ething that will a""ect the other re"erences. So a read'only ob0ect solves the aliasing %roble# nicely. RF SURFSTIJLT6PPEC7IZ6TIIKU It also see#s %ossible to handle all the cases in which you need a #odi"ied ob0ect by creating a brand new version o" the ob0ect with the #odi"ications, as )tring does. (owever, "or so#e o%erations this isn t

1=;5

e""icient. 6 case in %oint is the o%erator GL that has been overloaded "or )tring ob0ects. )verloading #eans that it has been given an e&tra #eaning when used with a %articular class. *The [ L and [LP "or )tring are the only o%erators that are overloaded in Java, and Java does not allow the %rogra##er to overload any others, @. RFSURF STIJLT6PPEC7IZ6TIILU :hen used with )tring ob0ects, the [L allows you to concatenate )trings together=

%tring s ? 8abc8 K foo K 8!ef8 K $nteger.to%tring -I*.<


/ou could i#agine how this might work= the )tring !abc$ could have a #ethod appen'A B that creates a new )tring ob0ect containing !abc$ concatenated with the contents o" foo. The new )tring ob0ect would then create another new )tring that added !de",$ and so on. RFSURF STIJLT6PPEC7IZ6TII?U This would certainly work, but it reAuires the creation o" a lot o" )tring ob0ects 0ust to %ut together this new )tring, and then you have a bunch o" the inter#ediate )tring ob0ects that need to be garbage'collected. I sus%ect that the Java designers tried this a%%roach "irst *which is a lesson in so"tware design9you don t really know anything about a syste# until you try it out in code and get so#ething working,. I also sus%ect they discovered that it delivered unacce%table %er"or#ance. RFSURF STIJLT6PPEC7IZ6TIIHU The solution is a #utable co#%anion class si#ilar to the one shown %reviously. Eor )tring, this co#%anion class is called )tring2*ffer, and the co#%iler auto#atically creates a )tring2*ffer to evaluate certain e&%ressions, in %articular when the overloaded o%erators L and LP are used with )tring ob0ects. This e&a#%le shows what ha%%ens=

//3 a""en!i6a3$##utable%trings.Hava
@ +<< allows the %rogra##er to overload o%erators at will. Because this can o"ten be a

co#%licated %rocess *see +ha%ter M@ o" Thinking in C++D 2nd editionD Prentice'(all, K@@@,, the Java designers dee#ed it a !bad$ "eature that shouldn t be included in Java. It wasn t so bad that they didn t end u% doing it the#selves, and ironically enough, o%erator overloading would be #uch easier to use in Java than in +<<. This can be seen in Python *see www.Python.org, which has garbage collection and straight"orward o%erator overloading.

1=;7

Thinking in Java

,,,'0ruceEckel'com

// De#onstrating %tringBuffer. "ublic class $##utable%trings @ "ublic static voi! #ain-%tringNO args. @ %tring foo ? 8foo8< %tring s ? 8abc8 K foo K 8!ef8 K $nteger.to%tring-I*.< %yste#.out."rintln-s.< // The 8e=uivalent8 using %tringBuffer3 %tringBuffer sb ? ne: %tringBuffer-8abc8.< // Creates %tring4 sb.a""en!-foo.< sb.a""en!-8!ef8.< // Creates %tring4 sb.a""en!-$nteger.to%tring-I*..< %yste#.out."rintln-sb.< A A ///3>
In the creation o" )tring s, the co#%iler is doing the rough eAuivalent o" the subseAuent code that uses sb= a )tring2*ffer is created and appen'A B is used to add new characters directly into the )tring2*ffer ob0ect *rather than #aking new co%ies each ti#e,. :hile this is #ore e""icient, it s worth noting that each ti#e you create a Auoted character string such as aabcb and a'efb, the co#%iler turns those into )tring ob0ects. So there can be #ore ob0ects created than you e&%ect, des%ite the e""iciency a""orded through )tring2*ffer. RFSURF STIJLT6PPEC7IZ6TII3U

#he String and StringBu!!er classes


(ere is an overview o" the #ethods available "or both )tring and )tring2*ffer so you can get a "eel "or the way they interact. These tables don t contain every single #ethod, but rather the ones that are i#%ortant to this discussion. Methods that are overloaded are su##ari1ed in a single row. RFSURFSTIJLT6PPEC7IZ6TIIGU Eirst, the )tring class=

1=;8

1etho' -onstr*ctor

Arg*ments, .verloa'ing
)verloaded= 7e"ault, )tring, )tring2*ffer, char arrays, byte arrays.

Use
+reating )tring ob0ects.

lengthA B charAtAB get-harsA B, get2ytesA B int Inde&


The beginning and end "ro# which to co%y, the array to co%y into, an inde& into the destination array.

Cu#ber o" characters in the )tring. The char at a location in the )tring. +o%y chars or bytes into an e&ternal array.

to-harArrayA B

eC*alsA B, eC*als6 Ignore-aseA B compareToA B

6 )tring to co#%are with. 6 )tring to co#%are with.

region1atchesA B

)""set into this

)tring, the other )tring and its o""set


and length to co#%are. )verload adds !ignore case.$

Produces a char]^ containing the characters in the )tring. 6n eAuality check on the contents o" the two )trings. 5esult is negative, 1ero, or %ositive de%ending on the le&icogra%hical ordering o" the )tring and the argu#ent. 4%%ercase and lowercase are not eAual. boolean result indicates whether the region #atches.

1=;:

Thinking in Java

,,,'0ruceEckel'com

1etho' starts0ithA B

Arg*ments, .verloa'ing )tring that it #ight


start with. )verload adds o""set into argu#ent. )tring that #ight be a su""i& o" this )tring. )verloaded= char, char and starting inde&, )tring, )tring, and starting inde&.

Use boolean result indicates whether the )tring starts with the argu#ent. boolean result indicates whether the argu#ent is a su""i&. 5eturns 'M i" the argu#ent is not "ound within this )tring, otherwise returns the inde& where the argu#ent starts. lastIn'e4.fA B
searches backward "ro# end. 5eturns a new )tring ob0ect containing the s%eci"ied character set. 5eturns a new )tring ob0ect containing the original )tring s characters "ollowed by the characters in the argu#ent. 5eturns a new )tring ob0ect with the re%lace#ents #ade. 4ses the old )tring i" no #atch is "ound. 5eturns a new )tring ob0ect with the case o" all letters changed. 4ses the old )tring i" no changes need to be #ade.

en's0ithA B in'e4.fA B, lastIn'e4.fA B

s*bstringA B

concatA B

)verloaded= Starting inde&, starting inde&, and ending inde&. The )tring to concatenate

replaceA B

The old character to search "or, the new character to re%lace it with.

to+o(er-aseA B toUpper-aseA B

1=;;

1etho' trimA B

Arg*ments, .verloa'ing

Use
5eturns a new )tring ob0ect with the white s%ace re#oved "ro# each end. 4ses the old )tring i" no changes need to be #ade. 5eturns a )tring containing a character re%resentation o" the argu#ent.

val*e.fA B

)verloaded= .b8ect, char]^, char]^ and o""set and count, boolean, char, int, long, float, 'o*ble.

internA B

Produces one and only one )tring re" %er uniAue character seAuence.

/ou can see that every )tring #ethod care"ully returns a new )tring ob0ect when it s necessary to change the contents. 6lso notice that i" the contents don t need changing the #ethod will 0ust return a re"erence to the original )tring. This saves storage and overhead. (ere s the )tring2*ffer class=

1etho' -onstr*cto r to)tringA B lengthA B capacityA B

Arg*ments, overloa'ing
)verloaded= de"ault, length o" bu""er to create, )tring to create "ro#.

Use
+reate a new

)tring2*ffer
ob0ect. +reates a )tring "ro# this )tring2*ffer. Cu#ber o" characters in the )tring2*ffer. 5eturns current nu#ber o" s%aces allocated.

11==

Thinking in Java

,,,'0ruceEckel'com

1etho' ens*re6 -apacityA B set+engthA B

Arg*ments, overloa'ing
Integer indicating desired ca%acity.

Use
Makes the

)tring2*ffer hold
at least the desired nu#ber o" s%aces. Truncates or e&%ands the %revious character string. I" e&%anding, %ads with nulls. 5eturns the char at that location in the bu""er. Modi"ies the value at that location.

Integer indicating new length o" character string in bu""er.

charAtA B set-harAtA B

get-harsA B

appen'A B

Integer indicating the location o" the desired ele#ent. Integer indicating the location o" the desired ele#ent and the new char value "or the ele#ent. The beginning and end "ro# which to co%y, the array to co%y into, an inde& into the destination array. )verloaded= .b8ect, )tring, char]^, char]^ with o""set and length, boolean, char, int, long, float, 'o*ble.

insertA B

)verloaded, each with a "irst argu#ent o" the o""set at which to start inserting= .b8ect, )tring, char]^, boolean, char, int, long, float, 'o*ble.

+o%y chars into an e&ternal array. There is no get2ytesA B as in )tring. The argu#ent is converted to a string and a%%ended to the end o" the current bu""er, increasing the bu""er i" necessary. The second argu#ent is converted to a string and inserted into the current bu""er beginning at the o""set. The bu""er is increased i" necessary.

11=1

1etho' reverseA B

Arg*ments, overloa'ing

Use
The order o" the characters in the bu""er is reversed.

The #ost co##only used #ethod is appen'A B, which is used by the co#%iler when evaluating )tring e&%ressions that contain the [L and [LP o%erators. The insertA B #ethod has a si#ilar "or#, and both #ethods %er"or# signi"icant #ani%ulations to the bu""er instead o" creating new ob0ects.

Strings are s.ecial


By now you ve seen that the )tring class is not 0ust another class in Java. There are a lot o" s%ecial cases in )tring, not the least o" which is that it s a built'in class and "unda#ental to Java. Then there s the "act that a Auoted character string is converted to a )tring by the co#%iler and the s%ecial overloaded o%erators L and LP. In this a%%endi& you ve seen the re#aining s%ecial case= the care"ully built i##utability using the co#%anion )tring2*ffer and so#e e&tra #agic in the co#%iler. RFSURF STIJLT6PPEC7IZ6TIIIU

1ummar:
Because everything is a re"erence in Java, and because every ob0ect is created on the hea% and garbage'collected only when it is no longer used, the "lavor o" ob0ect #ani%ulation changes, es%ecially when %assing and returning ob0ects. Eor e&a#%le, in + or +<<, i" you wanted to initiali1e so#e %iece o" storage in a #ethod, you d %robably reAuest that the user %ass the address o" that %iece o" storage into the #ethod. )therwise you d have to worry about who was res%onsible "or destroying that storage. Thus, the inter"ace and understanding o" such #ethods is #ore co#%licated. But in Java, you never have to worry about res%onsibility or whether an ob0ect will still e&ist when it is needed, since that is always taken care o" "or you. /our can create an ob0ect at the %oint that it is needed, and no sooner, and never worry about the #echanics o" %assing around res%onsibility "or that ob0ect= you si#%ly %ass the re"erence.

11=2

Thinking in Java

,,,'0ruceEckel'com

So#eti#es the si#%li"ication that this %rovides is unnoticed, other ti#es it is staggering. RFSURFSTIJLT6PPEC7IZ6TII2U The downside to all this underlying #agic is two"old=

!(7) /ou always take the e""iciency hit "or the e&tra #e#ory
#anage#ent *although this can be Auite s#all,, and there s always a slight a#ount o" uncertainty about the ti#e so#ething can take to run *since the garbage collector can be "orced into action whenever you get low on #e#ory,. Eor #ost a%%lications, the bene"its outweigh the drawbacks, and %articularly ti#e'critical sections can be written using native #ethods *see 6%%endi& B,. RFSURFSTIJLT6PPEC7IZ6TI2@U

!(() 6liasing= so#eti#es you can accidentally end u% with two


re"erences to the sa#e ob0ect, which is a %roble# only i" both re"erences are assu#ed to %oint to a distinct ob0ect. This is where you need to %ay a little closer attention and, when necessary, clone A B an ob0ect to %revent the other re"erence "ro# being sur%rised by an une&%ected change. 6lternatively, you can su%%ort aliasing "or e""iciency by creating i##utable ob0ects whose o%erations can return a new ob0ect o" the sa#e ty%e or so#e di""erent ty%e, but never change the original ob0ect so that anyone aliased to that ob0ect sees no change. RFSURFSTIJLT6PPEC7IZ6TI2MU So#e %eo%le say that cloning in Java is a botched design, and to heck with it, so they i#%le#ent their own version o" cloning @ and never call the .b8ect!cloneA B #ethod, thus eli#inating the need to i#%le#ent -loneable and catch the -lone/ot)*pporte'&4ception. This is certainly a reasonable a%%roach and since cloneA B is su%%orted so rarely within the standard Java library, it is a%%arently a sa"e one as well. But as long as you don t call .b8ect!cloneA B you don t need to i#%le#ent -loneable or catch the e&ce%tion, so that would see# acce%table as well. RFSURFSTIJLT6PPEC7IZ6TI2KU

@ 7oug Dea, who was hel%"ul in resolving this issue, suggested this to #e, saying that he si#%ly creates a "unction called '*plicateA B "or each class.

11=3

/0ercises
Solutions to selected e&ercises can be "ound in the electronic docu#entThe Thinking in Java "nnotated Solution @uide, available "or a s#all "ee "ro# ,,,'0ruceEckel'com.

!4,) 7e#onstrate a second level o" aliasing. +reate a #ethod that


takes a re"erence to an ob0ect but doesn t #odi"y that re"erence s ob0ect. (owever, the #ethod calls a second #ethod, %assing it the re"erence, and this second #ethod does #odi"y the ob0ect. RF SURFSTIJLT6PPEC7IZ6TI2LU

!4-) +reate a class my)tring 1y)tring containing a )tring ob0ect


that you initiali1e in the constructor using the constructor s argu#ent. 6dd a to)tringA B #ethod and a #ethod concatenateA B that a%%ends a )tring ob0ect to your internal string. I#%le#ent cloneA B in my)tring1y)tring. +reate two static #ethods that each take a my)tring 1y)tring 4 re"erence as an argu#ent and call 4!concatenateAMtestMB, but in the second #ethod call cloneA B "irst. Test the two #ethods and show the di""erent e""ects. RFSURFSTIJLT6PPEC7IZ6TI2?U

!44) +reate a class called 2attery containing an int that is a battery


nu#ber *as a uniAue identi"ier,. Make it cloneable and give it a to)tringA B #ethod. Cow create a class called Toy that contains an array o" 2attery and a to)tringA B that %rints out all the batteries. :rite a cloneA B "or Toy that auto#atically clones all o" its 2attery ob0ects. Test this by cloning Toy and %rinting the result. RFSURFSTIJLT6PPEC7IZ6TI2HU

!45) +hange -heck-loneable!8ava so that all o" the cloneA B


#ethods catch the -lone/ot)*pporte'&4ception rather than %assing it to the caller. RFSURFSTIJLT6PPEC7IZ6TI23U

!46) 4sing the #utable'co#%anion'class techniAue, #ake an


i##utable class containing an int, a 'o*ble and an array o" char. RFSURFSTIJLT6PPEC7IZ6TI2GU

!57) Modi"y -ompete!8ava to add #ore #e#ber ob0ects to classes


ThingI and ThingQ and see i" you can deter#ine how the
ti#ings vary with co#%le&ity9whether it s a si#%le linear

11=4

Thinking in Java

,,,'0ruceEckel'com

relationshi% or i" it see#s #ore co#%licated. RFSURF STIJLT6PPEC7IZ6TI2IU

!5() Starting with )nake!8ava, create a dee%'co%y version o" the


snake. RFSURFSTIJLT6PPEC7IZ6TI22U

!5!) Inherit an Array+ist and #ake its cloneA B %er"or# a dee%


co%y.I#%le#ent the -ollection inter"ace in a class called -loning-ollection, using a private Array+ist to %rovide the container "unctionality. )verride the cloneA B #ethod so that -loning-ollection %er"or#s a !conditional dee% co%y=$ it atte#%ts to cloneA B all the ele#ents it contains, but i" it cannot it leaves the re"erence*s, aliased. RFSU

11=5

;: #he "ava 2ative Interface 8"2I9


endi* ,as contributed b) and used ,ith the ermission o$ "ndrea Provaglio K,,,'"ndreaProvaglio'comA'

RFSTIJLT6PPEC7IZBTI@UThe material in this a

The Java language and its standard 6PI are rich enough to write "ull'"ledged a%%lications. But in so#e cases you #ust call non'Java code; "or e&a#%le, i" you want to access o%erating'syste#'s%eci"ic "eatures, inter"ace with s%ecial hardware devices, reuse a %ree&isting, non'Java code base, or i#%le#ent ti#e'critical sections o" code.
Inter"acing with non'Java code reAuires dedicated su%%ort in the co#%iler and in the Virtual Machine, and additional tools to #a% the Java code to the non'Java code. The standard solution "or calling non'Java code that is %rovided by JavaSo"t is called the Java +ative Inter$ace, which will be introduced in this a%%endi&. This is not an in'de%th treat#ent, and in so#e cases you re assu#ed to have %artial knowledge o" the related conce%ts and techniAues. RFSURFSTIJLT6PPEC7IZBTIMU JCI is a "airly rich %rogra##ing inter"ace that allows you to call native #ethods "ro# a Java a%%lication. It was added in Java M.M, #aintaining a certain degree o" co#%atibility with its Java M.@ eAuivalent= the native #ethod inter"ace *CMI,. CMI has design characteristics that #ake it unsuitable "or ado%tion across all virtual #achines. Eor this reason, "uture versions o" the language #ight no longer su%%ort CMI, and it will not be covered here. RFSURFSTIJLT6PPEC7IZBTIKU

11=7

+urrently, JCI is designed to inter"ace with native #ethods written only in + or +<<. 4sing JCI, your native #ethods can=

+reate, ins%ect, and u%date Java ob0ects *including arrays and )trings, +all Java #ethods +atch and throw e&ce%tions Doad classes and obtain class in"or#ation Per"or# run'ti#e ty%e checking
Thus, virtually everything you can do with classes and ob0ects in ordinary Java you can also do in native #ethods. RFSURF STIJLT6PPEC7IZBTILU

Calling a native method


:e ll start with a si#%le e&a#%le= a Java %rogra# that calls a native #ethod, which in turn calls the standard + library "unction printfA B. RF SURFSTIJLT6PPEC7IZBTI?U The "irst ste% is to write the Java code declaring a native #ethod and its argu#ents=

//3 a""en!i6b3%ho:Jessage.Hava "ublic class %ho:Jessage @ "rivate native voi! %ho:Jessage-%tring #sg.< static @ %yste#.loa!Library-8Jsg$#"l8.< // Linu6 hack, if you can2t get your library // "ath set in your environ#ent3 // %yste#.loa!// 8/ho#e/bruce/tiH /a""en!i6b/Jsg$#"l.so8.< A "ublic static voi! #ain-%tringNO args. @ %ho:Jessage a"" ? ne: %ho:Jessage-.< a"".%ho:Jessage-8aenerate! :ith J&$8.< A A ///3>

"

endi* 0! The Java +ative Inter$ace KJ+IA

11=8

The native #ethod declaration is "ollowed by a static block that calls )ystem!loa'+ibraryA B *which you could call at any ti#e, but this style is #ore a%%ro%riate,. )ystem!loa'+ibraryA B loads a 7DD in #e#ory and links to it. The 7DD #ust be in your syste# library %ath. The "ile na#e e&tension is auto#atically added by the JVM de%ending on the %lat"or#. RFSURFSTIJLT6PPEC7IZBTIHU In the above code you can also see a call to the )ystem!loa'A B #ethod, which is co##ented out. The %ath s%eci"ied here is an absolute %ath, rather than relying on an environ#ent variable. 4sing an environ#ent variable is naturally the better and #ore %ortable solution, but i" you can t "igure that out you can co##ent out the loa'+ibraryA B call and unco##ent this one, ad0usting the %ath to your own directory. RFSURF STIJLT6PPEC7IZBTI3U

#he header file generator: 3avah


Cow co#%ile your Java source "ile and run 8avah on the resulting !class "ile, s%eci"ying the _8ni switch *this is done auto#atically "or you by the #ake"ile in the source code distribution "or this book,= RFSURF STIJLT6PPEC7IZBTIGU

Havah eHni %ho:Jessage 8avah reads the Java class "ile and "or each native #ethod declaration it
generates a "unction %rototy%e in a + or +<< header "ile. (ere s the out%ut= the )ho(1essage!h source "ile *edited slightly to "it into this book,= RFSURFSTIJLT6PPEC7IZBTIIU

/B DG &GT ED$T TM$% L$LE - it is #achine generate! B/ Sinclu!e PHni.hQ /B Mea!er for class %ho:Jessage B/ Sifn!ef b$nclu!e!b%ho:Jessage S!efine b$nclu!e!b%ho:Jessage Sif!ef bbc"lus"lus e6tern 8C8 @ Sen!if /B

11=:

B Class3 %ho:Jessage B Jetho!3 %ho:Jessage B %ignature3 -LHava/lang/%tring<.W B/ J&$E9PG5T voi! J&$C0LL Javab%ho:Jessageb%ho:Jessage -J&$Env B, HobHect, Hstring.< Sif!ef bbc"lus"lus A Sen!if Sen!if
6s you can see by the Wif'ef XXcpl*spl*s %re%rocessor directive, this "ile can be co#%iled either by a + or a +<< co#%iler. The "irst Wincl*'e directive includes 8ni!h, a header "ile that, a#ong other things, de"ines the ty%es that you can see used in the rest o" the "ile. J/I&X#.$T and J/I-A++ are #acros that e&%and to #atch %lat"or#'s%eci"ic directives. J/I&nv, 8ob8ect and 8string are JCI data ty%e de"initions, which will be e&%lained shortly. RFSURFSTIJLT6PPEC7IZBTI2U

2ame mangling and function signatures


JCI i#%oses a na#ing convention *called name mangling, on native #ethods. This is i#%ortant, since it s %art o" the #echanis# by which the virtual #achine links Java calls to native #ethods. Basically, all native #ethods start with the word !Java,$ "ollowed by the na#e o" the class in which the Java native declaration a%%ears, "ollowed by the na#e o" the Java #ethod. The underscore character is used as a se%arator. I" the Java native #ethod is overloaded, then the "unction signature is a%%ended to the na#e as well; you can see the native signature in the co##ents %receding the %rototy%e. Eor #ore in"or#ation about na#e #angling and native #ethod signatures, %lease re"er to the JCI docu#entation. RFSURF STIJLT6PPEC7IZBTIM@U

"

endi* 0! The Java +ative Inter$ace KJ+IA

11=;

Im.lementing :our D&&


6t this %oint, all you have to do is write a + or +<< source code "ile that includes the 8avah'generated header "ile and i#%le#ents the native #ethod, then co#%ile it and generate a dyna#ic link library. This %art is %lat"or#'de%endent. The code below is co#%iled and linked into a "ile called 1sgImpl!'ll "or :indows or 1sgImpl!so "or 4ni&FDinu& *the #ake"ile %ackaged with the code listings contains the co##ands to do this9it is available on the +7 5)M bound into this book, or as a "ree download "ro# ,,,'0ruceEckel'com,= RFSURF STIJLT6PPEC7IZBTIMMU

//3 a""en!i6b3Jsg$#"l.c"" //S Teste! :ith WCKK D BCKK. $nclu!e "ath #ust //S be a!Huste! to fin! the J&$ hea!ers. %ee //S the #akefile for this cha"ter -in the //S !o:nloa!able source co!e. for an e6a#"le. Sinclu!e PHni.hQ Sinclu!e Pst!io.hQ Sinclu!e 8%ho:Jessage.h8 e6tern 8C8 J&$E9PG5T voi! J&$C0LL Javab%ho:Jessageb%ho:Jessage-J&$EnvB env, HobHect, Hstring HJsg. @ const charB #sg?env-Qaet%tringYTLChars-HJsg,'.< "rintf-8Thinking in Java, J&$3 Vs_n8, #sg.< env-Q5elease%tringYTLChars-HJsg, #sg.< A ///3>
The argu#ents that are %assed into the native #ethod are the gateway back into Java. The "irst, o" ty%e J/I&nv, contains all the hooks that allow you to call back into the JVM. *:e ll look at this in the ne&t section., The second argu#ent has a di""erent #eaning de%ending on the ty%e o" #ethod. Eor non' static #ethods like the e&a#%le above, the second argu#ent is the eAuivalent o" the !this$ %ointer in +<< and si#ilar to this in Java= it s a re"erence to the ob0ect that called the native #ethod. Eor static #ethods, it s a re"erence to the -lass ob0ect where the #ethod is i#%le#ented. RFSURFSTIJLT6PPEC7IZBTIMKU

111=

The re#aining argu#ents re%resent the Java ob0ects %assed into the native #ethod call. Pri#itives are also %assed in this way, but they co#e in by value. RFSURFSTIJLT6PPEC7IZBTIMLU In the "ollowing sections we ll e&%lain this code by looking at the ways that you access and control the JVM "ro# inside a native #ethod. RFSURF STIJLT6PPEC7IZBTIM?U

Accessing "2I functions: the J97Env argument


JCI "unctions are those that the %rogra##er uses to interact with the JVM "ro# inside a native #ethod. 6s you can see in the e&a#%le above, every JCI native #ethod receives a s%ecial argu#ent as its "irst %ara#eter= the J/I&nv argu#ent, which is a %ointer to a s%ecial JCI data structure o" ty%e J/I&nvX. )ne ele#ent o" the JCI data structure is a %ointer to an array generated by the JVM. Each ele#ent o" this array is a %ointer to a JCI "unction. The JCI "unctions can be called "ro# the native #ethod by dere"erencing these %ointers *it s si#%ler than it sounds,. Every JVM %rovides its own i#%le#entation o" the JCI "unctions, but their addresses will always be at %rede"ined o""sets. RF SURFSTIJLT6PPEC7IZBTIMHU Through the J/I&nv argu#ent, the %rogra##er has access to a large set o" "unctions. These "unctions can be grou%ed into the "ollowing categories=

)btaining version in"or#ation Per"or#ing class and ob0ect o%erations (andling global and local re"erences to Java ob0ects 6ccessing instance "ields and static "ields +alling instance #ethods and static #ethods

"

endi* 0! The Java +ative Inter$ace KJ+IA

1111

Per"or#ing string and array o%erations 8enerating and handling Java e&ce%tions
The nu#ber o" JCI "unctions is Auite large and won t be covered here. Instead, I ll show the rationale behind the use o" these "unctions. Eor #ore detailed in"or#ation, consult your co#%iler s JCI docu#entation. RFSURFSTIJLT6PPEC7IZBTIM3U I" you take a look at the 8ni!h header "ile, you ll see that inside the Wif'ef XXcpl*spl*s %re%rocessor conditional, the J/I&nvX structure is de"ined as a class when co#%iled by a +<< co#%iler. This class contains a nu#ber o" inline "unctions that let you access the JCI "unctions with an easy and "a#iliar synta&. Eor e&a#%le, the line o" +<< code in the %receding e&a#%le=

env-Q5elease%tringYTLChars-HJsg, #sg.<
could also be called "ro# + like this= RFSURFSTIJLT6PPEC7IZBTIMGU

-Benv.-Q5elease%tringYTLChars-env, HJsg, #sg.<


/ou ll notice that the + style is *naturally, #ore co#%licated9you need a double dere"erencing o" the env %ointer, and you #ust also %ass the sa#e %ointer as the "irst %ara#eter to the JCI "unction call. The e&a#%les in this a%%endi& use the +<< style. RFSURFSTIJLT6PPEC7IZBTIMIU

Accessing "ava 1trings


6s an e&a#%le o" accessing a JCI "unction, consider the code in 1sgImpl!cpp. (ere, the J/I&nv argu#ent env is used to access a Java )tring. Java )trings are in 4nicode "or#at, so i" you receive one and want to %ass it to a non'4nicode "unction * printfA B, "or e&a#%le,, you #ust "irst convert it into 6S+II characters with the JCI "unction "et)tringUTF-harsA B. This "unction takes a Java )tring and converts it to 4TE'I characters. *These are I bits wide to hold 6S+II values or M3 bits wide to hold 4nicode. I" the content o" the original string was co#%osed only o" 6S+II, the resulting string will be 6S+II as well., RFSURFSTIJLT6PPEC7IZBTIM2U

1112

"et)tringUTF-harsA B is one o" the #e#ber "unctions in J/I&nv. To access the JCI "unction, we use the ty%ical +<< synta& "or calling a #e#ber "unction though a %ointer. /ou use the "or# above to access all o" the JCI "unctions. RFSURFSTIJLT6PPEC7IZBTIK@U

assing and using "ava ob3ects


In the %revious e&a#%le we %assed a )tring to the native #ethod. /ou can also %ass Java ob0ects o" your own creation to a native #ethod. Inside your native #ethod, you can access the "ields and #ethods o" the ob0ect that was received. RFSURFSTIJLT6PPEC7IZBTIKMU To %ass ob0ects, use the ordinary Java synta& when declaring the native #ethod. In the e&a#%le below, 1yJava-lass has one p*blic "ield and one p*blic #ethod. The class Use.b8ects declares a native #ethod that takes an ob0ect o" class 1yJava-lass. To see i" the native #ethod #ani%ulates its argu#ent, the p*blic "ield o" the argu#ent is set, the native #ethod is called, and then the value o" the p*blic "ield is %rinted.

//3 a""en!i6b3YseGbHects.Hava class JyJavaClass @ "ublic int aWalue< "ublic voi! !ivByT:o-. @ aWalue /? A

< A

"ublic class YseGbHects @ "rivate native voi! changeGbHect-JyJavaClass obH.< static @ %yste#.loa!Library-8YseGbH$#"l8.< // Linu6 hack, if you can2t get your library // "ath set in your environ#ent3 // %yste#.loa!//8/ho#e/bruce/tiH /a""en!i6b/YseGbH$#"l.so8.< A "ublic static voi! #ain-%tringNO args. @ YseGbHects a"" ? ne: YseGbHects-.<

"

endi* 0! The Java +ative Inter$ace KJ+IA

1113

JyJavaClass anGbH ? ne: JyJavaClass-.< anGbH.aWalue ? < a"".changeGbHect-anGbH.< %yste#.out."rintln-8Java3 8 K anGbH.aWalue.< A A ///3>
6"ter co#%iling the code and running 8avah, you can i#%le#ent the native #ethod. In the e&a#%le below, once the "ield and #ethod I7 are obtained, they are accessed through JCI "unctions. RFSURF STIJLT6PPEC7IZBTIKKU

//3 a""en!i6b3YseGbH$#"l.c"" //S Teste! :ith WCKK D BCKK. $nclu!e "ath #ust //S be a!Huste! to fin! the J&$ hea!ers. %ee //S the #akefile for this cha"ter -in the //S !o:nloa!able source co!e. for an e6a#"le. Sinclu!e PHni.hQ e6tern 8C8 J&$E9PG5T voi! J&$C0LL JavabYseGbHectsbchangeGbHectJ&$EnvB env, HobHect, HobHect obH. @ Hclass cls ? env-QaetGbHectClass-obH.< Hfiel!$D fi! ? env-QaetLiel!$Dcls, 8aWalue8, 8$8.< H#etho!$D #i! ? env-QaetJetho!$Dcls, 8!ivByT:o8, 8-.W8.< int value ? env-Qaet$ntLiel!-obH, fi!.< "rintf-8&ative3 V!_n8, value.< env-Q%et$ntLiel!-obH, fi!, +.< env-QCallWoi!Jetho!-obH, #i!.< value ? env-Qaet$ntLiel!-obH, fi!.< "rintf-8&ative3 V!_n8, value.< A ///3>
Ignoring the !this$ eAuivalent, the +<< "unction receives a 8ob8ect, which is the native side o" the Java ob0ect re"erence we %ass "ro# the Java code. :e si#%ly read aVal*e, %rint it out, change the value, call the ob0ect s 'iv2yT(oA B #ethod, and %rint the value out again. RFSURF STIJLT6PPEC7IZBTIKLU To access a Java "ield or #ethod, you #ust "irst obtain its identi"ier using "etFiel'I A B "or "ields and "et1etho'I A B "or #ethods. These

1114

"unctions take the class ob0ect, a string containing the ele#ent na#e, and a string that gives ty%e in"or#ation= the data ty%e o" the "ield, or signature in"or#ation "or a #ethod *details can be "ound in the JCI docu#entation,. These "unctions return an identi"ier that you use to access the ele#ent. This a%%roach #ight see# convoluted, but your native #ethod has no knowledge o" the internal layout o" the Java ob0ect. Instead, it #ust access "ields and #ethods through inde&es returned by the JVM. This allows di""erent JVMs to i#%le#ent di""erent internal ob0ect layouts with no i#%act on your native #ethods. RFSURF STIJLT6PPEC7IZBTIK?U I" you run the Java %rogra#, you ll see that the ob0ect that s %assed "ro# the Java side is #ani%ulated by your native #ethod. But what e&actly is %assedO 6 %ointer or a Java re"erenceO 6nd what is the garbage collector doing during native #ethod callsO RFSURFSTIJLT6PPEC7IZBTIKHU The garbage collector continues to o%erate during native #ethod e&ecution, but it s guaranteed that your ob0ects will not be garbage' collected during a native #ethod call. To ensure this, local re$erences are created be"ore, and destroyed right a"ter, the native #ethod call. Since their li"eti#e wra%s the call, you know that the ob0ects will be valid throughout the native #ethod call. RFSURFSTIJLT6PPEC7IZBTIK3U Since these re"erences are created and subseAuently destroyed every ti#e the "unction is called, you cannot #ake local co%ies in your native #ethods, in static variables. I" you want a re"erence that lasts across "unction invocations, you need a global re"erence. 8lobal re"erences are not created by the JVM, but the %rogra##er can #ake a global re"erence out o" a local one by calling s%eci"ic JCI "unctions. :hen you create a global re"erence, you beco#e res%onsible "or the li"eti#e o" the re"erenced ob0ect. The global re"erence *and the ob0ect it re"ers to, will be in #e#ory until the %rogra##er e&%licitly "rees the re"erence with the a%%ro%riate JCI "unction. It s si#ilar to mallocA B and freeA B in +. RFSURF STIJLT6PPEC7IZBTIKGU

"

endi* 0! The Java +ative Inter$ace KJ+IA

1115

"2I and "ava e0ce.tions


:ith JCI, Java e&ce%tions can be thrown, caught, %rinted, and rethrown 0ust as they are inside a Java %rogra#. But it s u% to the %rogra##er to call dedicated JCI "unctions to deal with e&ce%tions. (ere are the JCI "unctions "or e&ce%tion handling= RFSURFSTIJLT6PPEC7IZBTIKIU

Thro(A B
Throws an e&isting e&ce%tion ob0ect. 4sed in native #ethods to rethrow an e&ce%tion.

Thro(/e(A B
8enerates a new e&ce%tion ob0ect and throws it.

&4ception.cc*rre'A B
7eter#ines i" an e&ce%tion was thrown and not yet cleared.

&4ception escribeA B
Prints an e&ce%tion and the stack trace.

&4ception-learA B
+lears a %ending e&ce%tion.

Fatal&rrorA B
5aises a "atal error. 7oes not return. 6#ong these, you can t ignore &4ception.cc*rre'A B and &4ception-learA B. Most JCI "unctions can generate e&ce%tions, and there is no language "eature that you can use in %lace o" a Java try block, so you #ust call &4ception.cc*rre'A B a"ter each JCI "unction call to see i" an e&ce%tion was thrown. I" you detect an e&ce%tion, you #ay choose to handle it *and %ossibly rethrow it,. /ou #ust #ake certain, however, that the e&ce%tion is eventually cleared. This can be done in your "unction using &4ception-learA B or in so#e other "unction i" the e&ce%tion is rethrown, but it #ust be done. RFSURF STIJLT6PPEC7IZBTIK2U /ou #ust ensure that the e&ce%tion is cleared, because otherwise the results will be un%redictable i" you call a JCI "unction while an e&ce%tion is %ending. There are "ew JCI "unctions that are sa"e to call during an

1117

e&ce%tion; a#ong these, o" course, are all the e&ce%tion handling "unctions. RFSURFSTIJLT6PPEC7IZBTIL@U

"2I and threading


Since Java is a #ultithreaded language, several threads can call a native #ethod concurrently. *The native #ethod #ight be sus%ended in the #iddle o" its o%eration when a second thread calls it., It s entirely u% to the %rogra##er to guarantee that the native call is thread'sa"e; i.e., it does not #odi"y shared data in an un#onitored way. Basically, you have two o%tions= declare the native #ethod as synchroni7e', or i#%le#ent so#e other strategy within the native #ethod to ensure correct, concurrent data #ani%ulation. RFSURFSTIJLT6PPEC7IZBTILMU 6lso, you should never %ass the J/I&nv %ointer across threads, since the internal structure it %oints to is allocated on a %er'thread basis and contains in"or#ation that #akes sense only in that %articular thread. RF SURFSTIJLT6PPEC7IZBTILKU

Csing a .ree0isting code base


The easiest way to i#%le#ent JCI native #ethods is to start writing native #ethod %rototy%es in a Java class, co#%ile that class, and run the ! class "ile through 8avah. But what i" you have a large, %ree&isting code base that you want to call "ro# JavaO 5ena#ing all the "unctions in your 7DDs to #atch the JCI na#e #angling convention is not a viable solution. The best a%%roach is to write a wra%%er 7DD !outside$ your original code base. The Java code calls "unctions in this new 7DD, which in turn calls your original 7DD "unctions. This solution is not 0ust a work' around; in #ost cases you #ust do this anyway because you #ust call JCI "unctions on the ob0ect re"erences be"ore you can use the#. RFSURF STIJLT6PPEC7IZBTILLU

"

endi* 0! The Java +ative Inter$ace KJ+IA

1118

Additional information
/ou can "ind "urther introductory #aterial, including a + *rather than +<<, e&a#%le and discussion o" Microso"t issues, in 6%%endi& 6 o" the "irst edition o" this book, which can be "ound on the +7 5)M bound in with this book, or in a "ree download "ro# ,,,'0ruceEckel'com. More e&tensive in"or#ation is available at >ava'sun'com *in the search engine, select !training N tutorials$ "or keywords !native #ethods$,. +ha%ter MM o" Core Java 2, Colume II, by (orst#ann N +ornell *Prentice'(all, K@@@, gives e&cellent coverage o" native #ethods. RFSU

111:

C: "ava rogramming 'uidelines


RFSTIJLT6PPEC7IZ+TI@UThis a%%endi& contains suggestions to hel% guide you in %er"or#ing low'level %rogra# design, and in writing code.
Caturally, these are guidelines and not rules. The idea is to use the# as ins%irations, and to re#e#ber that there are occasional situations where you need to bend or break a rule. RFSURFSTIJLT6PPEC7IZ+TIMU

Design
!(!) &legance al(ays pays off. In the short ter# it #ight see# like it
takes #uch longer to co#e u% with a truly grace"ul solution to a %roble#, but when it works the "irst ti#e and easily ada%ts to new situations instead o" reAuiring hours, days, or #onths o" struggle, you ll see the rewards *even i" no one can #easure the#,. Cot only does it give you a %rogra# that s easier to build and debug, but it s also easier to understand and #aintain, and that s where the "inancial value lies. This %oint can take so#e e&%erience to understand, because it can a%%ear that you re not being %roductive while you re #aking a %iece o" code elegant. 5esist the urge to hurry; it will only slow you down. RFSURF STIJLT6PPEC7IZ+TIKU

!(*) First make it (ork, then make it fast. This is true even i" you
are certain that a %iece o" code is really i#%ortant and that it will be a %rinci%al bottleneck in your syste#. 7on t do it. 8et the

111;

syste# going "irst with as si#%le a design as %ossible. Then i" it isn t going "ast enough, %ro"ile it. /ou ll al#ost always discover that !your$ bottleneck isn t the %roble#. Save your ti#e "or the really i#%ortant stu"". RFSURFSTIJLT6PPEC7IZ+TILU

!(+) $emember the a'ivi'e an' conC*erb principle. I" the


%roble# you re looking at is too con"using, try to i#agine what the basic o%eration o" the %rogra# would be, given the e&istence o" a #agic !%iece$ that handles the hard %arts. That !%iece$ is an ob0ect 9write the code that uses the ob0ect, then look at the ob0ect and enca%sulate its hard %arts into other ob0ects, etc. RFSURF STIJLT6PPEC7IZ+TI?U

!(,) )eparate the class creator from the class *ser Aclient 'rogra##erB. The class user is the !custo#er$ and doesn t need
or want to know what s going on behind the scenes o" the class. The class creator #ust be the e&%ert in class design and write the class so that it can be used by the #ost novice %rogra##er %ossible, yet still work robustly in the a%%lication. Dibrary use will be easy only i" it s trans%arent. RFSURFSTIJLT6PPEC7IZ+TIHU

!(-) 0hen yo* create a class, attempt to make yo*r names so clear that comments are *nnecessary. /our goal should be to
#ake the client %rogra##er s inter"ace conce%tually si#%le. To this end, use #ethod overloading when a%%ro%riate to create an intuitive, easy'to'use inter"ace. RFSURFSTIJLT6PPEC7IZ+TI3U

!(4) :o*r analysis an' 'esign m*st pro'*ce, at minim*m, the classes in yo*r system, their p*blic interfaces, an' their relationships to other classes, especially base classes. I"
your design #ethodology %roduces #ore than that, ask yoursel" i" all the %ieces %roduced by that #ethodology have value over the li"eti#e o" the %rogra#. I" they do not, #aintaining the# will cost you. Me#bers o" develo%#ent tea#s tend not to #aintain anything that does not contribute to their %roductivity; this is a "act o" li"e that #any design #ethods don t account "or. RFSURF STIJLT6PPEC7IZ+TIGU

!(5) A*tomate everything. :rite the test code "irst *be"ore you write
the class,, and kee% it with the class. 6uto#ate the running o" your

112=

Thinking in Java

,,,'0ruceEckel'com

tests through a #ake"ile or si#ilar tool. This way, any changes can be auto#atically veri"ied by running the test code, and you ll i##ediately discover errors. Because you know that you have the sa"ety net o" your test "ra#ework, you will be bolder about #aking swee%ing changes when you discover the need. 5e#e#ber that the greatest i#%rove#ents in languages co#e "ro# the built'in testing %rovided by ty%e checking, e&ce%tion handling, etc., but those "eatures take you only so "ar. /ou #ust go the rest o" the way in creating a robust syste# by "illing in the tests that veri"y "eatures that are s%eci"ic to your class or %rogra#. RFSURF STIJLT6PPEC7IZ+TIIU

!(6) 0rite the test co'e first Abefore yo* (rite the classB in or'er to verify that yo*r class 'esign is complete. I" you
can t write test code, you don t know what your class looks like. In addition, the act o" writing the test code will o"ten "lush out additional "eatures or constraints that you need in the class9these "eatures or constraints don t always a%%ear during analysis and design. Tests also %rovide e&a#%le code showing how your class can be used. RFSURFSTIJLT6PPEC7IZ+TI2U

!!7) All soft(are 'esign problems can be simplifie' by intro'*cing an e4tra level of concept*al in'irection' This
"unda#ental rule o" so"tware engineering @ is the basis o" abstraction, the %ri#ary "eature o" ob0ect'oriented %rogra##ing. RFSURFSTIJLT6PPEC7IZ+TIM@U

!!() An in'irection sho*l' have a meaning *in concert with


guideline 2,. This #eaning can be so#ething as si#%le as !%utting co##only used code in a single #ethod.$ I" you add levels o" indirection *abstraction, enca%sulation, etc., that don t have #eaning, it can be as bad as not having adeAuate indirection. RF SURFSTIJLT6PPEC7IZ+TIMMU

!!!) 1ake classes as atomic as possible. 8ive each class a single,


clear %ur%ose. I" your classes or your syste# design grows too co#%licated, break co#%le& classes into si#%ler ones. The #ost obvious indicator o" this is sheer si1e= i" a class is big, chances are
@ E&%lained to #e by 6ndrew >oenig.

1121

it s doing too #uch and should be broken u%. +lues to suggest redesign o" a class are= M, 6 co#%licated switch state#ent= consider using %oly#or%his#. K, 6 large nu#ber o" #ethods that cover broadly di""erent ty%es o" o%erations= consider using several classes. L, 6 large nu#ber o" #e#ber variables that concern broadly di""erent characteristics= consider using several classes. RFSURF STIJLT6PPEC7IZ+TIMKU

!!*) 0atch for long arg*ment lists. Method calls then beco#e
di""icult to write, read, and #aintain. Instead, try to #ove the #ethod to a class where it is *#ore, a%%ro%riate, andFor %ass ob0ects in as argu#ents. RFSURFSTIJLT6PPEC7IZ+TIMLU

!!+)

on;t repeat yo*rself. I" a %iece o" code is recurring in #any


#ethods in derived classes, %ut that code into a single #ethod in the base class and call it "ro# the derived'class #ethods. Cot only do you save code s%ace, you %rovide "or easy %ro%agation o" changes. So#eti#es the discovery o" this co##on code will add valuable "unctionality to your inter"ace. RFSURF STIJLT6PPEC7IZ+TIM?U

!!,) 0atch for switch statements or chaine' if+else cla*ses. This is ty%ically an indicator o" t) e/check coding, which #eans
you are choosing what code to e&ecute based on so#e kind o" ty%e in"or#ation *the e&act ty%e #ay not be obvious at "irst,. /ou can usually re%lace this kind o" code with inheritance and %oly#or%his#; a %oly#or%hic #ethod call will %er"or# the ty%e checking "or you, and allow "or #ore reliable and easier e&tensibility. RFSURFSTIJLT6PPEC7IZ+TIMHU

!!-) From a 'esign stan'point, look for an' separate things that change from things that stay the same. That is, search
"or the ele#ents in a syste# that you #ight want to change without "orcing a redesign, then enca%sulate those ele#ents in classes. /ou can learn signi"icantly #ore about this conce%t in Thinking in Patterns ,ith Java, downloadable at ,,,'0ruceEckel'com. RF SURFSTIJLT6PPEC7IZ+TIM3U

1122

Thinking in Java

,,,'0ruceEckel'com

!!4)

on;t e4ten' f*n'amental f*nctionality by s*bclassing. I" an inter"ace ele#ent is essential to a class it should be in the base class, not added during derivation. I" you re adding #ethods by inheriting, %erha%s you should rethink the design. RFSURF STIJLT6PPEC7IZ+TIMGU
and si#%le as you need to solve the %roble# at hand, but don t try to antici%ate all the ways that your class might be used. 6s the class is used, you ll discover ways you #ust e&%and the inter"ace. (owever, once a class is in use you cannot shrink the inter"ace without disturbing client code. I" you need to add #ore #ethods, that s "ine; it won t disturb code, other than "orcing reco#%iles. But even i" new #ethods re%lace the "unctionality o" old ones, leave the e&isting inter"ace alone *you can co#bine the "unctionality in the underlying i#%le#entation i" you want,. I" you need to e&%and the inter"ace o" an e&isting #ethod by adding #ore argu#ents, create an overloaded #ethod with the new argu#ents; this way you won t disturb any e&isting calls to the e&isting #ethod. RFSURF STIJLT6PPEC7IZ+TIMIU

!!5) +ess is more. Start with a #ini#al inter"ace to a class, as s#all

!!6) $ea' yo*r classes alo*' to make s*re they;re logical. 5e"er
to the relationshi% between a base class and derived class as !is'a$ and #e#ber ob0ects as !has'a.$ RFSURFSTIJLT6PPEC7IZ+TIM2U

!*7) 0hen 'eci'ing bet(een inheritance an' composition, ask if yo* nee' to *pcast to the base type. I" not, %re"er
co#%osition *#e#ber ob0ects, to inheritance. This can eli#inate the %erceived need "or #ulti%le base ty%es. I" you inherit, users will think they are su%%osed to u%cast. RFSURF STIJLT6PPEC7IZ+TIK@U

!*() Use 'ata members for variation in val*e an' metho' overri'ing for variation in behavior. That is, i" you "ind a
class that uses state variables along with #ethods that switch behavior based on those variables, you should %robably redesign it to e&%ress the di""erences in behavior within subclasses and overridden #ethods. RFSURFSTIJLT6PPEC7IZ+TIKMU

1123

$heck """.BruceEckel.com for in@de.th details and the date and location of the ne0t Hands-On Java Seminar
Based on this book Taught by Bruce Eckel Personal attention "ro# Bruce Eckel and his se#inar assistants Includes in'class %rogra##ing e&ercises Inter#ediateF6dvanced se#inars also o""ered
1124 Thinking in Java ,,,'0ruceEckel'com

0atch for overloa'ing. 6 #ethod should not conditionally e&ecute


code based on the value o" an argu#ent. In this case, you should create two or #ore overloaded #ethods instead. RFSURF STIJLT6PPEC7IZ+TIKKU

!**) Use e4ception hierarchies9%re"erably derived "ro# s%eci"ic


a%%ro%riate classes in the standard Java e&ce%tion hierarchy. The %erson catching the e&ce%tions can then catch the s%eci"ic ty%es o" e&ce%tions, "ollowed by the base ty%e. I" you add new derived e&ce%tions, e&isting client code will still catch the e&ce%tion through the base ty%e. RFSURFSTIJLT6PPEC7IZ+TIKLU

!*+) )ometimes simple aggregation 'oes the 8ob. 6 !%assenger


co#"ort syste#$ on an airline consists o" disconnected ele#ents= seat, air conditioning, video, etc., and yet you need to create #any o" these in a %lane. 7o you #ake %rivate #e#bers and build a whole new inter"aceO Co9in this case, the co#%onents are also %art o" the %ublic inter"ace, so you should create %ublic #e#ber ob0ects. Those ob0ects have their own %rivate i#%le#entations, which are still sa"e. Be aware that si#%le aggregation is not a solution to be used o"ten, but it does ha%%en. RFSURF STIJLT6PPEC7IZ+TIK?U

!*,) -onsi'er the perspective of the client programmer an' the person maintaining the co'e. 7esign your class to be as obvious as %ossible to use. 6ntici%ate the kind o" changes that will be #ade, and design your class so that those changes will be easy.
RFSURFSTIJLT6PPEC7IZ+TIKHU

!*-) 0atch o*t for agiant ob8ect syn'rome!b This is o"ten an a""liction o" %rocedural %rogra##ers who are new to ))P and who end u% writing a %rocedural %rogra# and sticking it inside one or two giant ob0ects. :ith the e&ce%tion o" a%%lication "ra#eworks, ob0ects re%resent conce%ts in your a%%lication, not the a%%lication. RFSURFSTIJLT6PPEC7IZ+TIK3U !*4) If yo* m*st 'o something *gly, at least locali7e the *gliness insi'e a class. RFSURFSTIJLT6PPEC7IZ+TIKGU

1125

Bruce Eckels Hands-On Java Seminar Multimedia CD Its like coming to the seminar! Available at www.BruceEckel.com

The .ands/On Java Seminar ca%tured on a Multi#edia +7.

)verhead slides and synchroni1ed audio voice narration "or all the lectures. Just %lay it to see and hear the lectures. +reated and narrated by Bruce Eckel. Based on the #aterial in this book.

7e#o lecture available at ,,,'0ruceEckel'com

If yo* m*st 'o something nonportable, make an abstraction for that service an' locali7e it (ithin a class. This e&tra level o"
indirection %revents the non%ortability "ro# being distributed throughout your %rogra#. *This idio# is e#bodied in the 0ridge Pattern,. RFSURFSTIJLT6PPEC7IZ+TIKIU

!*6) .b8ects sho*l' not simply hol' some 'ata. They should also have well'de"ined behaviors. *)ccasionally, !data ob0ects$ are a%%ro%riate, but only when used e&%ressly to %ackage and trans%ort a grou% o" ite#s when a generali1ed container is inna%%ro%riate., RFSURFSTIJLT6PPEC7IZ+TIK2U !+7) -hoose composition first (hen creating ne( classes from e4isting classes. /ou should only used inheritance i" it is
reAuired by your design. I" you use inheritance where co#%osition will work, your designs will beco#e needlessly co#%licated. RF SURFSTIJLT6PPEC7IZ+TIL@U

!+() Use inheritance an' metho' overri'ing to e4press 'ifferences in behavior, an' fiel's to e4press variations in state. 6n e&tre#e e&a#%le o" what not to do is inheriting
di""erent classes to re%resent colors instead o" using a !color$ "ield. RFSURFSTIJLT6PPEC7IZ+TILMU

!+!) 0atch o*t for variance. Two se#antically di""erent ob0ects #ay
have identical actions, or res%onsibilities, and there is a natural te#%tation to try to #ake one a subclass o" the other 0ust to bene"it "ro# inheritance. This is called variance, but there s no real 0usti"ication to "orce a su%erclassFsubclass relationshi% where it doesn t e&ist. 6 better solution is to create a general base class that %roduces an inter"ace "or both as derived classes9it reAuires a bit #ore s%ace, but you still bene"it "ro# inheritance, and will %robably #ake an i#%ortant discovery about the design. RFSURF STIJLT6PPEC7IZ+TILKU

!+*) 0atch o*t for li#itation '*ring inheritance. The clearest


designs add new ca%abilities to inherited ones. 6 sus%icious design re#oves old ca%abilities during inheritance without adding new ones. But rules are #ade to be broken, and i" you are working "ro# an old class library, it #ay be #ore e""icient to restrict an e&isting

1128

class in its subclass than it would be to restructure the hierarchy so your new class "its in where it should, above the old class. RFSURF STIJLT6PPEC7IZ+TILLU

!++) Use 'esign patterns to eliminate anake' f*nctionality!b


That is, i" only one ob0ect o" your class should be created, don t bolt ahead to the a%%lication and write a co##ent !Make only one o" these.$ :ra% it in a singleton. I" you have a lot o" #essy code in your #ain %rogra# that creates your ob0ects, look "or a creational %attern like a "actory #ethod in which you can enca%sulate that creation. Eli#inating !naked "unctionality$ will not only #ake your code #uch easier to understand and #aintain, it will also #ake it #ore bullet%roo" against the well'intentioned #aintainers that co#e a"ter you. RFSURFSTIJLT6PPEC7IZ+TIL?U

!+,) 0atch o*t for aanalysis paralysis!b 5e#e#ber that you #ust usually #ove "orward in a %ro0ect be"ore you know everything, and that o"ten the best and "astest way to learn about so#e o" your unknown "actors is to go to the ne&t ste% rather than trying to "igure it out in your head. /ou can t know the solution until you have the solution. Java has built'in "irewalls; let the# work "or
you. /our #istakes in a class or set o" classes won t destroy the integrity o" the whole syste#. RFSURFSTIJLT6PPEC7IZ+TILHU

!+-) 0hen yo* think yo*;ve got a goo' analysis, 'esign, or implementation, 'o a (alkthro*gh. Bring so#eone in "ro# outside your grou%9this doesn t have to be a consultant, but can be so#eone "ro# another grou% within your co#%any. 5eviewing your work with a "resh %air o" eyes can reveal %roble#s at a stage when it s #uch easier to "i& the#, and #ore than %ays "or the ti#e and #oney !lost$ to the walkthrough %rocess. RFSURF
STIJLT6PPEC7IZ+TIL3U

Im.lementation
!+4) In general, follo( the )*n co'ing conventions. These are
available at

>ava'sun'com/docs/codeconv/inde*'html *the code in this book

112:

Thinking in Java

,,,'0ruceEckel'com

"ollows these conventions as #uch as I was able,. These are used "or what constitutes arguably the largest body o" code that the largest nu#ber o" Java %rogra##ers will be e&%osed to. I" you doggedly stick to the coding style you ve always used, you will #ake it harder "or your reader. :hatever coding conventions you decide on, ensure they are consistent throughout the %ro0ect. There is a "ree tool to auto#atically re"or#at Java code at= home',tal'de/

so$t,are/solutions/>indent' RFSURFSTIJLT6PPEC7IZ+TILGU !+5) 0hatever co'ing style yo* *se, it really 'oes make a 'ifference if yo*r team Aan' even better, yo*r companyB stan'ar'i7es on it. This #eans to the %oint that everyone
considers it "air ga#e to "i& so#eone else s coding style i" it doesn t con"or#. The value o" standardi1ation is that it takes less brain cycles to %arse the code, so that you can "ocus #ore on what the code #eans. RFSURFSTIJLT6PPEC7IZ+TILIU

!+6) Follo( stan'ar' capitali7ation r*les. +a%itali1e the "irst


letter o" class na#es. The "irst letter o" "ields, #ethods, and ob0ects *re"erences, should be lowercase. 6ll identi"iers should run their words together, and ca%itali1e the "irst letter o" all inter#ediate words. Eor e&a#%le=

ThisIsA-lass/ame thisIsA1etho'.rFiel'/ame +a%itali1e all the letters o" static final %ri#itive identi"iers that
have constant initiali1ers in their de"initions. This indicates they are co#%ile'ti#e constants. #ackages are a special case9they are all lowercase letters, even "or inter#ediate words. The do#ain e&tension *co#, org, net, edu, etc., should also be lowercase. *This was a change between Java M.M and Java K., RFSURFSTIJLT6PPEC7IZ+TIL2U

!,7)

on;t create yo*r o(n a'ecorate'b private 'ata member names. This is usually seen in the "or# o" %re%ended underscores
and characters. (ungarian notation is the worst e&a#%le o" this, where you attach e&tra characters that indicate data ty%e, use, location, etc., as i" you were writing asse#bly language and the co#%iler %rovided no e&tra assistance at all. These notations are con"using, di""icult to read, and un%leasant to en"orce and

112;

#aintain. Det classes and %ackages do the na#e sco%ing "or you. RF SURFSTIJLT6PPEC7IZ+TI?@U

!,() Follo( a acanonical formb when creating a class "or general' %ur%ose use. Include de"initions "or eC*alsA B, hash-o'eA B, to)tringA B, cloneA B *i#%le#ent -loneable,, and i#%le#ent -omparable and )eriali7able. RFSURF
STIJLT6PPEC7IZ+TI?MU

!,!) Use the Java2eans aget,b aset,b an' aisb naming conventions "or #ethods that read and change private "ields,
even i" you don t think you re #aking a JavaBean at the ti#e. Cot only does it #ake it easy to use your class as a Bean, but it s a standard way to na#e these kinds o" #ethods and so will be #ore easily understood by the reader. RFSURF STIJLT6PPEC7IZ+TI?KU

!,*) For each class yo* create, consi'er incl*'ing a static 'ublic test1 2 that contains co'e to test that class. /ou don t
need to re#ove the test code to use the class in a %ro0ect, and i" you #ake any changes you can easily rerun the tests. This code also %rovides e&a#%les o" how to use your class. RFSURF STIJLT6PPEC7IZ+TI?LU

!,+) )ometimes yo* nee' to inherit in or'er to access 'rotected members of the base class. This can lead to a
%erceived need "or #ulti%le base ty%es. I" you don t need to u%cast, "irst derive a new class to %er"or# the %rotected access. Then #ake that new class a #e#ber ob0ect inside any class that needs to use it, rather than inheriting. RFSURFSTIJLT6PPEC7IZ+TI??U

!,,) Avoi' the *se of final metho's for efficiency p*rposes. 4se final only when the %rogra# is running, but not "ast enough,
and your %ro"iler has shown you that a #ethod invocation is the bottleneck. RFSURFSTIJLT6PPEC7IZ+TI?HU

!,-) If t(o classes are associate' (ith each other in some f*nctional (ay As*ch as containers an' iteratorsB, try to make one an inner class of the other. This not only
e#%hasi1es the association between the classes, but it allows the

113=

Thinking in Java

,,,'0ruceEckel'com

class na#e to be reused within a single %ackage by nesting it within another class. The Java containers library does this by de"ining an inner Iterator class inside each container class, thereby %roviding the containers with a co##on inter"ace. The other reason you ll want to use an inner class is as %art o" the private i#%le#entation. (ere, the inner class bene"icial "or i#%le#entation hiding rather than the class association and %revention o" na#es%ace %ollution noted above. RFSURF STIJLT6PPEC7IZ+TI?3U

!,4) Anytime yo* notice classes that appear to have high co*pling (ith each other, consi'er the co'ing an' maintenance improvements yo* might get by *sing inner classes. The use o" inner classes will not uncou%le the classes, but
rather #ake the cou%ling e&%licit and #ore convenient. RFSURF STIJLT6PPEC7IZ+TI?GU

!,5)

on;t fall prey to premat*re optimi7ation. This way lies #adness. In %articular, don t worry about writing *or avoiding, native #ethods, #aking so#e #ethods final, or tweaking code to be e""icient when you are "irst constructing the syste#. /our %ri#ary goal should be to %rove the design, unless the design reAuires a certain e""iciency. RFSURFSTIJLT6PPEC7IZ+TI?IU

!,6) %eep scopes as small as possible so the visibility an' lifetime of yo*r ob8ects are as small as possible. This
reduces the chance o" using an ob0ect in the wrong conte&t and hiding a di""icult'to'"ind bug. Eor e&a#%le, su%%ose you have a container and a %iece o" code that iterates through it. I" you co%y that code to use with a new container, you #ay accidentally end u% using the si1e o" the old container as the u%%er bound o" the new one. I", however, the old container is out o" sco%e, the error will be caught at co#%ile'ti#e. RFSURFSTIJLT6PPEC7IZ+TI?2U

!-7) Use the containers in the stan'ar' Java library. Beco#e


%ro"icient with their use and you ll greatly increase your %roductivity. Pre"er Array+ist "or seAuences, Hash)et "or sets, Hash1ap "or associative arrays, and +inke'+ist "or stacks

1131

*rather than )tack, and Aueues. RFSURF STIJLT6PPEC7IZ+TIH@U

!-() For a program to be rob*st, each component m*st be rob*st. 4se all the tools %rovided by Java= access control,
e&ce%tions, ty%e checking, and so on, in each class you create. That way you can sa"ely #ove to the ne&t level o" abstraction when building your syste#. RFSURFSTIJLT6PPEC7IZ+TIHMU

!-!) #refer compile6time errors to r*n6time errors. Try to


handle an error as close to the %oint o" its occurrence as %ossible. Pre"er dealing with the error at that %oint to throwing an e&ce%tion. +atch any e&ce%tions in the nearest handler that has enough in"or#ation to deal with the#. 7o what you can with the e&ce%tion at the current level; i" that doesn t solve the %roble#, rethrow the e&ce%tion. RFSURFSTIJLT6PPEC7IZ+TIHKU

!-*) 0atch for long metho' 'efinitions. Methods should be brie",


"unctional units that describe and i#%le#ent a discrete %art o" a class inter"ace. 6 #ethod that is long and co#%licated is di""icult and e&%ensive to #aintain, and is %robably trying to do too #uch all by itsel". I" you see such a #ethod, it indicates that, at the least, it should be broken u% into #ulti%le #ethods. It #ay also suggest the creation o" a new class. S#all #ethods will also "oster reuse within your class. *So#eti#es #ethods #ust be large, but they should still do 0ust one thing., RFSURFSTIJLT6PPEC7IZ+TIHLU

!-+) %eep things as a'rivate as possible!b )nce you %ublici1e an


as%ect o" your library *a #ethod, a class, a "ield,, you can never take it out. I" you do, you ll wreck so#ebody s e&isting code, "orcing the# to rewrite and redesign. I" you %ublici1e only what you #ust, you can change everything else with i#%unity, and since designs tend to evolve this is an i#%ortant "reedo#. In this way, i#%le#entation changes will have #ini#al i#%act on derived classes. Privacy is es%ecially i#%ortant when dealing with #ultithreading9only private "ields can be %rotected against un' synchroni7e' use. RFSURFSTIJLT6PPEC7IZ+TIH?U

!-,) Use comments liberally, an' *se the javadoc comment6 'oc*mentation synta4 to pro'*ce yo*r program

1132

Thinking in Java

,,,'0ruceEckel'com

'oc*mentation. (owever, the co##ents should add geniune #eaning to the code; co##ents that only reiterate what the code is clearly e&%ressing are annoying. Cote that the ty%ical verbose detail o" Java class and #ethod na#es reduce the need "or as #any co##ents. RFSURFSTIJLT6PPEC7IZ+TIHHU !--) Avoi' *sing amagic n*mbersb9which are nu#bers hard' wired into code. These are a night#are i" you need to change the#, since you never know i" !M@@$ #eans !the array si1e$ or !so#ething else entirely.$ Instead, create a constant with a descri%tive na#e and use the constant identi"ier throughout your %rogra#. This #akes the %rogra# easier to understand and #uch easier to #aintain. RFSURFSTIJLT6PPEC7IZ+TIH3U !-4) 0hen creating constr*ctors, consi'er e4ceptions. In the
best case, the constructor won t do anything that throws an e&ce%tion. In the ne&t'best scenario, the class will be co#%osed and inherited "ro# robust classes only, so they will need no cleanu% i" an e&ce%tion is thrown. )therwise, you #ust clean u% co#%osed classes inside a finally clause. I" a constructor #ust "ail, the a%%ro%riate action is to throw an e&ce%tion, so the caller doesn t continue blindly, thinking that the ob0ect was created correctly. RFSURFSTIJLT6PPEC7IZ+TIHGU

!-5) If yo*r class reC*ires any clean*p (hen the client programmer is finishe' (ith the ob8ect, place the clean*p co'e in a single, (ell6'efine' metho'9with a na#e like clean*pA B that clearly suggests its %ur%ose. In addition, %lace a boolean "lag in the class to indicate whether the ob0ect has been cleaned u% so that finali7eA B can check "or !the death condition$
*see +ha%ter ?,. RFSURFSTIJLT6PPEC7IZ+TIHIU

!-6) The responsibility of finali%e1 2 can only be to verify athe 'eath con'itionb of an ob8ect for 'eb*gging! *See +ha%ter
?., In s%ecial cases, it #ight be needed to release #e#ory that would not otherwise be released by the garbage collector. Since the garbage collector #ight not get called "or your ob0ect, you cannot use finali7eA B to %er"or# necessary cleanu%. Eor that you #ust create your own !cleanu%$ #ethod. In the finali7eA B #ethod "or

1133

the class, check to #ake sure that the ob0ect has been cleaned u% and throw a class derived "ro# $*ntime&4ception i" it hasn t, to indicate a %rogra##ing error. Be"ore relying on such a sche#e, ensure that finali7eA B works on your syste#. */ou #ight need to call )ystem!gcA B to ensure this behavior., RFSURF STIJLT6PPEC7IZ+TIH2U

!47) If an ob8ect m*st be cleane' *p Aother than by garbage collectionB (ithin a partic*lar scope, *se the follo(ing approach< Initiali1e the ob0ect and, i" success"ul, i##ediately enter a try block with a finally clause that %er"or#s the cleanu%.
RFSURFSTIJLT6PPEC7IZ+TI3@U

!4() 0hen overri'ing finali%e1 2 '*ring inheritance, remember to call su'er6finali%e1 2! *This is not necessary i" .b8ect is your i##ediate su%erclass., /ou should call s*per! finali7eA B as the $inal act o" your overridden finali7eA B rather
than the "irst, to ensure that base'class co#%onents are still valid i" you need the#. RFSURFSTIJLT6PPEC7IZ+TI3MU

!4!) 0hen yo* are creating a fi4e'6si7e container of ob8ects, transfer them to an array9es%ecially i" you re returning this
container "ro# a #ethod. This way you get the bene"it o" the array s co#%ile'ti#e ty%e checking, and the reci%ient o" the array #ight not need to cast the ob0ects in the array in order to use the#. Cote that the base'class o" the containers library, 8ava!*til! -ollection, has two toArrayA B #ethods to acco#%lish this. RF SURFSTIJLT6PPEC7IZ+TI3KU

!4*) -hoose interfaces over abstract classes. I" you know


so#ething is going to be a base class, your "irst choice should be to #ake it an interface, and only i" you re "orced to have #ethod de"initions or #e#ber variables should you change it to an abstract class. 6n interface talks about what the client wants to do, while a class tends to "ocus on *or allow, i#%le#entation details. RFSURFSTIJLT6PPEC7IZ+TI3LU

!4+) Insi'e constr*ctors, 'o only (hat is necessary to set the ob8ect into the proper state. 6ctively avoid calling other #ethods *e&ce%t "or final #ethods, since those #ethods can be

1134

Thinking in Java

,,,'0ruceEckel'com

overridden by so#eone else to %roduce une&%ected results during construction. *See +ha%ter G "or details., S#aller, si#%ler constructors are less likely to throw e&ce%tions or cause %roble#s. RFSURFSTIJLT6PPEC7IZ+TI3?U

!4,) To avoi' a highly fr*strating e4perience, make s*re that there is only one *npackage' class of each name any(here in yo*r classpath. )therwise, the co#%iler can "ind
the identically'na#ed other class "irst, and re%ort error #essages that #ake no sense. I" you sus%ect that you are having a class%ath %roble#, try looking "or !class "iles with the sa#e na#es at each o" the starting %oints in your class%ath. Ideally, %ut all your classes within %ackages. RFSURFSTIJLT6PPEC7IZ+TI3HU

!4-) 0atch o*t for acci'ental overloa'ing. I" you atte#%t to


override a base'class #ethod and you don t Auite get the s%elling right, you ll end u% adding a new #ethod rather than overriding an e&isting #ethod. (owever, this is %er"ectly legal, so you won t get any error #essage "ro# the co#%iler or run'ti#e syste#9your code si#%ly won t work correctly. RFSURF STIJLT6PPEC7IZ+TI33U

!44) 0atch o*t for premat*re optimi7ation. Eirst #ake it work, then #ake it "ast9but only i" you #ust, and only i" it s %roven that there is a %er"or#ance bottleneck in a %articular section o" your code. 4nless you have used a %ro"iler to discover a bottleneck, you will %robably be wasting your ti#e. The hidden cost o" %er"or#ance tweaks is that your code beco#es less understandable and #aintainable. RFSURFSTIJLT6PPEC7IZ+TI3GU !45) $emember that co'e is rea' m*ch more than it is (ritten. +lean designs #ake "or easy'to'understand %rogra#s, but co##ents, detailed e&%lanations, and e&a#%les are invaluable. They will hel% both you and everyone who co#es a"ter you. I" nothing else, the "rustration o" trying to "erret out use"ul in"or#ation "ro# the online Java docu#entation should convince you. RFSU

1135

D: $esources
1oftware
RFSTIJLT6PPEC7IZ7TI@U The J % "ro# >ava'sun'com. Even i" you choose to use a third'%arty develo%#ent environ#ent, it s always a good idea to have the J7> on hand in case you co#e u% against what #ight be a co#%iler error. The J7> is the touchstone, and i" there is a bug in it, chances are it will be well'known. RFSURFSTIJLT6PPEC7IZ7TIMU

The HT1+ Java 'oc*mentation "ro# >ava'sun'com. I have never


"ound a re"erence book on the standard Java libraries that wasn t out o" date or #issing in"or#ation. 6lthough the (TMD docu#entation "ro# Sun is shot'through with s#all bugs and is so#eti#es unusably terse, all the classes and #ethods are at least there. Peo%le are so#eti#es unco#"ortable at "irst using an online resource rather than a %rinted book, but it s worth your while to get over this and o%en the (TMD docs "irst, so you can at least get the big %icture. I" you can t "igure it out at that %oint, then reach "or the %rinted books. RFSURFSTIJLT6PPEC7IZ7TIKU

;ooks
Thinking in Java7 8st dition. 6vailable as "ully'inde&ed, color'
synta&'highlighted (TMD on the +7 5)M bound in with this book, or as a "ree download "ro# ,,,'0ruceEckel'com. Includes older #aterial and #aterial that was not considered interesting enough to carry through to the K nd edition. RFSURFSTIJLT6PPEC7IZ7TILU

Core Java 9, by (orst#ann N +ornell, Volu#e I9Eunda#entals *Prentice'(all, M222,. Volu#e II96dvanced Eeatures, K@@@. (uge, co#%rehensive, and the "irst %lace I go when I # hunting "or answers. The book I reco##end when you ve co#%leted Thinking in Java and need to cast a bigger net. RFSURFSTIJLT6PPEC7IZ7TI?U

1137

Java in a 0utshell. - Deskto' :uick Reference7 9nd dition, by 7avid Elanagan *) 5eilly, M22G,. 6 co#%act su##ary o" the online Java docu#entation. Personally, I %re"er to browse the docs "ro# >ava'sun' com online, es%ecially since they change so o"ten. (owever, #any "olks still like %rinted docu#entation and this "its the bill; it also %rovides #ore discussion than the online docu#ents. F/GHF/GTIJ3I"PPE+%IN%II5H The Java Class 5ibraries. -n -nnotated Reference, by Patrick +han and 5osanna Dee *6ddison':esley, M22G,. :hat the online re"erence should have been= enough descri%tion to #ake it usable. )ne o" the technical reviewers "or Thinking in Java said, !I" I had only one Java book, this would be it *well, in addition to yours, o" course,.$ I # not as thrilled with it as he is. It s big, it s e&%ensive, and the Auality o" the e&a#%les doesn t satis"y #e. 0ut it s a %lace to look when you re stuck and it see#s to have #ore de%th *and sheer si1e, than Java in a +utshell. RF SURFSTIJLT6PPEC7IZ7TI3U Java 0etwork "rogra##ing, by Elliotte 5usty (arold *) 5eilly, M22G,. I didn t begin to understand Java networking until I "ound this book. I also "ind his :eb site, +a"W au Dait, to be a sti#ulating, o%inionated, and u%'to'date %ers%ective on Java develo%#ents, unencu#bered by allegiances to any vendors. (is regular u%dates kee% u% with "ast'changing news about Java. See metalab'unc'edu/>ava$a#/. RF SURFSTIJLT6PPEC7IZ7TIGU JD4C Database -ccess with Java, by (a#ilton, +attell N Eisher
*6ddison':esley, M22G,. I" you know nothing about SeD and databases, this is a nice, gentle introduction. It also contains so#e o" the details as well as an !annotated re"erence$ to the 6PI *again, what the online re"erence should have been,. The drawback, as with all books in The Java Series *!The )CD/ Books 6uthori1ed by JavaSo"t$, is that it s been whitewashed so that it says only wonder"ul things about Java9you won t "ind out about any dark corners in this series. RFSURF STIJLT6PPEC7IZ7TIIU

Java "rogra##ing with COR4-, by 6ndreas Vogel N >eith 7uddy


*John :iley N Sons, M22G,. 6 serious treat#ent o" the sub0ect with code e&a#%les "or three Java )5Bs *Visibroker, )rbi&, Joe,. RFSURF STIJLT6PPEC7IZ7TI2U

"

endi* %! -esources

1138

Design "atterns, by 8a##a, (el#, Johnson N Vlissides *6ddison' :esley, M22H,. The se#inal book that started the %atterns #ove#ent in %rogra##ing. RFSURFSTIJLT6PPEC7IZ7TIM@U "ractical -lgorith#s for "rogra##ers, by Binstock N 5e&
*6ddison':esley, M22H,. The algorith#s are in +, so they re "airly easy to translate into Java. Each algorith# is thoroughly e&%lained. RFSURF STIJLT6PPEC7IZ7TIMMU

Anal:sis L design
xtre#e "rogra##ing x'lained, by >ent Beck *6ddison':esley, K@@@,. I love this book. /es, I tend to take a radical a%%roach to things but IVve always "elt that there could be a #uch di""erent, #uch better %rogra# develo%#ent %rocess, and I think ZP co#es %retty darn close. The only book that has had a si#ilar i#%act on #e was Peo leBare *described below,, which talks %ri#arily about the environ#ent and dealing with cor%orate culture. E*treme Programming E* lained talks about %rogra##ing, and turns #ost things, even recent !"indings,$ on their ear. They even go so "ar as to say that %ictures are )> as long as you don t s%end too #uch ti#e on the# and are willing to throw the# away. */ou ll notice that this book does not have the !4MD sta#% o" a%%roval$ on its cover., I could see deciding whether to work "or a co#%any based solely on whether they used ZP. S#all book, s#all cha%ters, e""ortless to read, e&citing to think about. /ou start i#agining yoursel" working in such an at#os%here and it brings visions o" a whole new world. RFSURF STIJLT6PPEC7IZ7TIMKU U/5 Distilled7 9nd dition, by Martin Eowler *6ddison':esley,
K@@@,. :hen you "irst encounter 4MD, it is daunting because there are so #any diagra#s and details. 6ccording to Eowler, #ost o" this stu"" is unnecessary so he cuts through to the essentials. Eor #ost %ro0ects, you only need to know a "ew diagra##ing tools, and Eowler s goal is to co#e u% with a good design rather than worry about all the arti"acts o" getting there. 6 nice, thin, readable book; the "irst one you should get i" you need to understand 4MD. RFSURFSTIJLT6PPEC7IZ7TIMLU

U/5 Toolkit, by (ans'Erik Eriksson N Magnus Penker, *John :iley N


Sons, M22G,. E&%lains 4MD and how to use it, and has a case study in

113:

Java. 6n acco#%anying +7 5)M contains the Java code and a cut'down version o" 5ational 5ose. 6n e&cellent introduction to 4MD and how to use it to build a real syste#. RFSURFSTIJLT6PPEC7IZ7TIM?U

The Unified *oftware Develo'#ent "rocess, by Ivar Jacobsen,


8rady Booch, and Ja#es 5u#baugh *6ddison':esley, M222,. I went in "ully %re%ared to dislike this book. It see#ed to have all the #akings o" a boring college te&t. I was %leasantly sur%rised9only %ockets o" the book contain e&%lanations that see# as i" those conce%ts aren t clear to the authors. The bulk o" the book is not only clear, but en0oyable. 6nd best o" all, the %rocess #akes a lot o" %ractical sense. It s not E&tre#e Progra##ing *and does not have their clarity about testing, but it s also %art o" the 4MD 0uggernaut9even i" you can t get ZP ado%ted, #ost %eo%le have cli#bed aboard the !4MD is good$ bandwagon *regardless o" their actual level o" e&%erience with it, and so you can %robably get it ado%ted. I think this book should be the "lagshi% o" 4MD, and the one you can read a"ter Eowler s <M( %istilled when you want #ore detail. RF SURFSTIJLT6PPEC7IZ7TIMHU Be"ore you choose any #ethod, it s hel%"ul to gain %ers%ective "ro# those who are not trying to sell one. It s easy to ado%t a #ethod without really understanding what you want out o" it or what it will do "or you. )thers are using it, which see#s a co#%elling reason. (owever, hu#ans have a strange little %sychological Auirk= I" they want to believe so#ething will solve their %roble#s, they ll try it. *This is e&%eri#entation, which is good., But i" it doesn t solve their %roble#s, they #ay redouble their e""orts and begin to announce loudly what a great thing they ve discovered. *This is denial, which is not good., The assu#%tion here #ay be that i" you can get other %eo%le in the sa#e boat, you won t be lonely, even i" it s going nowhere *or sinking,. RFSURFSTIJLT6PPEC7IZ7TIM3U This is not to suggest that all #ethodologies go nowhere, but that you should be ar#ed to the teeth with #ental tools that hel% you stay in e&%eri#entation #ode *!It s not working; let s try so#ething else$, and out o" denial #ode *!Co, that s not really a %roble#. Everything s wonder"ul, we don t need to change$,. I think the "ollowing books, read be$ore you choose a #ethod, will %rovide you with these tools. RFSURF STIJLT6PPEC7IZ7TIMGU

"

endi* %! -esources

113;

*oftware Creativit!, by 5obert 8lass *Prentice'(all, M22H,. This is the best book I ve seen that discusses ers ective on the whole #ethodology issue. It s a collection o" short essays and %a%ers that 8lass has written and so#eti#es acAuired *P.J. Plauger is one contributor,, re"lecting his #any years o" thinking and study on the sub0ect. They re entertaining and only long enough to say what s necessary; he doesn t ra#ble and bore you. (e s not 0ust blowing s#oke, either; there are hundreds o" re"erences to other %a%ers and studies. 6ll %rogra##ers and #anagers should read this book be"ore wading into the #ethodology #ire. RFSURF STIJLT6PPEC7IZ7TIMIU *oftware Runawa!s. /onu#ental *oftware Disasters, by 5obert 8lass *Prentice'(all, M22G,. The great thing about this book is that it brings to the "ore"ront what we don t talk about= how #any %ro0ects not only "ail, but "ail s%ectacularly. I "ind that #ost o" us still think !That can t ha%%en to #e$ *or !That can t ha%%en again$,, and I think this %uts us at a disadvantage. By kee%ing in #ind that things can always go wrong, you re in a #uch better %osition to #ake the# go right. RFSURF STIJLT6PPEC7IZ7TIM2U "eo'lewareD 9nd dition, by To# 7e#arco and Ti#othy Dister *7orset
(ouse, M222,. 6lthough they have backgrounds in so"tware develo%#ent, this book is about %ro0ects and tea#s in general. But the "ocus is on the eo le and their needs, rather than the technology and its needs. They talk about creating an environ#ent where %eo%le will be ha%%y and %roductive, rather than deciding what rules those %eo%le should "ollow to be adeAuate co#%onents o" a #achine. This latter attitude, I think, is the biggest contributor to %rogra##ers s#iling and nodding when Z/Q #ethod is ado%ted and then Auietly doing whatever they ve always done. RFSURFSTIJLT6PPEC7IZ7TIK@U

Co#'lexit!, by M. Mitchell :aldro% *Si#on N Schuster, M22K,. This


chronicles the co#ing together o" a grou% o" scientists "ro# di""erent disci%lines in Santa Ee, Cew Me&ico, to discuss real %roble#s that their individual disci%lines couldn t solve *the stock #arket in econo#ics, the initial "or#ation o" li"e in biology, why %eo%le do what they do in sociology, etc.,. By crossing %hysics, econo#ics, che#istry, #ath, co#%uter science, sociology, and others, a #ultidisci%linary a%%roach to these %roble#s is develo%ing. But #ore i#%ortant, a di""erent way o"

114=

thinking about these ultra'co#%le& %roble#s is e#erging= 6way "ro#


#athe#atical deter#inis# and the illusion that you can write an eAuation that %redicts all behavior, and toward "irst observing and looking "or a %attern and trying to e#ulate that %attern by any #eans %ossible. *The book chronicles, "or e&a#%le, the e#ergence o" genetic algorith#s., This kind o" thinking, I believe, is use"ul as we observe ways to #anage #ore and #ore co#%le& so"tware %ro0ects. RFSURF STIJLT6PPEC7IZ7TIKMU

:thon
5earning "!thon, by Mark Dut1 and 7avid 6scher *) 5eilly, M222,. 6
nice %rogra##er s introduction to what is ra%idly beco#ing #y "avorite language, an e&cellent co#%anion to Java. The book includes an introduction to JPython, which allows you to co#bine Java and Python in a single %rogra# *the JPython inter%reter is co#%iled to %ure Java bytecodes, so there is nothing s%ecial you need to add to acco#%lish this,. This language union %ro#ises great %ossibilities. RFSURF STIJLT6PPEC7IZ7TIKKU

M: own list of books


Disted in order o" %ublication. Cot all o" these are currently available. RF SURFSTIJLT6PPEC7IZ7TIKLU

Co#'uter Interfacing with "ascal & C, *Sel"'%ublished via the Eisys i#%rint, M2II. )nly available via ,,,'0ruceEckel'com,. 6n introduction to electronics "ro# back when +PFM was still king and 7)S was an u%start. I used high'level languages and o"ten the %arallel %ort o" the co#%uter to drive various electronic %ro0ects. 6da%ted "ro# #y colu#ns in the "irst and best #aga1ine I wrote "or, Micro Cornuco ia' *To %ara%hrase Darry ) Brien, long'ti#e editor o" So$t,are %evelo ment Maga?ine= the best co#%uter #aga1ine ever %ublished9they even had %lans "or building a robot in a "lower %ot., 6las, Micro + beca#e lost long be"ore the Internet a%%eared. +reating this book was an e&tre#ely satis"ying %ublishing e&%erience. RFSURFSTIJLT6PPEC7IZ7TIK?U

"

endi* %! -esources

1141

Using C++, *)sborneFMc8raw'(ill, M2I2,. )ne o" the "irst books out on +<<. This is out o" %rint and re%laced by its second edition, the rena#ed C++ Inside & Out. RFSURFSTIJLT6PPEC7IZ7TIKHU C++ Inside & Out, *)sborneFMc8raw'(ill, M22L,. 6s noted, actually the K nd edition o" Using -LL. The +<< in this book is reasonably accurate, but itVs circa M22K and Thinking in C++ is intended to re%lace it.
/ou can "ind out #ore about this book and download the source code at ,,,'0ruceEckel'com. RFSURFSTIJLT6PPEC7IZ7TIK3U

Thinking in C++7 8st dition, *Prentice'(all, M22H,. RFSURF


STIJLT6PPEC7IZ7TIKGU

Thinking in C++7 9nd dition7 ;olu#e 8, *Prentice'(all, K@@@,. 7ownloadable "ro# ,,,'0ruceEckel'com. RFSURF
STIJLT6PPEC7IZ7TIKIU

4lack 4elt C++7 the /aster<s Collection, Bruce Eckel, editor *MNT
Books, M22?,. )ut o" %rint. 6 collection o" cha%ters by various +<< lu#inaries based on their %resentations in the +<< track at the So"tware 7evelo%#ent +on"erence, which I chaired. The cover on this book sti#ulated #e to gain control over all "uture cover designs. RFSURF STIJLT6PPEC7IZ7TIK2U

Thinking in Java7 8st dition, *Prentice'(all, M22I,. The "irst edition o" this book won the So$t,are %evelo ment Maga?ine Productivity 6ward, the Java %evelo erJs Journal Editor s +hoice 6ward, and the JavaBorld -eaderJs Choice ",ard $or best book. 7ownloadable "ro# ,,,'0ruceEckel'com. RFSU

1142

Inde0
Please note that so#e na#es will be du%licated in ca%itali1ed "or#. Eollowing Java style, the ca%itali1ed na#es re"er to Java classes, while lowercase na#es re"er to a general conce%t.
boolean g

o%erators that won t work with boolean g M?I


0avac g MKI, a\ g MH?, Pde%recated g ML?, N\ g MH?, R g M?I, RR\ g MHH \\ g

o%erator g M@3H
]\ g MH?

6
abstract g

class g LLI
abstract keyword g LL2, 6bstract :indow Toolkit *6:T, g GM3, 6bstractButton g G3L, abstraction g LM, 6bstractSeAuentialDist g HK@, 6bstractSet g ?GI, acce%t* , g 2?L access g

control g KHK, s%eci"iers g LI, KHK, K3?


action co##and g G2?, 6ctionEvent g G2H, I?H, 6ctionDistener g GL2, actor, in use cases g IK, add* ,, 6rrayDist g ?33, add6ctionDistener* , g I?K, I2@, add+hangeDistener g I@@, addition g M?L, addDistener g GH@, addZZZDistener* , g GHM, 6dlerLK g 3LK, aggregation g L2 aliasing g M?K

and String g M@2H, during a #ethod call g M@H?


align g GK?, 6lreadyBoundE&ce%tion g M@M? analysis g

%aralysis g GG
and g M@GH 6C7 g

logical *NN, g MH@


anony#ous inner class g LIH, H2I, GLG, 2@G anony#ous inner class g

and constructors g LI2

anony#ous inner class, and table'driven code g HK@ a%%let g GM2

advantages "or clientFserver syste#s g GK@, co#bined a%%lets and a%%lications g GKI, %ackaging a%%lets in a J65 "ile to o%ti#i1e loading g IKL, %lacing inside a :eb %age g GKL
6%%let g

co#bined with a%%lication g IGM, initiali1ation %ara#eters g IGM


a%%letviewer g GKH a%%lication g

a%%lication builder g ILM, a%%lication "ra#ework g ?@2, co#bined with 6%%let g IGM
a%%lication "ra#ework, and a%%lets g GKM, archive tag, "or (TMD and J65 "iles g IKL argu#ent g

"inal g L@2, %assing a re"erence into a #ethod g M@H?


array g ?KK

ele#ent co#%arisons g ??G, "irst'class ob0ects g ?K?, initiali1ation g KL2, length g K?@, o" ob0ects g ?K?, o" %ri#itives g ?K?
6rrayDist g ?GK, ?I@, HMI, HKL, 6rrays class, container utility g ?L@, 6rrays.asDist* , g HLI, 6rrays.binarySearch* , g ?HK, 6rrays."ill* , g ??L, assigning ob0ects g M?M, assign#ent g M?@, associative array g ?HH, ?2?, associative arrays *Ma%s, g ?HI, auto'decre#ent o%erator g M?3, auto'incre#ent o%erator g M?3, auto#atic ty%e conversion g KIL, available* , g 3KM

B
base g

ty%es g ?M
base M3 g M3L, base I g M3? base class g KG@, KI3, LK3

base'class inter"ace g LLM, constructor g L?H


B6SI+ language g 2I, Basic6rrowButton g G3?, beanbo& Bean testing tool g I?I Beans g

and #ultithreading g II3, na#ing convention g ILK


Beck, >ent g MMLI, Bill Joy g M?G binary g

nu#bers g M3?, o%erators g MHL


binary nu#bers, %rinting g MHG, binarySearch* , g ?HK binding g

late binding g LKG


BitSet g H?M

1144

bitwise g

6C7 g M3M, 6C7 o%erator *N, g MHL, EZ+D4SIVE )5 Z)5 *a, g MHL, C)T h g MHL, o%erators g MHL, )5 o%erator *], g MHL
bitwise co%y g M@3?, blank "inal g L@I blocking g

and available* , g 3KK, and threads g I2M, on IF) g 2@M


Booch, 8rady g MML2 book g

errors, re%orting g K?
Boolean g MG3 Boolean g

algebra g MHL, and casting g M3K, vs. + and +<< g MHM


BorderDayout g G?M, Borland g IHM, bound %ro%erties g I?2, bounds checking, array g K?M, Bo&, "or Bo&Dayout g G?3, Bo&Dayout g G?H, break keyword g MIL, Bu""ered5eader g HI?, 3K@, Bu""ered:riter g 3KK, business ob0ectsFlogic g IKG button g

creating your own g GH2


button, Swing g GLL, Button8rou% g G3?, GG2, buttons g G3L, Byte6rrayIn%utStrea# g 3@L, Byte6rray)ut%utStrea# g 3@H

+
+F+<<, inter"acing with g MM@G +<< g M?I

co%y constructor g M@IL, Standard +ontainer Dibrary aka STD g ?HH, strategies "or transition to g 2I, vector class, vs. array and 6rrayDist g ?KL, why it succeeds g 23
callback g ??G, H23, GLH callbacks g

and inner classes g ?@3


ca%acity, o" a (ashMa% or (ashSet g H@I ca%itali1ation g

o" %ackage na#es g MKM


case state#ent g M2M, cast g H@, K@2, 3II cast g

and containers g ?33, and %ri#itive ty%es g MGG, "ro# "loat or double to integral, truncation g M2?, o%erators g M3M
catch g

catching an e&ce%tion g HHH, catching any e&ce%tion g H3L, keyword g HH3

+7 5)M "or book g K@ change g

vector o" change g ?ML


check bo& g GGG, +heckedIn%utStrea# g 3L@, +hecksu# g 3LK class g L?, KGK, HII

g L2M, access g KGL, browser g KGL, class literal g 32M, 32H, creators g LG, eAuivalence, and instanceo"FisInstance* , g 322, initiali1ing #e#bers at %oint o" de"inition g KK2, inner classes and overriding g ?@@, keyword g ?@, loading g LMG, #e#ber initiali1ation g KIL, read'only classes g M@II
+lass g G33

+lass ob0ect g 3HI, 3II, II@


class'res%onsibility'collaboration *+5+, cards g I?, +lass+astE&ce%tion g LHI, 32K class%ath g KHG, GK3

and r#ic g M@M3


cleanu% g

%er"or#ing g KMG, with "inally g HGH


cleanu%, guaranteeing with "inali1e* , g KKK client %rogra##er g LG

vs. library creator g KHK


client, network g 2?M, clone* , g M@3M, +loneable inter"ace g M@3K, +loneCotSu%%ortedE&ce%tion g M@3?, close* , g 3K@, closure, and inner classes g ?@3 code g

coding standards g KK, MMM2, organi1ation g K3H


codebase g GK? collection g KMI

g K2L
+ollection g ?H3, collection class g ?KK, +ollections g HL@, +ollections.enu#eration* , g HL2, +ollections."ill* , g ?HI, +ollections.reverse)rder*, g ?H@, collisions, during hashing g H@3, co#.bruceeckel.swing g GLM, co##a o%erator g M3@, MIL, +o##and Pattern g H23 co##ents g

and e#bedded docu#entation g MKI


co##on inter"ace g LLI, co##on %it"alls when using o%erators g M3M, +o##on'8ateway Inter"ace *+8I, g 2IL, +o#%arable g ??G, ?2L, +o#%arator g ??2, co#%areTo* ,, in 0ava.lang. +o#%arable g ??G, co#%aring arrays g ??3, co#%ilation unit g KH?, co#%ile'ti#e constant g L@H, co#%onent, and JavaBeans g ILK co#%osition g L2, KIM

and cloning g M@3I, and design g LHL, choosing co#%osition vs. inheritance g K2I, co#bining co#%osition N inheritance g K2M, vs. inheritance g L@?

1147

conce%ts g L@, conditional o%erator g MH2 +onsole g

Swing dis%lay "ra#ework in co#.bruceeckel.swing g GK2


console in%ut g 3K@, const, in +<< g M@2H constant g

"olding g L@H, grou%s o" constant values g LGK, i#%licit constants, and String g M@2H
constrained %ro%erties g I?2 constructor g

and e&ce%tion handling g HIL, and e&ce%tions g HIK, and "inally g HI?, and overloading g K@K, argu#ents g K@@, base'class constructors and e&ce%tions g K2M, calling base'class constructors with argu#ents g K2@, calling "ro# other constructors g KMK, initiali1ation during inheritance and co#%osition g K2M, na#e g M22, return value g K@M
+onstructor g

"or re"lection g G@H


container g

class g ?KK, ?HH, o" %ri#itives g ?KI


container classes, utilities "or g ?3@, control "ra#ework, and inner classes g ?@2, controlling access g KGG cookies g

and JSP g M@@I


cookies, and servlets g 22@, co%ying an array g ???, +)5B6 g M@MG, cou%ling g HHG, +5+LK g 3LK, createState#ent* , g 23H, critical section, and synchroni1ed block g II?

7
dae#on threads g IGK data g

static initiali1ation g KLL


data ty%e g

eAuivalence to class g LH
database g

Java 7ataBase +onnectivity *J7B+, g 23M, 45D g 23K


7atabaseMeta7ata g 2GL, 7ataElavor g IKK, 7atagra# g 2HG, 7ataIn%ut g 3M3, 7ataIn%utStrea# g 3@2, 3KM, 3KK, 7ata)ut%ut g 3M3, 7ata)ut%utStrea# g 3MM, 3MH, 3KL, deadlock, #ultithreading g I2I, 2@H, death condition, and "inali1e* , g KKK, decorator design %attern g 3@G decou%ling g

via %oly#or%his# g ?2
decou%ling through %oly#or%his# g LKK, decre#ent o%erator g M?3 dee% co%y g M@3@, M@3I

and 6rrayDist g M@G@


de"ault constructor g K@L, K@2

synthesi1ing a de"ault constructor g K2@


de"ault constructor, access the sa#e as the class g G@I, de"ault keyword, in a switch state#ent g M2M, de"ault %ackage g K3G, 7e"aultMutableTreeCode g IML, de"ault5ead)b0ect* , g 3H?, 7e"aultTreeModel g IML, de"ault:rite)b0ect* , g 3H?, 7e#arco, To# g MM?@, deAueue g ?HH derived g

derived class g LK3, derived class, initiali1ing g KI2, ty%es g ?M


design g LHH design g

and inheritance g LHK, and #istakes g KGI, o" ob0ect hierarchies g LMI, %atterns g 2K
design %atterns g KG3, destroy* , g 2@2, destructor g KMH, KMG, HGH destructor g

Java doesn t have one g K2L


develo%#ent, incre#ental g L@M diagra# g

use case g IK
dialog bo& g I@M, dictionary g ?2?, digital signing g GK@ directory g

and %ackages g K3?, creating directories and %aths g 3@@, lister g H2H
dis%ose* , g I@M, division g M?L, do'while g MIM, 7o#ain Ca#e Syste# *7CS, g 2L2, dotted Auad g 2L2, double, literal value #arker *7, g M3?, downcast g L@?, LH3, 32K downcast g

ty%e'sa"e downcast in run'ti#e ty%e identi"ication g 32K


7rawing lines in Swing g G2G, dro%'down list g GI@ dyna#ic g

behavior change with co#%osition g LH?, binding g LKK, LKG


dyna#ic aggregate initiali1ation synta& "or arrays g ?KG

E
early binding g ?I, LKG, editor, creating one using the Swing JTe&tPane g GGH e""iciency g

and arrays g ?KL, and "inal g LM?

114:

elegance, in %rogra##ing g 2L, enca%sulation g KGM, Enter%rise JavaBeans *EJB, g M@KG, Enu#eration g HL2 eAuals* , g M?2, ?2L

and hashed data structures g H@L, overriding "or (ashMa% g H@M, vs. \\ g 3G@
eAuivalence g

\\ g M?I
error g

handling with e&ce%tions g HHM, recovery g H2@, standard error strea# g HHI
event g

event'driven syste# g ?@2, JavaBeans g ILM, res%onding to a Swing event g GLH


event listener g

order o" e&ecution g IK3


event'driven %rogra##ing g GLH, events and listeners g GHM, EventSet7escri%tors g IL2, evolution, in %rogra# develo%#ent g 2@, e&ce%tion g HII e&ce%tion g

changing the %oint o" origin o" the e&ce%tion g H3I, creating your own g HHG, design issues g HIG, Error class g HG@, E&ce%tion class g HG@, e&ce%tion handler g HH3, handler g HHK, handling g K2?, losing an e&ce%tion, %it"all g HGI, restrictions g HG2, s%eci"ication g H3K, ter#ination vs. resu#%tion g HHG, Throwable g H3?, throwing an e&ce%tion g HHL
e&ce%tional condition g HHK e&ce%tions g

and JCI g MMM3


e&ecuteeuery* , g 23H, E&%onential notation g M3?, e&tending a class during inheritance g ?L e&tends g KG@, KII, LHH

and inter"ace g LGK, keyword g KI3


e&tensible g

%rogra# g LLM
E&ternali1able g 3??

alternative a%%roach to using g 3HM


E&tre#e Progra##ing *ZP, g 2L, MMLI

"ail "ast containers g HL?, "alse g MH@, Eeature7escri%tor g I?2, Eield, "or re"lection g G@H, "ields, initiali1ing "ields in inter"aces g LGH, EIE) g ?I2 "ile g

characteristics o" "iles g 3@@


Eile g 3I@ Eile g

class g H2H
"ile dialogs g I@3, Eile Trans"er Protocol *ETP, g GK3, EileIn%ut5eader g 3K@, Eilena#eEilter g 3GI, EileCotEoundE&ce%tion g HI3, Eile5eader g HI?, Eile:riter g 3KK, "illInStackTrace* , g H33, Eilter5eader g 3M? "inal g L3L

and %rivate g LMM, argu#ent g H22, classes g LMK, data g L@H, keyword g L@H, #ethod g LKG, #ethods g LM@, LHK, static %ri#itives g L@G, with ob0ect re"erences g L@H
"inali1e* , g KMH, HIG "inali1e* , g

and inheritance g L?3, calling directly g KMI


"inally g K2?, K23

keyword g HGL, %it"all g HGI


"lat'"ile database g 23G, "lavor, cli%board g IK@, "loat, literal value #arker*E, g M3? "loating %oint g

true and "alse g MHM


ElowDayout g G?K, "lushing out%ut "iles g 3KK, "or keyword g MIM, "orCa#e* , g 32@, GHH, E)5T56C g M3?, "orward re"erencing g KLM, Eowler, Martin g GG, 2M, MMLI, "riendly g KHK, LIK "riendly g

and inter"ace g L3L, less accessible than %rotected g L?I


"unctor g H23

8
garbage collection g KMH, L?H

and native #ethod e&ecution g MMMH, "orcing "inali1ation g K2G, how the collector works g KKL, order o" ob0ect recla#ation g K2G, setting re"erences to null to allow cleanu% g ?MK
generator g ?H2, generator ob0ect, to "ill arrays and containers g ?LM, get* ,, 6rrayDist g ?33, ?GK, get* ,, (ashMa% g ?2I, getBeanIn"o* , g ILH, getBytes* , g 3KM, get+lass* , g H3?, G@M, get+onstructor* , g G33, get+onstructors* , g G@G, get+ontentPane* , g GKK, get+ontents* , g IKK, getEventSet7escri%tors* , g IL2, getEloat* , g 23H, getIn%utStrea#* , g 2?L, getInt* , g 23H, getInter"aces* , g G@K, getMethod7escri%tors* , g IL2, getMethods* , g G@G, getModel* , g IM?, getCa#e* , g G@L, IL2, get)ut%utStrea#* , g 2?L, getPriority* , g 2M@, getPro%erty7escri%tors* , g IL2, getPro%ertyTy%e* , g IL2, get5eadMethod* , g IL2,

115=

getSelectedValues* , g GIK, getState* , g G2?, getString* , g 23H, getSu%erclass* , g G@L, getTrans"er7ata* , g IKK, getTrans"er7ataElavors* , g IKK, get:riteMethod* , g IL2, 8lass, 5obert g MM?@, glue, in Bo&Dayout g G?H goto g

lack o" goto in Java g MIH


gra%hical user inter"ace *84I, g ?@2, GM3, 8ra%hics g G2G, greater than *U, g M?I, greater than or eAual to *U\, g M?I, 8ridBagDayout g G??, 8ridDayout g G?L, 2KG, guarded region, in e&ce%tion handling g HHH, 84I builders g GMG guidelines g

ob0ect develo%#ent g II (
hardware devices, inter"acing with g MM@3, has'a g L2, has'a relationshi%, co#%osition g L@@, hash code g ?2?, H@H, hash "unction g H@H hash+ode* , g ?2@, ?2?

and hashed data structures g H@L, issues when writing g H@2, overriding "or (ashMa% g H@M
hashing g H@L

e&ternal chaining g H@3


(ashMa% g HMI, G3M, (ashSet g HK?, (ashtable g HK2, H?@, hasCe&t* ,, Iterator g ?GL, (e&adeci#al g M3L, high conce%t g I@, (TMD g 2IL (TMD g

na#e g IG@, %ara# g IG@, value g IG@


(TMD on Swing co#%onents g I@I

I
IF) g

co#%ression library g 3L@, in%ut g 3@K, library g H2?, %i%ed strea#s g 3K3, ty%ical IF) con"igurations g 3MG
Icon g G33, I7D g M@M2, idlto0ava g M@KM, i"'else state#ent g MH2, MGI, IllegalMonitorStateE&ce%tion g I22, I#ageIcon g G33, i##utable ob0ects g M@II i#%le#entation g L3

and inter"ace g K22, L3L, hiding g LG, KGM, LIK


i#%le#ents keyword g L3L, i#%ort keyword g KHL, incre#ent o%erator g M?3, inde&ed %ro%erty g I?2, inde&ing o%erator _ ` g KL2 inde&)"* , g

String g G@G
inheritance g ?@, KG@, KIM, KI3, LKK

and "inal g LML, class inheritance diagra#s g L@L, diagra# g H@, "ro# an abstract class g LL2, "ro# inner classes g L22, vs co#%osition g 33G

initial ca%acity, o" a (ashMa% or (ashSet g H@2 initiali1ation g

and class loading g LMH, base class g KI2, initiali1ing with the constructor g M22, o" #ethod variables g KKI, with inheritance g LM3
inline #ethod calls g LM@, inner class g LI@, IL@ inner class g

and Swing g GH@, and u%casting g LIK, hidden re"erence to the ob0ect o" the enclosing class g L2L, identi"iers and .class "iles g ?@K, in #ethods N sco%es g LI?, nesting within any arbitrary sco%e g LI3, re"erring to the outer class ob0ect g L23
In%utStrea# g 2?G, In%utStrea#5eader g 3MK, 2?G, insertCodeInto* , g IM? instance g

instance initiali1ation g L2@, non'static instance initiali1ation g KLI


instance o" a class g LK instanceo" g

dyna#ic instanceo" g 32G, keyword g 32K


Integer g

%arseInt* , g I@3
Integer wra%%er class g K?K inter"ace g

and i#%le#entation, se%aration g KGK, and inheritance g LGM, +loneable inter"ace used as a "lag g M@3K, de"ining the class g 2?, i#%le#entation, se%aration o" g LI, keyword g L3L, %rivate, as nested inter"aces g LG2, u%casting to an inter"ace g L3G, vs. abstract g L32
Inter"ace 7e"inition Danguage *I7D, g M@M2, inter"acing with hardware devices g MM@3, internationali1ation, in IF) library g 3MK Internet g

Internet Protocol g 2L2, Internet Service Provider *ISP, g GK3


Interru%tedE&ce%tion g IHI, intranet g GK@, Intros%ector g ILH, is'a g LHH is'a g

relationshi%, inheritance g L@@, relationshi%, inheritance N u%casting g L@K, vs. is'like'a relationshi%s g ?H
is'like'a g LHH, is7ae#on* , g IGK, is7ataElavorSu%%orted* , g IKK, isInstance g 32G, isInter"ace * , g G@L, iteration, in %rogra# develo%#ent g I2, iterator g ?GK, Iterator g ?GK, ?I@, HMI, iterator* , g ?I@

J
Jacobsen, Ivar g MML2, J6%%let g G?@, J65 g I?G J65 g

1152

"ile g KHH, 0ar "iles and class%ath g KHI


J65 utility g 3LH Java g M@H

and %ointers g M@HL, and set'to% bo&es g MHL, ca%itali1ation style source' code checking tool g 3GM, containers library g ?HH, %ublic Java se#inars g MM, versions g KL
Java M.M g

IF) strea#s g 3MK


Java 6:T g GM3, Java Eoundation +lasses *JE+FSwing, g GM3, Java o%erators g ML2, Java Server Pages *JSP, g 223, Java Virtual Machine g 3I2 JavaBeans g

see Beans g IL@


0avah g MM@I, JButton g G33, J+heckBo& g G33, GGG, J+heckBo&MenuIte# g GI2, J+heckbo&MenuIte#$ g G2?, J+o#boBo& g GI@, J+o#%onent g G32, G2G J7> g

downloading and installing g MKG


JEile+hooser g I@3, JEra#e g GLM, Jini g M@?K JIT g

Just'In Ti#e co#%ilers g M@?


JDabel g GKK, GGK, JDist g GIK, JMenu$ g G2?, JMenuBar g GII, G2H, JMenuIte# g G33, G2H, G2G, JMenuIte#$ g G2?, JCI+6DD g MM@2, JCIEnv g MMMM, JCIEZP)5T g MM@2, 0oin g 23G, J)%tionPane g GIH, JPanel g G?@, G3?, G2G, 2KG, JPo%u%Menu g G2H, JProgressBar g IMM, J5adioButton g G33, GG2, JScrollPane g G?@, GGL, GI?, IM?, JSlider g IMM, JTabbedPane g GI?, JTable g IM?, JTe&t6rea g GLI, IK@, JTe&tEield g GLH, JTe&tEield$ g G32, JTe&tPane g GGH, JToggleButton g G3?, JTree g IMM

>
keyboard navigation, and Swing g GM2, keySet* , g HK2, >oenig, 6ndrew g MMKM

D
label g MI3, labeled break g MI3, labeled continue g MI3, late binding g ?2 layout g

controlling layout with layout #anagers g G?@


la1y ini1iali1ation g KI?, le"t'shi"t o%erator *RR, g MH?, length, "or arrays g ?K?, less than *R, g M?I, less than or eAual to *R\, g M?I library g

creator, vs. client %rogra##er g KHK, design g KHK, use g KHL


DIE) g ?II lightweight g

Swing co#%onents g GMI

linked list g ?HH, DinkedDist g ?I2, HKL, Dist g ?KL, ?HH, ?I?, GIK Dist g

sorting and searching g HK2


listener ada%ters g GHG, listener classes g IL@, listener inter"aces g GH3, Dister, Ti#othy g MM?@ literal g

long g M3?, values g M3L


load "actor, o" a (ashMa% or (ashSet g H@2 loading g

.class "iles g KHG


local loo%back IP address g 2?K localhost g 2?K

and 5MI g M@ML


logical g

o%erator and short'circuiting g MHM, o%erators g MH@


lvalue g M?@

M
#ain* , g KIG, #aintenance, %rogra# g 2@, #anage#ent obstacles g M@@, #ani"est "ile, "or J65 "iles g 3LH, #a% g ?2?, Ma% g ?KL, ?HH, ?2?, HK3, Ma%.Entry g H@L, #ark* , g 3M3, Math. rando#* , g ?2G Math.rando#* , g

values %roduced by g M2?


#athe#atical o%erators g M?L, #a&* , g HLM #e#ber g

#e#ber "unction g L3, ob0ect g L2


#e#ory e&haustion, solution via 5e"erences g HML, #essage bo&, in Swing g GIH, #eta'class g 3I2 #ethod g

adding #ore #ethods to a design g KGI, aliasing during #ethod calls g M?K, looku% tool g GHL, #ethod call binding g LKG, overloading g K@M, %oly#or%hic #ethod call g LKK, %rotected #ethods g L@M, recursive g ?G3, static g KM?
Method g IL2 Method g

"or re"lection g G@H


Method7escri%tors g IL2, #ethodology, analysis and design g G3, Meyers, Scott g LG, Microso"t g IHM, #ission state#ent g I@, #istakes, and design g KGI, #kdirs* , g 3@K, #ne#onics *keyboard shortcuts, g G2?, #odulus g M?L, #onitor, "or #ultithreading g II@, #ulti'tiered syste#s g IKG

1154

#ulticast g I?H

event, and JavaBeans g II3, #ulticast events g IK3


#ultidi#ensional arrays g K??, #ulti%aradig# %rogra##ing g LK, #ulti%le inheritance, in +<< and Java g L3G, #ulti%lication g M?L, #ulti%ly'nested class g L2I, MultiStringMa% g 3GG, #ultitasking g IH3, #ultithreading g 2HM #ultithreading g

and containers g HLL, drawbacks g 2LL, when to use it g 2LK C


na#e g GKH na#e g

clash g KH?, collisions g KH2, s%aces g KH?


na#e collisions when co#bining inter"aces g LG@ Ca#ing g

bind* , g M@ML, rebind* , g M@M?, unbind* , g M@MH


narrowing conversion g M3K, MGG, K@2, native #ethod inter"ace *CMI, in Java M.@ g MM@3, natural logarith#s g M3?, nesting inter"aces g LG3 network %rogra##ing g 2LI

dedicated connection g 2HM, identi"ying #achines g 2L2, serving #ulti%le clients g 2HM, testing %rogra#s without a network g 2?M
new o%erator g KMH

and %ri#itives, array g K?M


newInstance* , g G33 newInstance* , g

re"lection g G@L
ne&t* ,, Iterator g ?GL, ne&tToken* , g 3G2 no'arg g

constructors g K@L
non'Java code, calling g MM@3, Corth, BorderDayout g G?M C)T g

logical *., g MH@


not eAuivalent *.\, g M?I, noti"yDisteners* , g I2@, null g MMK, ?K3, CullPointerE&ce%tion g HGM

)
ob0ect g LK

creation g M22, eAuivalence g M?I, "ive stages o" ob0ect design g IG, inter"ace to g L?, lock, "or #ultithreading g II@, %rocess o" creation g KLH, seriali1ation g 3LG

)b0ect g ?KL

clone* , g M@3H, hash+ode* , g ?2?, standard root class, de"ault inheritance "ro# g KI3, wait* , and noti"y* , #ethods g I22
ob0ect'oriented g

analysis and design g G3


)b0ect)ut%utStrea# g 3LI, )ctal g M3?, )7B+ g 23K, o" g 2M, LMH, L?L, L?2, LHM, )M8 g M@MI, ones co#%le#ent o%erator g MHL, ))P g KGK ))P g

basic characteristics g LK
o%erator g

overloading g M3@, %recedence g M?@, %recedence #ne#onic g M33


)5 g

*]], g MH@
order g

o" initiali1ation g KLM


)ut%utStrea# g 3@H, 2?G, )ut%utStrea#:riter g 2?G over"low g

and %ri#itive ty%es g MGG


overloading g

distinguishing overloaded #ethods g K@L, lack o" na#e hiding during inheritance g K2G, on return values g K@2, o%erator overloading "or String g M@2H
overriding g

"unction g ??, vs. overloading g LLH P


%ackage g KHL

access, and "riendly g K3H, and a%%lets g GKG, creating uniAue %ackage na#es g KH3
%aint+o#%onent* , g G2G, I@H, %air %rogra##ing g 2H, %ara#eter, a%%let g GKH, %ara#eteri1ed ty%e g ?GM %ass g

%ass by value g M@HI


%atterns, design g M@@, %er"ect hashing "unction g H@3, %er"or#ance issues g M@M, Perl %rogra##ing language g GLK, %ersistence g 3HH, Phanto#5e"erence g HML, %i%e g 3@L, %i%ed strea# g 2@M, %lanning, so"tware develo%#ent g G2, Plauger, P.J. g MM?@, Pluggable Dook N Eeel g IMG

1157

%ointer g

Java e&clusion o" %ointers g ?@3


%oly#or%his# g ?G, LKK, LH2, 3I3, GMM %oly#or%his# g

and constructors g L?K, behavior o" %oly#or%hic #ethods inside constructors g L?2
%ort g 2?K, %ortability in +, +<< and Java g M3H, %osition, absolute, when laying out Swing co#%onents g G??, %rereAuisites, "or this book g L@ %ri#itive g

co#%arison g M?2, data ty%es, and use with o%erators g M33, dealing with the i##utability o" %ri#itive wra%%er classes g M@II, "inal g L@H, initiali1ation o" class data #e#bers g KKI, wra%%ers g ?22
%ri#itive ty%es g MM@, %rintIn"o* , g G@L, %rinting arrays g ?LK, %rintStackTrace* , g H3?, H33, Print:riter g 3KK, 3KL, 2?G %riority g

thread g 2M@
%rivate g LI, KHK, K3?, K3I, L@@, II@ %rivate g

inner class g I3H, inner classes g ?ML, #ethod overriding g LLG, #ethods g LHK
%roble# s%ace g LM, L@K, %rocess, and threading g IH3 %rogra##ing g

in the large g 2I, ob0ect'oriented g 3I3


%rogress bar g IM@ %ro#otion g

o" %ri#itive ty%es g MG3, ty%e %ro#otion g M3H


Pro%erties g 3GG, %ro%erty g ILM, Pro%erty+hangeEvent g I?2, Pro%erty7escri%tors g IL2, Pro%tertyVetoE&ce%tion g I?2 %rotected g LI, KHK, K3?, KG@, L@@

and "riendly g L@@, is also "riendly g KGM, use in clone* , g M@3M


%rotocol g L3L

unreliable %rotocol g 2HI


%ublic g LI, KHK, K3?, K33

and inter"ace g L3L, class, and co#%ilation units g KH?


%ure g

substitution g ?H

%ure inheritance, vs. e&tension g LH?, %ure substitution g LHH, %ushBack* , g 3G2, %ut* ,, (ashMa% g ?2I, Python g I3

e
Aueue g ?HH, ?I2

5
567 *5a%id 6%%lication 7evelo%#ent, g G@?, radio button g GG2, 5ando#6ccessEile g 3MH, 3KK, ra%id %rototy%ing g 2K, re'throwing an e&ce%tion g H33, reachable ob0ects and garbage collection g HML, read+har* , g 3KL, read7ouble* , g 3K?, 5eader g 3MK, 3ML, 2@M, 2?G, readE&ternal* , g 3??, reading "ro# standard in%ut g 3K3, readDine* , g HIG, 3KK, 3KL, 3KG read)b0ect* , g 3L2

with Seriali1able g 3HM


recursion, unintended via toString*, g ?GH, redirecting standard IF) g 3KI, re"actoring g 2M re"erence g

eAuivalence vs ob0ect eAuivalence g M?I, "inding e&act ty%e o" a base re"erence g 3II, re"erence eAuivalence vs. ob0ect eAuivalence g M@3H
5e"erence, "ro# 0ava.lang.re" g HML, re"lection g G@?, GHL, ILH re"lection g

and Beans g ILM


re"lection e&a#%le g G3? relational g

database g 23G, o%erators g M?I


reliable %rotocol g 2HI, 5e#ote Method Invocation *5MI, g M@M@, 5e#oteE&ce%tion g M@MG, re#ove6ctionDistener* , g I?K, I2@, re#oveZZZDistener* , g GHM, re#ovingFturning g M@GG, rena#eTo* , g 3@K, reAuest, in ))P g L?, reAuire#ents analysis g I@, reset* , g 3M3, 5esultSet g 23H, resu#e* , g I23 return g

an array g ?KI
reusability g L2 reuse g II

code reuse g KIM, e&isting class libraries g M@@


right'shi"t o%erator *UU, g MH? 5MI g

and +)5B6 g M@KG, 5e#ote g M@M@, re#ote inter"ace g M@M@


r#ic g M@MH, r#iregistry g M@ML, 5MISecurityManager g M@MK, rollover g G3I 5TTI g

and cloning g M@33, di""erence between 5TTI and re"lection g G@3, using the +lass ob0ect g G@M
5u#baugh, Ja#es g MML2, run'ti#e binding g LKG run'ti#e ty%e identi"ication g

115:

*5TTI, g LHG, #isuse g GMM, sha%e e&a#%le g 3IH, when to use it g GMM
runEinali1ers)nE&it* , g L?I, 5unnable g 2KH 5unnable g

inter"ace g I3G
5unti#eE&ce%tion g ?KL, HGM, rvalue g M?@

S
scenario g IM, scheduling g IL sco%e g

use case g 2@
searching an array g ?HK, seek* , g 3MH, 3KH, sending a #essage g L?, se%arating business logic "ro# 4I logic g IK3, Seriali1able g 3??, 3?2, 33K, I?? seriali1ation g

and ob0ect storage g 3HH, controlling the %rocess o" seriali1ation g 3??, 5MI argu#ents g M@MH, to %er"or# dee% co%ying g M@GK
server g 2?M servlet g 2IL

#ultithreading g 2I2
session g

and JSP g M@@H


session tracking, with servlets g 22@, Set g ?KL, ?HH, ?2@, HK?, setBorder* , g GGK, set+ontents* , g IKK, set7ae#on* , g IGK, set7e"ault+lose)%eration* , g GLM, setErr*PrintStrea#, g 3KI, setIcon* , g G3I, setIn*In%utStrea#, g 3KI, setDayout* , g G?@, setMne#onic* , g G2?, set)ut *PrintStrea#, g 3KI, setPriority* , g 2M@, setToolTi%Te&t* , g G32, shallow co%y g M@3@, M@3I sha%e g

e&a#%le g ?M, LKI


shi"t o%erators g MH?, show* , g I@K, show7ocu#ent* , g 2HI, shu""le* , g HLM, side e""ect g ML2, M?G, K@2, M@HG, sign e&tension g MH?, signed two s co#%le#ent g MHI, Si#ula %rogra##ing language g L?, Si#ula'3G g KGK singleton g

design %attern g KG3


Si1e, o" a (ashMa% or (ashSet g H@2, si1e* ,, 6rrayDist g ?33 si1eo"* , g

lack o" in Java g M3H


skeleton, 5MI g M@MH, slee%* , g IHI, IGI, I2H, slider g IM@, S#alltalk g LK, KMH, Socket g 2H@, So"t5e"erence g HML so"tware g

develo%#ent #ethodology g GG
So"tware 7evelo%#ent +on"erence g M@, solution s%ace g LM

sorting g ??G

and searching Dists g HK2


source code co%yright notice g KM, s%eciali1ation g L@@ SeD g

stored %rocedures g 2G@, Structured euery Danguage g 23M


Stack g ?II, H?@, startu% costs g M@M, state+hanged* , g I@@, State#ent g 23H static g L3L

and "inal g L@H, block g KL3, clause g 32@, construction clause g KL3, initiali1ation g LMG, inner classes g L2L, keyword g KM?
sto%* , g

and deadlocks g 2@H, de%recation in Java K g 2@H


strea#'based sockets g 2HG, Strea#Tokeni1er g 33?, 3GI, G@I String g

concatenation with o%erator < g M3@, i##utability g M@2?, inde&)"* , g H2G, le&icogra%hic vs. al%habetic sorting g ?HM, #ethods g M@2G, o%erator < g ?32, )%erator < g M3@, o%erator < and <\ overloading g KIG, toString * , g ?3I
StringBu""er g

#ethods g MM@@
String5eader g 3KM, StringSelection g IKK, StringTokeni1er g 33I, struts, in Bo&Dayout g G?H, stub, 5MI g M@MH, style o" creating classes g KGK, subob0ect g KI2, K2I substitution g

%rinci%le g ?H
subtraction g M?L su%er g K2@

and "inali1e* , g L?I, and inner classes g L22


su%er keyword g KII, su%er.clone* , g M@3M, M@3H, M@IK, su%erclass g KII sus%end* , g I23

de%recation in Java K g 2@G


Swing g GM3, Swing co#%onent e&a#%les g G3K, Swing event #odel g GH@, IK?, switch keyword g M2M synchroni1ed g 3L, II@

and inheritance g I2@, and wait* , N noti"y* , g I2I, containers g HLL, deciding what #ethods to synchroni1e g I2@, e""iciency g IIH, static g II@, synchroni1ed block g II?
syste# cli%board g IM2, syste# s%eci"ication g I@, Syste#.arrayco%y* , g ???, Syste#.err g HHI, Syste#.gc* , g KK@, Syste#.in g 3K@, Syste#.runEinali1ation* , g KK@

117=

T
table g IM? te#%late g

in +<< g ?GM
testing g

auto#ated g 2?, E&tre#e Progra##ing *ZP, g 2L


testing techniAues g L2H, this keyword g KMM Thread g IH3, IHI

co#bined with #ain class g I3H, interru%t* , g 2@3, order o" e&ecution o" threads g I3K, %ro%erly sus%ending N resu#ing g 2@G, run* , g I3@, sharing li#ited resources g IG?, slee%* , g I2K, start* , g I3M, sto%%ing g 2@3, thread grou% g 2MH, thread grou%, de"ault %riority g 2MH, threads and e""iciency g IH2, when they can be sus%ended g IG2
throw keyword g HH?, Throwable g H3I, throwing an e&ce%tion g HH?, ti#e'critical code sections g MM@3, to6rray* , g HK2, Tokeni1ing g 33?, To#cat, standard servlet container g 22H, tool ti%s g G32, TooManyDistenersE&ce%tion g I?H, toString* , g KIL, ?G?, HMI training g 22

and #entoring g M@M, M@K


training se#inars %rovided by Bruce Eckel g K?, Trans"erable g IKK, transient keyword g 3?2, translation unit g KH?, Trans#ission +ontrol Protocol *T+P, g 2HG, tree g IMM, TreeMa% g HK2, 33G, TreeSet g HK?, try g K23, HGH try g

try block in e&ce%tions g HHH


ty%e g

ty%e checking and arrays g ?KL, ty%e sa"ety in Java g M3M


T/PE "ield, "or %ri#itive class literals g 32M, ty%e sa"e sets o" constants g LGH, ty%e'conscious 6rrayDist g ?G@, ty%ical g HI2

4
4MD g I3 4MD g

indicating co#%osition g L2
unary g

#inus *', g M?H, o%erator g MHL, o%erators g M?H, %lus *<, g M?H
unicast g I?H, 4nicast5e#ote)b0ect g M@MM, 4nicode g 3MK, 4ni"ied Modeling Danguage *4MD, g L3, MMLI, unit testing g KIG, un#odi"iable, #aking a +ollection or Ma% un#odi"iable g HLK, unsu%%orted #ethods, in the Java K containers g HLH, u%casting g H@, L@K, LKL, 3I3 u%casting g

and inter"ace g L33

u%dates o" the book g KL, 45D g 2H2 use case g IM

iteration g I2
4ser 7atagra# Protocol *47P, g 2HI user inter"ace g IL

and threads, "or res%onsiveness g I3K, res%onsive, with threading g IHG V


variable g

de"ining a variable g MIK, variable argu#ent lists *unknown Auantity and ty%e o" argu#ents, g K??
Vector g HKL, HLI, H?@, versioning, seriali1ation g 3HH, visibility, %ackage visibility, *"riendly, g LIK visual g

%rogra##ing g ILM :
wait* , g I2I, :aldro%, M. Mitchell g MM?@ weak g

weakly ty%ed language g ?2


:eak(ashMa% g HM3, :eak5e"erence g HML :eb g

dis%laying a :eb %age "ro# within an a%%let g 2HI, sa"ety, and a%%let restrictions g GM2
web o" ob0ects g 3L2, M@3@, while g MI@, widening conversion g M3K, wild'card g GI, :indow6da%ter g GLM, window+losing* , g GLM, I@M, windowed a%%lications g GKG, :indows E&%lorer, running Java %rogra#s "ro# g GLK, writeBytes* , g 3KL, write7ouble* , g 3K?, writeE&ternal* , g 3?? write)b0ect* , g 3L2

with Seriali1able g 3HM


:riter g 3MK, 2@M, 2?G

/
yield* , g I2L

Q
1ero e&tension g MH?, Qi%Entry g 3L?

1172

/nd@Cser &icense Agreement for Microsoft 1oftware IM O$#A2#@$/AD CA$/<C&&G: #his Microsoft /nd@Cser &icense Agreement 8B/C&AB9 is a legal agreement between :ou 8either an individual or a single entit:9 and Microsoft Cor.oration for the Microsoft software .roduct included in this .ackageH which includes com.uter software and ma: include associated mediaH .rinted materialsH and BonlineB or electronic documentation 8B1O<#WA$/ $ODCC#B9) #he 1O<#WA$/ $ODCC# also includes an: u.dates and su..lements to the original 1O<#WA$/ $ODCC# .rovided to :ou b: Microsoft) ;: installingH co.:ingH downloadingH accessing or otherwise using the 1O<#WA$/ $ODCC#H :ou agree to be bound b: the terms of this /C&A) If :ou do not agree to the terms of this /C&AH do not installH co.:H or otherwise use the 1O<#WA$/ $ODCC#) 1O<#WA$/ $ODCC# &IC/21/ #he 1O<#WA$/ $ODCC# is .rotected b: co.:right laws and international co.:right treatiesH as well as other intellectual .ro.ert: laws and treaties) #he 1O<#WA$/ $ODCC# is licensedH not sold) () '$A2# O< &IC/21/) #his /C&A grants :ou the following rights: ()( &icense 'rant) Microsoft grants to :ou as an individualH a .ersonal none0clusive license to make and use co.ies of the 1O<#WA$/ $ODCC# for the sole .ur.oses of evaluating and learning how to use the 1O<#WA$/ $ODCC#H as ma: be instructed in accom.an:ing .ublications or documentation) Gou ma: install the software on an unlimited number of com.uters .rovided that :ou are the onl: individual using the 1O<#WA$/ $ODCC#) ()! Academic Cse) Gou must be a BRualified /ducational CserB to use the 1O<#WA$/ $ODCC# in the manner described in this section) #o determine whether :ou are a Rualified /ducational CserH .lease contact the Microsoft 1ales Information CenterDOne Microsoft Wa:D$edmondH WA 657,!@-*66 or the Microsoft subsidiar: serving :our countr:) If :ou are a Rualified /ducational CserH :ou ma: either: 8i9 e0ercise the rights granted in 1ection ()(H O$ 8ii9 if :ou intend to use the 1O<#WA$/ $ODCC# solel: for instructional .ur.oses in connection with a class or other educational .rogramH this /C&A grants :ou the following alternative license models: 8A9 er Com.uter Model) <or ever: valid license :ou have ac%uired for the 1O<#WA$/ $ODCC#H :ou ma: install a single co.: of the 1O<#WA$/

$ODCC# on a single com.uter for access and use b: an unlimited number of student end users at :our educational institutionH .rovided that all such end users com.l: with all other terms of this /C&AH O$ 8;9 er &icense Model) If :ou have multi.le licenses for the 1O<#WA$/ $ODCC#H then at an: time :ou ma: have as man: co.ies of the 1O<#WA$/ $ODCC# in use as :ou have licensesH .rovided that such use is limited to student or facult: end users at :our educational institution and .rovided that all such end users com.l: with all other terms of this /C&A) <or .ur.oses of this subsectionH the 1O<#WA$/ $ODCC# is Bin useB on a com.uter when it is loaded into the tem.orar: memor: 8i)e)H $AM9 or installed into the .ermanent memor: 8e)g)H hard diskH CD $OMH or other storage device9 of that com.uterH e0ce.t that a co.: installed on a network server for the sole .ur.ose of distribution to other com.uters is not Bin useB) If the antici.ated number of users of the 1O<#WA$/ $ODCC# will e0ceed the number of a..licable licensesH then :ou must have a reasonable mechanism or .rocess in .lace to ensure that the number of .ersons using the 1O<#WA$/ $ODCC# concurrentl: does not e0ceed the number of licenses) !) D/1C$I #IO2 O< O#>/$ $I'>#1 A2D &IMI#A#IO21) T &imitations on $everse /ngineeringH Decom.ilationH and Disassembl:) Gou ma: not reverse engineerH decom.ileH or disassemble the 1O<#WA$/ $ODCC#H e0ce.t and onl: to the e0tent that such activit: is e0.ressl: .ermitted b: a..licable law notwithstanding this limitation) T 1e.aration of Com.onents) #he 1O<#WA$/ $ODCC# is licensed as a single .roduct) Its com.onent .arts ma: not be se.arated for use on more than one com.uter) T $ental) Gou ma: not rentH lease or lend the 1O<#WA$/ $ODCC#) T #rademarks) #his /C&A does not grant :ou an: rights in connection with an: trademarks or service marks of Microsoft) T 1oftware #ransfer) #he initial user of the 1O<#WA$/ $ODCC# ma: make a one@time .ermanent transfer of this /C&A and 1O<#WA$/ $ODCC# onl: directl: to an end user) #his transfer must include all of the 1O<#WA$/ $ODCC# 8including all com.onent .artsH the media and .rinted materialsH an: u.gradesH this /C&AH andH if a..licableH the Certificate of Authenticit:9) 1uch transfer ma: not be b: wa: of consignment or an: other indirect transfer) #he transferee of such one@time transfer must agree to com.l: with the terms of this /C&AH including the obligation not to further transfer this /C&A and 1O<#WA$/ $ODCC#) T 2o 1u..ort) Microsoft shall have no obligation to .rovide an: .roduct su..ort for the 1O<#WA$/ $ODCC#) T #ermination) Without .re3udice to an: other rightsH Microsoft ma: terminate this /C&A if :ou fail to com.l: with the terms and conditions of this /C&A) In

such eventH :ou must destro: all co.ies of the 1O<#WA$/ $ODCC# and all of its com.onent .arts) *) CO G$I'>#) All title and intellectual .ro.ert: rights in and to the 1O<#WA$/ $ODCC# 8including but not limited to an: imagesH .hotogra.hsH animationsH videoH audioH musicH te0tH and Ba..letsB incor.orated into the 1O<#WA$/ $ODCC#9H the accom.an:ing .rinted materialsH and an: co.ies of the 1O<#WA$/ $ODCC# are owned b: Microsoft or its su..liers) All title and intellectual .ro.ert: rights in and to the content which ma: be accessed through use of the 1O<#WA$/ $ODCC# is the .ro.ert: of the res.ective content owner and ma: be .rotected b: a..licable co.:right or other intellectual .ro.ert: laws and treaties) #his /C&A grants :ou no rights to use such content) All rights not e0.ressl: granted are reserved b: Microsoft) +) ;ACUC CO G) After installation of one co.: of the 1O<#WA$/ $ODCC# .ursuant to this /C&AH :ou ma: kee. the original media on which the 1O<#WA$/ $ODCC# was .rovided b: Microsoft solel: for backu. or archival .ur.oses) If the original media is re%uired to use the 1O<#WA$/ $ODCC# on the COM C#/$H :ou ma: make one co.: of the 1O<#WA$/ $ODCC# solel: for backu. or archival .ur.oses) /0ce.t as e0.ressl: .rovided in this /C&AH :ou ma: not otherwise make co.ies of the 1O<#WA$/ $ODCC# or the .rinted materials accom.an:ing the 1O<#WA$/ $ODCC#) ,) C)1) 'O=/$2M/2# $/1#$IC#/D $I'>#1) #he 1O<#WA$/ $ODCC# and documentation are .rovided with $/1#$IC#/D $I'>#1) CseH du.licationH or disclosure b: the 'overnment is sub3ect to restrictions as set forth in sub.aragra.h 8c98(98ii9 of the $ights in #echnical Data and Com.uter 1oftware clause at D<A$1 !,!)!!4@47(* or sub.aragra.hs 8c98(9 and 8!9 of the Commercial Com.uter 1oftware@$estricted $ights at +5 C<$ ,!)!!4@(6H as a..licable) Manufacturer is Microsoft Cor.orationDOne Microsoft Wa:D $edmondH WA 657,!@-*66) -) /E O$# $/1#$IC#IO21) Gou agree that :ou will not e0.ort or re@e0.ort the 1O<#WA$/ $ODCC#H an: .art thereofH or an: .rocess or service that is the direct .roduct of the 1O<#WA$/ $ODCC# 8the foregoing collectivel: referred to as the B$estricted Com.onentsB9H to an: countr:H .ersonH entit: or end user sub3ect to C)1) e0.ort restrictions) Gou s.ecificall: agree not to e0.ort or re@ e0.ort an: of the $estricted Com.onents 8i9 to an: countr: to which the C)1) has embargoed or restricted the e0.ort of goods or servicesH which currentl: includeH but are not necessaril: limited to CubaH IranH Ira%H &ib:aH 2orth UoreaH 1udan and 1:riaH or to an: national of an: such countr:H wherever locatedH who intends to transmit or trans.ort the $estricted Com.onents back to such countr:M 8ii9 to an: end@user who :ou know or have reason to know will utili?e the $estricted Com.onents in the designH develo.ment or .roduction of nuclearH chemical or biological wea.onsM or 8iii9 to an: end@user who has been

.rohibited from .artici.ating in C)1) e0.ort transactions b: an: federal agenc: of the C)1) government) Gou warrant and re.resent that neither the ;EA nor an: other C)1) federal agenc: has sus.endedH revokedH or denied :our e0.ort .rivileges) 4) 2O#/ O2 "A=A 1C O$#) #>/ 1O<#WA$/ $ODCC# MAG CO2#AI2 1C O$# <O$ $O'$AM1 W$I##/2 I2 "A=A) "A=A #/C>2O&O'G I1 2O# <AC&# #O&/$A2# A2D I1 2O# D/1I'2/DH MA2C<AC#C$/DH O$ I2#/2D/D <O$ C1/ O$ $/1A&/ A1 O2@&I2/ CO2#$O& /RCI M/2# I2 >AQA$DOC1 /2=I$O2M/2#1 $/RCI$I2' <AI&@1A</ /$<O$MA2C/H 1CC> A1 I2 #>/ O /$A#IO2 O< 2CC&/A$ <ACI&I#I/1H AI$C$A<# 2A=I'A#IO2 O$ COMMC2ICA#IO2 1G1#/M1H AI$ #$A<<IC CO2#$O&H DI$/C# &I</ 1C O$# MAC>I2/1H O$ W/A O21 1G1#/M1H I2 W>IC> #>/ <AI&C$/ O< "A=A #/C>2O&O'G COC&D &/AD DI$/C#&G #O D/A#>H /$1O2A& I2"C$GH O$ 1/=/$/ >G1ICA& O$ /2=I$O2M/2#A& DAMA'/) MI1C/&&A2/OC1 If :ou ac%uired this .roduct in the Cnited 1tatesH this /C&A is governed b: the laws of the 1tate of Washington) If :ou ac%uired this .roduct in CanadaH this /C&A is governed b: the laws of the rovince of OntarioH Canada) /ach of the .arties hereto irrevocabl: attorns to the 3urisdiction of the courts of the rovince of Ontario and further agrees to commence an: litigation which ma: arise hereunder in the courts located in the "udicial District of GorkH rovince of Ontario) If this .roduct was ac%uired outside the Cnited 1tatesH then local law ma: a..l:) 1hould :ou have an: %uestions concerning this /C&AH or if :ou desire to contact Microsoft for an: reasonH .lease contact MicrosoftH or write: Microsoft 1ales Information CenterDOne Microsoft Wa:D $edmondH WA 657,!@-*66) &IMI#/D WA$$A2#G &IMI#/D WA$$A2#G) Microsoft warrants that 8a9 the 1O<#WA$/ $ODCC# will .erform substantiall: in accordance with the accom.an:ing written materials for a .eriod of ninet: 8679 da:s from the date of recei.tH and 8b9 an: 1u..ort 1ervices .rovided b: Microsoft shall be substantiall: as described in a..licable written materials .rovided to :ou b: MicrosoftH and Microsoft su..ort engineers will make commerciall: reasonable efforts to solve an: .roblem) #o the e0tent allowed b: a..licable lawH im.lied warranties on the 1O<#WA$/ $ODCC#H if an:H are limited to ninet: 8679 da:s) 1ome statesD3urisdictions do

not allow limitations on duration of an im.lied warrant:H so the above limitation ma: not a..l: to :ou) CC1#OM/$ $/M/DI/1) MicrosoftVs and its su..liersV entire liabilit: and :our e0clusive remed: shall beH at MicrosoftVs o.tionH either 8a9 return of the .rice .aidH if an:H or 8b9 re.air or re.lacement of the 1O<#WA$/ $ODCC# that does not meet MicrosoftVs &imited Warrant: and that is returned to Microsoft with a co.: of :our recei.t) #his &imited Warrant: is void if failure of the 1O<#WA$/ $ODCC# has resulted from accidentH abuseH or misa..lication) An: re.lacement 1O<#WA$/ $ODCC# will be warranted for the remainder of the original warrant: .eriod or thirt: 8*79 da:sH whichever is longer) Outside the Cnited 1tatesH neither these remedies nor an: .roduct su..ort services offered b: Microsoft are available without .roof of .urchase from an authori?ed international source) 2O O#>/$ WA$$A2#I/1) #O #>/ MAEIMCM /E#/2# /$MI##/D ;G A &ICA;&/ &AWH MIC$O1O<# A2D I#1 1C &I/$1 DI1C&AIM A&& O#>/$ WA$$A2#I/1 A2D CO2DI#IO21H /I#>/$ /E $/11 O$ IM &I/DH I2C&CDI2'H ;C# 2O# &IMI#/D #OH IM &I/D WA$$A2#I/1 O$ CO2DI#IO21 O< M/$C>A2#A;I&I#GH <I#2/11 <O$ A A$#ICC&A$ C$ O1/H #I#&/ A2D 2O2@ I2<$I2'/M/2#H WI#> $/'A$D #O #>/ 1O<#WA$/ $ODCC#H A2D #>/ $O=I1IO2 O< O$ <AI&C$/ #O $O=ID/ 1C O$# 1/$=IC/1) #>I1 &IMI#/D WA$$A2#G 'I=/1 GOC 1 /CI<IC &/'A& $I'>#1) GOC MAG >A=/ O#>/$1H W>IC> =A$G <$OM 1#A#/D"C$I1DIC#IO2 #O 1#A#/D"C$I1DIC#IO2) &IMI#A#IO2 O< &IA;I&I#G) #O #>/ MAEIMCM /E#/2# /$MI##/D ;G A &ICA;&/ &AWH I2 2O /=/2# 1>A&& MIC$O1O<# O$ I#1 1C &I/$1 ;/ &IA;&/ <O$ A2G 1 /CIA&H I2CID/2#A&H I2DI$/C#H O$ CO21/RC/2#IA& DAMA'/1 W>A#1O/=/$ 8I2C&CDI2'H WI#>OC# &IMI#A#IO2H DAMA'/1 <O$ &O11 O< ;C1I2/11 $O<I#1H ;C1I2/11 I2#/$$C #IO2H &O11 O< ;C1I2/11 I2<O$MA#IO2H O$ A2G O#>/$ /CC2IA$G &O119 A$I1I2' OC# O< #>/ C1/ O< O$ I2A;I&I#G #O C1/ #>/ 1O<#WA$/ $ODCC# O$ #>/ <AI&C$/ #O $O=ID/ 1C O$# 1/$=IC/1H /=/2 I< MIC$O1O<# >A1 ;//2 AD=I1/D O< #>/ O11I;I&I#G O< 1CC> DAMA'/1) I2 A2G CA1/H MIC$O1O<#V1 /2#I$/ &IA;I&I#G C2D/$ A2G $O=I1IO2 O< #>I1 /C&A 1>A&& ;/ &IMI#/D #O #>/ '$/A#/$ O< #>/ AMOC2# AC#CA&&G AID ;G GOC <O$ #>/ 1O<#WA$/ $ODCC# O$ C)1)W,)77M $O=ID/DH >OW/=/$H I< GOC >A=/ /2#/$/D I2#O A MIC$O1O<# 1C O$# 1/$=IC/1 A'$//M/2#H MIC$O1O<#V1 /2#I$/ &IA;I&I#G $/'A$DI2' 1C O$# 1/$=IC/1 1>A&& ;/ 'O=/$2/D ;G #>/ #/$M1 O< #>A# A'$//M/2#) ;/CAC1/ 1OM/ 1#A#/1D"C$I1DIC#IO21 DO 2O# A&&OW #>/ /EC&C1IO2 O$ &IMI#A#IO2 O< &IA;I&I#GH #>/ A;O=/ &IMI#A#IO2 MAG 2O# A &G #O GOC) 7+6, art 2o) -+*,5

&IC/21/ A'$//M/2# <O$ Mind=iewH Inc)Vs #hinking in C: <oundations for "ava L CFF CD $OM b: Chuck Allison #his CD is .rovided together with the book B#hinking in "avaH !nd edition)B $/AD #>I1 A'$//M/2# ;/<O$/ C1I2' #>I1 B#hinking in C: <oundations for CFF L "avaB 8>ereafter called BCDB9) ;G C1I2' #>/ CD GOC A'$// #O ;/ ;OC2D ;G #>/ #/$M1 A2D CO2DI#IO21 O< #>I1 A'$//M/2#) I< GOC DO 2O# A'$// #O #>/ #/$M1 A2D CO2DI#IO21 O< #>I1 A'$//M/2#H IMM/DIA#/&G $/#C$2 #>/ C2C1/D CD <O$ A <C&& $/<C2D O< MO2I/1 AIDH I< A2G) X!777 Mind=iewH Inc) All rights reserved) rinted in the C)1) 1O<#WA$/ $/RCI$/M/2#1 #he .ur.ose of this CD is to .rovide the ContentH not the associated software necessar: to view the Content) #he Content of this CD is in >#M& for viewing with Microsoft Internet /0.lorer + or newerH and uses Microsoft 1ound Codecs available in MicrosoftVs Windows Media la:er for Windows) It is :our res.onsibilit: to correctl: install the a..ro.riate Microsoft software for :our s:stem) #he te0tH imagesH and other media included on this CD 8BContentB9 and their com.ilation are licensed to :ou sub3ect to the terms and conditions of this Agreement b: Mind=iewH Inc)H having a .lace of business at ,*+* =alle =istaH &a MesaH CA 6(6+() Gour rights to use other .rograms and materials included on the CD are also governed b: se.arate agreements distributed with those .rograms and materials on the CD 8the BOther AgreementsB9) In the event of an: inconsistenc: between this Agreement and the Other AgreementsH this Agreement shall govern) ;: using this CDH :ou agree to be bound b: the terms and conditions of this Agreement) Mind=iewH Inc) owns title to the Content and to all intellectual .ro.ert: rights thereinH e0ce.t insofar as it contains materials that are .ro.rietar: to third@.art: su..liers) All rights in the Content e0ce.t those e0.ressl: granted to :ou in this Agreement are reserved to Mind=iewH Inc) and such su..liers as their res.ective interests ma: a..ear) () &IMI#/D &IC/21/ Mind=iewH Inc) grants :ou a limitedH none0clusiveH nontransferable license to use the Content on a single dedicated com.uter 8e0cluding network servers9) #his Agreement and :our rights hereunder shall automaticall: terminate if :ou fail to com.l: with an: .rovisions of this Agreement or an: of the Other

Agreements) C.on such terminationH :ou agree to destro: the CD and all co.ies of the CDH whether lawful or notH that are in :our .ossession or under :our control) !) ADDI#IO2A& $/1#$IC#IO21 a) Gou shall not 8and shall not .ermit other .ersons or entities to9 directl: or indirectl:H b: electronic or other meansH re.roduce 8e0ce.t for archival .ur.oses as .ermitted b: law9H .ublishH distributeH rentH leaseH sellH sublicenseH assignH or otherwise transfer the Content or an: .art thereof) b) Gou shall not 8and shall not .ermit other .ersons or entities to9 use the Content or an: .art thereof for an: commercial .ur.ose or mergeH modif:H create derivative works ofH or translate the Content) c) Gou shall not 8and shall not .ermit other .ersons or entities to9 obscure Mind=iewVs or its su..liers co.:rightH trademarkH or other .ro.rietar: notices or legends from an: .ortion of the Content or an: related materials) *) /$MI11IO21 a) /0ce.t as noted in the Contents of the CDH :ou must treat this software 3ust like a book) >oweverH :ou ma: co.: it onto a com.uter to be used and :ou ma: make archival co.ies of the software for the sole .ur.ose of backing u. the software and .rotecting :our investment from loss) ;: sa:ingH B3ust like a bookHB Mind=iewH Inc) meansH for e0am.leH that this software ma: be used b: an: number of .eo.le and ma: be freel: moved from one com.uter location to anotherH so long as there is no .ossibilit: of its being used at one location or on one com.uter while it is being used at another) "ust as a book cannot be read b: two different .eo.le in two different .laces at the same timeH neither can the software be used b: two different .eo.le in two different .laces at the same time) b) Gou ma: show or demonstrate the un@modified Content in a live .resentationH live seminarH or live .erformance as long as :ou attribute all material of the Content to Mind=iewH Inc) c) Other .ermissions and grants of rights for use of the CD must be obtained directl: from Mind=iewH Inc) at htt.:DDwww)Mind=iew)net) 8;ulk co.ies of the CD ma: also be .urchased at this site)9 DI1C&AIM/$ O< WA$$A2#G #he Content and CD are .rovided BA1 I1B without warrant: of an: kindH either e0.ress or im.liedH includingH without limitationH an: warrant: of

merchantabilit: and fitness for a .articular .ur.ose) #he entire risk as to the results and .erformance of the CD and Content is assumed b: :ou) Mind=iewH Inc) and its su..liers assume no res.onsibilit: for defects in the CDH the accurac: of the ContentH or omissions in the CD or the Content) Mind=iewH Inc) and its su..liers do not warrantH guaranteeH or make an: re.resentations regarding the useH or the results of the useH of the .roduct in terms of correctnessH accurac:H reliabilit:H currentnessH or otherwiseH or that the Content will meet :our needsH or that o.eration of the CD will be uninterru.ted or error@freeH or that an: defects in the CD or Content will be corrected) Mind=iewH Inc) and its su..liers shall not be liable for an: lossH damagesH or costs arising from the use of the CD or the inter.retation of the Content) 1ome states do not allow e0clusion or limitation of im.lied warranties or limitation of liabilit: for incidental or conse%uential damagesH so all of the above limitations or e0clusions ma: not a..l: to :ou) In no event shall Mind=iewH Inc) or its su..liersV total liabilit: to :ou for all damagesH lossesH and causes of action 8whether in contractH tortH or otherwise9 e0ceed the amount .aid b: :ou for the CD) Mind=iewH Inc)H and rentice@>allH Inc) s.ecificall: disclaim the im.lied warrantees of merchantabilit: and fitness for a .articular .ur.ose) 2o oral or written information or advice given b: Mind=iewH Inc)H rentice@>allH Inc)H their dealersH distributorsH agents or em.lo:ees shall create a warrantee) Gou ma: have other rightsH which var: from state to state) 2either Mind=iewH Inc)H ;ruce /ckelH Chuck AllisonH rentice@>allH nor an:one else who has been involved in the creationH .roduction or deliver: of the .roduct shall be liable for an: directH indirectH conse%uentialH or incidental damages 8including damages for loss of business .rofitsH business interru.tionH loss of business informationH and the like9 arising out of the use of or inabilit: to use the .roduct even if Mind=iewH Inc)H has been advised of the .ossibilit: of such damages) ;ecause some states do not allow the e0clusion or limitation of liabilit: for conse%uential or incidental damagesH the above limitation ma: not a..l: to :ou) #his CD is .rovided as a su..lement to the book B#hinking in "ava !nd edition)B #he sole res.onsibilit: of rentice@>all will be to .rovide a re.lacement CD in the event that the one that came with the book is defective) #his re.lacement warrantee shall be in effect for a .eriod of si0t: da:s from the .urchase date) Mind=iewH Inc) does not bear an: additional res.onsibilit: for the CD) 2O #/C>2ICA& 1C O$# I1 $O=ID/D WI#> #>I1 CD $OM #he following are trademarks of their res.ective com.anies in the C)1) and ma: be .rotected as trademarks in other countries: 1un and the 1un &ogoH

1un Micros:stemsH "avaH all "ava@based names and logos and the "ava Coffee Cu. are trademarks of 1un Micros:stemsM Internet /0.lorerH the Windows Media la:erH DO1H Windows 6,H and Windows 2# are trademarks of Microsoft)

&hinking in $: 6oundations !or Java ; $<<


Multimedia 1eminar@on@CD $OM
JK@@@ MindView, Inc. 6ll rights reserved. 0A$/I/"< 2&F.$& .#&/I/" TH& I)- #A-%A"&, -A$&FU++: $&A TH& T&$1) A/ -./ ITI./) .F TH& +I-&/)& A"$&&1&/T , 0A$A/T&& +I1ITATI./ ./ TH& #$&VI.U) #A"&)! The +7 5)M %ackaged with this book is a #ulti#edia se#inar consisting o" synchroni1ed slides and audio lectures. The goal o" this se#inar is to introduce you to the as%ects o" + that are necessary "or you to #ove on to +<< or Java, leaving out the un%leasant %arts that + %rogra##ers #ust deal with on a day'to'day basis but that the +<< and Java languages steer you away "ro#. The +7 also contains this book in (TMD "or# along with the source code "or the book. This +7 5)M will work with :indows *with a sound syste#,. (owever, you #ust=

M. Install the #ost recent version o" Microso"t s Internet E&%lorer. Because o" the "eatures %rovided on the +7, it will C)T work with Cetsca%e Cavigator. The Internet &4plorer soft(are for 0in'o(s ?X5/T is incl*'e' on the - ! K. Install Microso"t s Bindo,s Media Pla)er. The 1e'ia #layer soft(are for 0in'o(s ?X5/T is incl*'e' on the - ! /ou can also go to http<55(((!microsoft! com5(in'o(s5me'iaplayer and "ollow the instructions or links there to download and install the Media Player "or your %articular %lat"or#. L. 6t this %oint you should be able to %lay the lectures on the +7. 4sing the Internet E&%lorer :eb browser, o%en the "ile Install!html that you ll "ind on the +7. This will introduce you to the +7 and %rovide "urther instructions about the use o" the +7.

Das könnte Ihnen auch gefallen