100% found this document useful (2 votes)
1K views

Head First Java 2nd Edition

Uploaded by

weipanda
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (2 votes)
1K views

Head First Java 2nd Edition

Uploaded by

weipanda
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 690

:PVS#SBJOPO+BWB‰"-FBSOFST(VJEF

ND%DITION #OVERS*AVA

-FBSOIPXUISFBET
DBODIBOHFZPVSMJGF )FBE'JSTU
+BWB .BLF+BWBDPODFQUT
TUJDLUPZPVSCSBJO

'PPMBSPVOEJO
UIF+BWB-JCSBSZ

"WPJEFNCBSBTTJOH
00NJTUBLFT

#FOEZPVSNJOE
BSPVOE
+BWBQV[[MFT

.BLFBUUSBDUJWF
BOEVTFGVM(6*T

,BUIZ4JFSSB#FSU#BUFT
Table of Contents (summary)
Intro xxi
1 Breaking the Surface: a quick dip 1
2 A Trip to Objectville: yes, there will be objects 27
3 Know Your Variables: primitives and references 49
4 How Objects Behave: object state affects method behavior 71
5 Extra-Strength Methods: flow control, operations, and more 95
6 Using the Java Library: so you don’t have to write it all yourself 125
7 Better Living in Objectville: planning for the future 165
8 Serious Polymorphism: exploiting abstract classes and interfaces 197
9 Life and Death of an Object: constructors and memory management 235
10 Numbers Matter: math, formatting, wrappers, and statics 273
11 Risky Behavior: exception handling 315
12 A Very Graphic Story: intro to GUI, event handling, and inner classes 353
13 Work on Your Swing: layout managers and components 399
14 Saving Objects: serialization and I/O 429
15 Make a Connection: networking sockets and multithreading 471
16 Data Structures: collections and generics 529
17 Release Your Code: packaging and deployment 581
18 Distributed Computing: RMI with a dash of servlets, EJB, and Jini 607
A Appendix A: Final code kitchen 649
B Appendix B: Top Ten Things that didn’t make it into the rest of the book 659
Index 677

Table of Contents (the full version)

i Intro
Your brain on Java. (EREYOUARETRYINGTOLEARNSOMETHING WHILEHEREYOURBRAIN
ISDOINGYOUAFAVORBYMAKINGSURETHELEARNINGDOESNTSTICK9OURBRAINSTHINKING h"ETTER
LEAVEROOMFORMOREIMPORTANTTHINGS LIKEWHICHWILDANIMALSTOAVOIDANDWHETHERNAKED
SNOWBOARDINGISABADIDEAv3OHOWDOYOUTRICKYOURBRAININTOTHINKINGTHATYOURLIFE
DEPENDSONKNOWING*AVA

Who is this book for? xxii


What your brain is thinking xxiii
Metacognition xxv
Bend your brain into submission xxvii
What you need for this book xxviii
Technical editors xxx
Acknowledgements xxxi

ix
1 Breaking the Surface
Java takes you to new places. &ROMITSHUMBLERELEASETOTHEPUBLICASTHE
WIMPY VERSION *AVASEDUCEDPROGRAMMERSWITHITSFRIENDLYSYNTAX OBJECT ORIENTED
FEATURES MEMORYMANAGEMENT ANDBESTOFALLˆTHEPROMISEOFPORTABILITY7ELLTAKEAQUICK
DIPANDWRITESOMECODE COMPILEIT ANDRUNIT7ERETALKINGSYNTAX LOOPS BRANCHING ANDWHAT
MAKES*AVASOCOOL$IVEIN

The way Java works 2


Virtual Code structure in Java 7
Machines
Anatomy of a class 8
The main() method 9
Method Party() Looping 11
0 aload_0
Conditional branching (if tests) 13
1 invokespe-
cial #1 <Method Coding the “99 bottles of beer” app 14
java.lang.Object()>
Phrase-o-matic 16
4 return
Fireside chat: compiler vs. JVM 18
Compiled You Bet
Shoot Me

Exercises and puzzles 20


bytecode

2 A Trip to Objectville
I was told there would be objects. )N#HAPTER WEPUTALLOFOURCODE
INTHEMAIN METHOD4HATSNOTEXACTLYOBJECT ORIENTED3ONOWWEVEGOTTOLEAVETHAT
PROCEDURALWORLDBEHINDANDSTARTMAKINGSOMEOBJECTSOFOUROWN7ELLLOOKATWHAT
MAKESOBJECT ORIENTED// DEVELOPMENTIN*AVASOMUCHFUN7ELLLOOKATTHEDIFFERENCE
BETWEENACLASSANDANOBJECT7ELLLOOKATHOWOBJECTSCANIMPROVEYOURLIFE

Chair Wars (Brad the OO guy vs. Larry the procedural guy) 28
Inheritance (an introduction) 31
Overriding methods (an introduction) 32
What’s in a class? (methods, instance variables) 34
Making your first object 36
Using main() 38
Guessing Game code 39
Exercises and puzzles 42

x
3 Know Your Variables
Variables come in two flavors: primitive and reference.
4HERESGOTTABEMORETOLIFETHANINTEGERS 3TRINGS ANDARRAYS7HATIFYOUHAVEA0ET/WNER
OBJECTWITHA$OGINSTANCEVARIABLE/RA#ARWITHAN%NGINE)NTHISCHAPTERWELLUNWRAP
THEMYSTERIESOF*AVATYPESANDLOOKATWHATYOUCANDECLAREASAVARIABLE WHATYOUCANPUT
INAVARIABLE ANDWHATYOUCANDOWITHAVARIABLE!NDWELLFINALLYSEEWHATLIFEISTRULYLIKE
ONTHEGARBAGE COLLECTIBLEHEAP

Declaring a variable (Java cares about type) 50


24
size Primitive types (“I’d like a double with extra foam, please”) 51
Java keywords 53
int
Reference variables (remote control to an object) 54
ct Object declaration and assignment 55
Dog obje
Objects on the garbage-collectible heap 57
fido Arrays (a first look) 59
Exercises and puzzles 63
Dog reference

4 How Objects Behave


State affects behavior, behavior affects state. 7EKNOWTHATOBJECTS
HAVESTATEANDBEHAVIOR REPRESENTEDBYINSTANCEVARIABLESANDMETHODS.OWWELLLOOK
ATHOWSTATEANDBEHAVIORARERELATED!NOBJECTSBEHAVIORUSESANOBJECTSUNIQUESTATE
)NOTHERWORDS METHODSUSEINSTANCEVARIABLEVALUES,IKE hIFDOGWEIGHTISLESSTHAN
POUNDS MAKEYIPPYSOUND ELSEv,ETSGOCHANGESOMESTATE

Methods use object state (bark different) 73


pass-by-value means Method arguments and return types 74
pass-by-copy Pass-by-value (the variable is always copied) 77
Getters and Setters 79

copy of Encapsulation (do it or risk humiliation) 80


x Using references in an array 83
111 0 111
00 00 Exercises and puzzles 88
0 00
00
X Z
int int
foo.go(x); void go(int z){ }

xi
5 Extra-Strength Methods
Let’s put some muscle in our methods. 9OUDABBLEDWITHVARIABLES
PLAYEDWITHAFEWOBJECTS ANDWROTEALITTLECODE"UTYOUNEEDMORETOOLS,IKE
OPERATORS!NDLOOPS-IGHTBEUSEFULTOGENERATERANDOMNUMBERS!NDTURN
A3TRINGINTOANINT YEAH THATWOULDBECOOL!NDWHYDONTWELEARNITALLBYBUILDING
SOMETHINGREAL TOSEEWHATITSLIKETOWRITEANDTEST APROGRAMFROMSCRATCH-AYBEA
he GAME LIKE3INKA$OT#OMSIMILARTO"ATTLESHIP 
e ’r e g o n na build tame
W t Com g
Sink a Do Building the Sink a Dot Com game 96
Starting with the Simple Dot Com game (a simpler version) 98
!
Writing prepcode (pseudocode for the game) 100
"
'OCOM

Test code for Simple Dot Com 102


#
Coding the Simple Dot Com game 103
$ 0ETSCOM
Final code for Simple Dot Com 106
%
Generating random numbers with Math.random() 111
&
Ready-bake code for getting user input from the command-line 112
' !SK-ECOM
Looping with for loops 114
      
Casting primitives from a large size to a smaller size 117
Converting a String to an int with Integer.parseInt() 117
Exercises and puzzles 118

6 Using the Java Library


Java ships with hundreds of pre-built classes. 9OUDONTHAVETO
REINVENTTHEWHEELIFYOUKNOWHOWTOFINDWHATYOUNEEDFROMTHE*AVALIBRARY COMMONLY
KNOWNASTHE*AVA!0)9OUVEGOTBETTERTHINGSTODO)FYOUREGOINGTOWRITECODE YOU
MIGHTASWELLWRITEONLYTHEPARTSTHATARECUSTOMFORYOURAPPLICATION4HECORE*AVALIBRARY
ISAGIANTPILEOFCLASSESJUSTWAITINGFORYOUTOUSELIKEBUILDINGBLOCKS

Analying the bug in the Simple Dot Com Game 126


h'OODTOKNOWTHERESAN!RRAY,ISTIN ArrayList (taking advantage of the Java API) 132
THEJAVAUTILPACKAGE"UTBYMYSELF HOW Fixing the DotCom class code 138
WOULD)HAVElGUREDTHATOUTv
Building the real game (Sink a Dot Com) 140
- Julia, 31, hand model
Prepcode for the real game 144
Code for the real game 146
boolean expressions 151
Using the library (Java API) 154
Using packages (import statements, fully-qualified names) 155
Using the HTML API docs and reference books 158
Exercises and puzzles 161

xii
7 Better Living in Objectville
Plan your programs with the future in mind. 7HATIFYOUCOULDWRITE
CODETHATSOMEONEELSECOULDEXTEND EASILY7HATIFYOUCOULDWRITECODETHATWASFLEXIBLE
FORTHOSEPESKYLAST MINUTESPECCHANGES7HENYOUGETONTHE0OLYMORPHISM0LAN YOULL
LEARNTHESTEPSTOBETTERCLASSDESIGN THETRICKSTOPOLYMORPHISM THEWAYSTOMAKE
FLEXIBLECODE ANDIFYOUACTNOWˆABONUSLESSONONTHETIPSFOREXPLOITINGINHERITANCE

Understanding inheritance (superclass and subclass relationships) 168


Designing an inheritance tree (the Animal simulation) 170
Make it Stick Avoiding duplicate code (using inheritance) 171
Overriding methods 172
2OSESARERE
D VIOLETSARE IS-A and HAS-A (bathtub girl) 177
3QUARE)3 ! BLUE
3HAPE THERE
VERSEISNTTRU What do you inherit from your superclass? 180
2OSESARERE E
D VIOLETSARE
"EER)3 !$RI DEAR What does inheritance really buy you? 182
NK BUTNOTA
LLDRINKSARE
/+ YOURTUR BEER Polymorphism (using a supertype reference to a subclass object) 183
N-AKEONE
WAY NESSOF THATSHOWS Rules for overriding (don’t touch those arguments and return types!) 190
THE)3 !RELA THEONE
BER IF8EX TE TIONSHIP!ND
NDS9 8)3 ! REMEM Method overloading (nothing more than method name re-use) 191
9MUSTMAK
ESENSE
Exercises and puzzles 192

8
Serious Polymorphism
Inheritance is just the beginning. 4OEXPLOITPOLYMORPHISM WENEED
INTERFACES7ENEEDTOGOBEYONDSIMPLEINHERITANCETOFLEXIBILITYYOUCANGETONLYBY
DESIGNINGANDCODINGTOINTERFACES7HATSANINTERFACE!ABSTRACTCLASS7HATSAN
ABSTRACTCLASS!CLASSTHATCANTBEINSTANTIATED7HATSTHATGOODFOR2EADTHECHAPTER

Some classes just should not be instantiated 200


Object o = al.get(id); Abstract classes (can’t be instantiated) 201
Dog d = (Dog) o; Abstract methods (must be implemented) 203
d.bark(); Polymorphism in action 206
Class Object (the ultimate superclass of everything) 208
Object
Taking objects out of an ArrayList (they come out as type Object) 211
D og t Compiler checks the reference type (before letting you call a method) 213
o objec
Get in touch with your inner object 214
cast t Polymorphic references 215
back tohe Object
Object
Casting an object reference (moving lower on the inheritance tree) 216
d know is a Dog we
there. Deadly Diamond of Death (multiple inheritance problem) 223
Dog
Using interfaces (the best solution!) 224
Exercises and puzzles 230

xiii
9 Life and Death of an Object
Objects are born and objects die. 9OUREINCHARGE9OUDECIDEWHENAND
HOWTOCONSTRUCTTHEM9OUDECIDEWHENTOABANDONTHEM4HE'ARBAGE#OLLECTORGC
RECLAIMSTHEMEMORY7ELLLOOKATHOWOBJECTSARECREATED WHERETHEYLIVE ANDHOWTO
KEEPORABANDONTHEMEFFICIENTLY4HATMEANSWELLTALKABOUTTHEHEAP THESTACK SCOPE
CONSTRUCTORS SUPERCONSTRUCTORS NULLREFERENCES ANDGCELIGIBILITY

The stack and the heap, where objects and variables live 236
calls
When someone od, this Methods on the stack 237
et h
the go() m oned. His Where local variables live 238
Duck is aband has been
only reference for a Where instance variables live 239
reprogrammed k. The miracle of object creation 240
Du ec differ
ent Duc Constructors (the code that runs when you say new) 241
t

ck obj
Initializing the state of a new Duck 243
d
Overloaded constructors 247
Du Heap Superclass constructors (constructor chaining) 250
ck objec
t

Invoking overloaded constructors using this() 256


ing the
‘d’ is assigned a new Duck object, leav . That Life of an object 258
original (first) Duck object abandoned Garbage Collection (and making objects eligible) 260
first Duck is toast..
Exercises and puzzles 266

Static variables
are shared by
10 Numbers Matter
Do the Math.4HE*AVA!0)HASMETHODSFORABSOLUTEVALUE ROUNDING MINMAX ETC
"UTWHATABOUTFORMATTING9OUMIGHTWANTNUMBERSTOPRINTEXACTLYTWODECIMALPOINTS
ORWITHCOMMASINALLTHERIGHTPLACES!NDYOUMIGHTWANTTOPRINTANDMANIPULATEDATES
all instances of TOO!NDWHATABOUTPARSINGA3TRINGINTOANUMBER/RTURNINGANUMBERINTOA3TRING
a class.
7ELLSTARTBYLEARNINGWHATITMEANSFORAVARIABLEORMETHODTOBESTATIC
static variable:
iceCream Math class (do you really need an instance of it?) 274
kid instance two
kid instance one static methods 275

instance variables: static variables 277


one per instance Constants (static final variables) 282
Math methods (random(), round(), abs(), etc.) 286
static variables:
one per class Wrapper classes (Integer, Boolean, Character, etc.) 287
Autoboxing 289
Number formatting 294
Date formatting and manipulation 301
Static imports 307
Exercises and puzzles 310

xiv
11 Risky Behavior
Stuff happens. 4HEFILEISNTTHERE4HESERVERISDOWN.OMATTERHOWGOODA
PROGRAMMERYOUARE YOUCANTCONTROLEVERYTHING7HENYOUWRITEARISKYMETHOD YOUNEED
CODETOHANDLETHEBADTHINGSTHATMIGHTHAPPEN"UTHOWDOYOUKNOWWHENAMETHODIS
RISKY7HEREDOYOUPUTTHECODETOHANDLETHEEXCEPTIONALSITUATION)NTHISCHAPTER WERE
GOINGTOBUILDA-)$)-USIC0LAYER THATUSESTHERISKY*AVA3OUND!0) SOWEBETTERFINDOUT

Making a music machine (the BeatBox) 316


What if you need to call risky code? 319
an excepti
ows on
hr 2 ba Exceptions say “something bad may have happened...” 320
ck
t

The compiler guarantees (it checks) that you’re aware of the risks 321
class Cow {
Catching exceptions using a try/catch (skateboarder) 322
class Bar { void moo() {
void go() { if (serverDown){

}
moo();
1 }
explode();
Flow control in try/catch blocks 326
}
int stuff() {
}
x.beep();

}
} calls risky method The finally block (no matter what happens, turn off the oven!) 327
Catching multiple exceptions (the order matters) 329
your code class with a
risky method Declaring an exception (just duck it) 335
Handle or declare law 337
Code Kitchen (making sounds) 339
Exercises and puzzles 348

12 A Very Graphic Story


Face it, you need to make GUIs. %VENIFYOUBELIEVETHATFORTHERESTOFYOUR
LIFEYOULLWRITEONLYSERVER SIDECODE SOONERORLATERYOULLNEEDTOWRITETOOLS ANDYOULL
WANTAGRAPHICALINTERFACE7ELLSPENDTWOCHAPTERSON'5)S ANDLEARNMORELANGUAGE
FEATURESINCLUDING%VENT(ANDLINGAND)NNER#LASSES7ELLPUTABUTTONONTHESCREEN
class MyOuter { WELLPAINTONTHESCREEN WELLDISPLAYAJPEGIMAGE ANDWELLEVENDOSOMEANIMATION

class MyInner {
void go() { Your first GUI 355
} Getting a user event 357
}
Implement a listener interface 358
}
Getting a button’s ActionEvent 360
Putting graphics on a GUI 363
The outer and inner objects
are now intimately linked. Fun with paintComponent() 365
oute
r

The Graphics2D object 366


Putting more than one button on a screen 370
jects on the
These two aobspecial bond. The inner
Inner classes to the rescue (make your listener an inner class) 376
heap have use the outer’s
inner can (and vice-versa). Animation (move it, paint it, move it, paint it, move it, paint it...) 382
variables Code Kitchen (painting graphics with the beat of the music) 386
Exercises and puzzles 394

xv
13 Work on your Swing
Swing is easy. 5NLESSYOUACTUALLYCAREWHEREEVERYTHINGGOES3WINGCODELOOKS
EASY BUTTHENCOMPILEIT RUNIT LOOKATITANDTHINK hHEY THATSNOTSUPPOSEDTOGOTHEREv
4HETHINGTHATMAKESITEASYTOCODEISTHETHINGTHATMAKESITHARDTOCONTROLˆTHE,AYOUT
-ANAGER"UTWITHALITTLEWORK YOUCANGETLAYOUTMANAGERSTOSUBMITTOYOURWILL)N
THISCHAPTER WELLWORKONOUR3WINGANDLEARNMOREABOUTWIDGETS

Swing Components 400

Components in Layout Managers (they control size and placement) 401


the east and Three Layout Managers (border, flow, box) 403
west get theirth. BorderLayout (cares about five regions) 404
preferred wid
FlowLayout (cares about the order and preferred size) 408
Things in the BoxLayout (like flow, but can stack components vertically) 411
north and The center gets JTextField (for single-line user input) 413
south get their whatever’s left. JTextArea (for multi-line, scrolling text) 414
preferred height.
JCheckBox (is it selected?) 416
JList (a scrollable, selectable list) 417
Code Kitchen (The Big One - building the BeatBox chat client) 418
Exercises and puzzles 424

14 Saving Objects
Objects can be flattened and inflated. /BJECTSHAVESTATEANDBEHAVIOR
"EHAVIORLIVESINTHECLASS BUTSTATELIVESWITHINEACHINDIVIDUALOBJECT)FYOURPROGRAM
NEEDSTOSAVESTATE YOUCANDOITTHEHARDWAY INTERROGATINGEACHOBJECT PAINSTAKINGLY
WRITINGTHEVALUEOFEACHINSTANCEVARIABLE/R YOUCANDOITTHEEASY//WAYˆYOUSIMPLY
FREEZE DRYTHEOBJECTSERIALIZEIT ANDRECONSTITUTEDESERIALIZE ITTOGETITBACK

serialized Saving object state 431


Writing a serialized object to a file 432
Java input and output streams (connections and chains) 433
Object serialization 434
ions?
Any quest Implementing the Serializable interface
Using transient variables
437
439
deserialized Deserializing an object 441
Writing to a text file 447
java.io.File 452
Reading from a text file 454
Splitting a String into tokens with split() 458
CodeKitchen 462
Exercises and puzzles 466
xvi
15
Make a Connection
Connect with the outside world. )TSEASY!LLTHELOW LEVELNETWORKING
DETAILSARETAKENCAREOFBYCLASSESINTHEJAVANETLIBRARY/NEOF*AVASBESTFEATURESIS
THATSENDINGANDRECEIVINGDATAOVERANETWORKISREALLYJUST)/WITHASLIGHTLYDIFFERENT
CONNECTIONSTREAMATTHEENDOFTHECHAIN)NTHISCHAPTERWELLMAKECLIENTSOCKETS7ELL
MAKESERVERSOCKETS7ELLMAKECLIENTSANDSERVERS"EFORETHECHAPTERSDONE YOULLHAVEA
FULLY FUNCTIONAL MULTITHREADEDCHATCLIENT$IDWEJUSTSAYMULTITHREADED
Socket c
to port 5o0nnection
on the serv 00 Chat program overview 473
196.164.1.10er at Connecting, sending, and receiving 474
3
Network sockets 475
TCP ports 476
Reading data from a socket (using BufferedReader) 478
Writing data to a socket (using PrintWriter) 479
Client Server
nnection Writing the Daily Advice Client program 480
Socket ocothe client Writing a simple server 483
back t 64.1.100,
at 196.1242 Daily Advice Server code 484
port 4 Writing a chat client 486
Multiple call stacks 490
Launching a new thread (make it, start it) 492
The Runnable interface (the thread’s job) 494
Three states of a new Thread object (new, runnable, running) 495
The runnable-running loop 496
Thread scheduler (it’s his decision, not yours) 497
Putting a thread to sleep 501
Making and starting two threads 503
Concurrency issues: can this couple be saved? 505
The Ryan and Monica concurrency problem, in code 506
Locking to make things atomic 510
Every object has a lock 511
The dreaded “Lost Update” problem 512
Synchronized methods (using a lock) 514
Deadlock! 516
Multithreaded ChatClient code 518
Ready-bake SimpleChatServer 520
Exercises and puzzles 524

xvii
16 Data Structures
Sorting is a snap in Java. 9OUHAVEALLTHETOOLSFORCOLLECTINGANDMANIPULATING
YOURDATAWITHOUTHAVINGTOWRITEYOUROWNSORTALGORITHMS4HE*AVA#OLLECTIONS
&RAMEWORKHASADATASTRUCTURETHATSHOULDWORKFORVIRTUALLYANYTHINGYOULLEVERNEED
TODO7ANTTOKEEPALISTTHATYOUCANEASILYKEEPADDINGTO7ANTTOFINDSOMETHINGBY
NAME7ANTTOCREATEALISTTHATAUTOMATICALLYTAKESOUTALLTHEDUPLICATES3ORTYOURCO
WORKERSBYTHENUMBEROFTIMESTHEYVESTABBEDYOUINTHEBACK

Collections 533
Sorting an ArrayList with Collections.sort() 534
List 0 1 2 3 Generics and type-safety 540
Sorting things that implement the Comparable interface 547
Sorting things with a custom Comparator 552
The collection API—lists, sets, and maps 557
Set Avoiding duplicates with HashSet 559
Overriding hashCode() and equals() 560
HashMap 567
Using wildcards for polymorphism 574
Map “Ball”
“Ball1” “Fish”
“Ball2” “Fish”“Car”
“Car”
Exercises and puzzles 576

17 Release Your Code


It’s time to let go. 9OUWROTEYOURCODE9OUTESTEDYOURCODE9OUREFINEDYOURCODE
9OUTOLDEVERYONEYOUKNOWTHATIFYOUNEVERSAWALINEOFCODEAGAIN THATDBEFINE"UTIN
THEEND YOUVECREATEDAWORKOFART4HETHINGACTUALLYRUNS"UTNOWWHAT)NTHESEFINAL
TWOCHAPTERS WELLEXPLOREHOWTOORGANIZE PACKAGE ANDDEPLOYYOUR*AVACODE7ELLLOOK
ATLOCAL SEMI LOCAL ANDREMOTEDEPLOYMENTOPTIONSINCLUDINGEXECUTABLEJARS *AVA7EB
3TART 2-) AND3ERVLETS2ELAX3OMEOFTHECOOLESTTHINGSIN*AVAAREEASIERTHANYOUTHINK
classes

Deployment options 582


com
Keep your source code and class files separate 584
101101

foo
10 110 1
0 11 0
Making an executable JAR (Java ARchives) 585
MyApp.jar 001 10
001 01

Running an executable JAR 586


MyApp.class
Put your classes in a package! 587
Packages must have a matching directory structure 589
Web Server Compiling and running with packages 590
JWS
Lorper
iure
Compiling with -d 591
eugue
tat vero
conse
euguero- Making an executable JAR (with packages) 592
MyApp.jar
MyApp.jnlp MyApp.jar
Java Web Start (JWS) for deployment from the web 597
How to make and deploy a JWS application 600
Exercises and puzzles 601

xviii
18
Distributed Computing
Being remote doesn’t have to be a bad thing. 3URE THINGSAREEASIER
WHENALLTHEPARTSOFYOURAPPLICATIONAREINONEPLACE INONEHEAP WITHONE*6-TORULE
THEMALL"UTTHATSNOTALWAYSPOSSIBLE/RDESIRABLE7HATIFYOURAPPLICATIONHANDLES
POWERFULCOMPUTATIONS7HATIFYOURAPPNEEDSDATAFROMASECUREDATABASE)NTHIS
CHAPTER WELLLEARNTOUSE*AVASAMAZINGLYSIMPLE2EMOTE-ETHOD)NVOCATION2-) 7ELL
ALSOTAKEAQUICKPEEKAT3ERVLETS %NTERPRISE*AVA"EANS%*" AND*INI

Client Server Java Remote Method Invocation (RMI), hands-on, very detailed 614
Servlets (a quick look) 625
RMI STUB RMI SKELETON Enterprise JavaBeans (EJB), a very quick look 631
Jini, the best trick of all 632
Se e
r

C li
ent helper rvice help Se
rvice objec
t

C li
Building the really cool universal service browser 636
ent object
The End 648

A
Appendix A
The final Code Kitchen project. !LLTHECODEFORTHEFULLCLIENT SERVERCHAT
BEATBOX9OURCHANCETOBEAROCKSTAR

BeatBoxFinal (client code) 650


MusicServer (server code) 657
DANCEBEAT

!NDYGROOVE
REVISED
#HRISGROOVE
BEAT
.IGELDANCE

B
Appendix B
The Top Ten Things that didn’t make it into the book. 7ECANTSEND
YOUOUTINTOTHEWORLDJUSTYET 7EHAVEAFEWMORETHINGSFORYOU BUTTHISISTHEENDOFTHE
BOOK!NDTHISTIMEWEREALLYMEANIT
Top Ten List 660

i Index 677

xix
how to use thOIS book

Intro

-the bl>Yl\i,,~ ,~tiOf\:


DID \:h<'1 f.t Wl ,•• J••• \""~,.~-;~ boo\<r"
IY\ -this stl.bOf\I 'Wt. .lYlS'Ht:Y
'So, whY

xxi
how to use this book

Who is this book for?


If you can answer "yes" to all of these:
This is NOT a reference
E!)" Have you done some programming? book. Head First Java is a
book designed for 'earning,
® Do you want to learn Java? not an encyclopedia of
Java facts.
® Do you prefer stimulating dinner party
conversation to dry, dull, technical
lectures?
this book is for you.

Who should probably back away frotH this book?


If you can answer "yes" to anyone of these:

Is your programming background limited


to HTML only, with no scripting language
experience?
(If you've don e anything with looping, or if/then
logic , you 'll do fine with this book, but HTML
tagging alone might not be enough.)

® Are you a kick-butt C++ programmer


looking for a reference book?

® Are you afraid to try something different?


Would you rather have a root canal than I
mix stripes with plaid? Do you believe
than a technical book can't be serious If
there's a picture of a duck in the memory
management section?

this book is not for you .

xxii intr o
the intra

We k.,ow what you"re thittkhtg.


"How can this be a seriousJava programming book?"
"What's with all the graphics?"
"Can I actually learn it this way?"
"Do I smell pizza?"

A.,d we kt10w what your brain is thittkittg.


Your brain craves novelty. It's always searching, scanning, waiting for
something unusual. It was built that way, and it helps you stay alive.
Today, you're less likely to be a tiger snack. But your brain 's still
looking. You just never know.
So what does your brain do with all the routine, ordinary, normal
things you encounter? Everything it can to stop them from
interfering with the brain's realjotr-recording things that matter. It
doesn't bother saving the boring things; they never make it past the
"th is is obviously not important" filter.
How does your brain know what's important? Suppose you're out for
a day hike and a tigerjumps in front of you , what happens inside your
head?
Neurons fire. Emotions crank up. Chemicals suW
And that's how your brain knows ...
This must be Importantl Don't forget ItI
But imagine you're at home, or in a library. It's a safe, warm, tiger-free
zone. You're studying. Getting ready for an exam. Or trying to learn
some tough technical topic your boss thinks will take a week, ten days
at the most,
Just one problem. Your brain's trying to do you a big favor. It 's
trying to make sure that this obviou.sly non-important content
doesn't clutter up scarce resources. Resources that are better
spent storing the really bigthings. Like tigers. Like the danger of
fire. Like how you should never again snowboard in shorts.
And there's no simple way to tell your brain, "Hey brain, thank
you very much, but no matter how dull this book is. and how
little I'm registering on the emotional richter scale right now, I
really do want you to keep this stuff around. h

you are he re ~ xxiII


how to use this book

We tlUn1 of a "!lead Fll'St Java" reader as a learner.


-
So what does It take to learn something? First, you have to get It, then make sure
you don't forgetll It's not about pushing facts Into your head. Based on the
latest research In cognltJve science, neurobiology, and educatJonal psychology,
learning takes a lot more than text on a page . We know what turns your brain on.

Soma of the Head First learning principles:

Make It visual. Images are far more memorable than words RMI"'(loo~
~ite
alone, and make learning much more effective (Up to 89%
Improvement in recall and transfer studies) . It also makes
things more understandable. Put the words within
or near the graphics they relate to, rather than on the
bottom or on another page, and learners will be up to twice
as likely to solve problems related to the content.

Use a conversational and personalized style,In recent studies,


students performed up to 40% better on post-learning tests if the content spoke
It re4l1y SlJcks to ~ <III
Qbstl"<lct m~tkod. You directly to the reader, using a flrst-person, conversational style rather than
don't heve Q body. taking a formal tone.Tell stories instead of lecturing. Use casual language. Don't
take yourself too seriously. Which would you pay more attention to: a stimulating
o dinner party companion, or a lecture?
o

Get the learner to think more deeply. In other words, unless


you actively flex your neurons, nothing much happens in your head.
A reader has to be motivated, engaged, curious, and inspired to
solve problems, draw conclusions, and generate new knowledge.
And for that, you need challenges, exercises, and thought-
~0llll10 ; provoking questions, and actlvlties that involve both sides
of the brain, and multiple senses.
~,-.A 'l>o41'· ,~ t
tl4~i-
~ ;Ie. Oet-and kee,,-,he reader's attention. We've all
had the"' really want to learn this but I can't stay awake past
page one" experience. Your brain pays arrentlon to things that are out
of the ordinary, interesting, strange, eye-catching, unexpected. Learning a new,
tough, technical topic doesn't have to be boring. Your brain will learn much more qUicklyjf it's not.

Touch their emotlon8. We now know that your ability to remember something Is largely
dependent on Its emotional content. You remember what you care about. You remember when
you feel somethIng. No we're not talking heart-wrenching stories about a boy and hIs dog .
We're talking emotions like surprise, curiosity, fun, "what the ...T", and the feeling of "I Rulel"
that comes when you solve a puzzle, learn something everybody else thinks Is hard, or realize
you know something that ·"m more technical than thou' Bob from engineering doe$n't.

XXiv in t ra
the intro

Metacogtlitiott: thittkittg about thittki"Q.


If you really want to learn, and you want to learn more quickly and more deeply,
pay attention to how you pay attention. Think about how you think, Learn how
you learn.
Most of us did not take courses on metacognition or learning theory when we were
growing up. We were expected to learn, but rarely taught to learn. o
o
But we assume that if you're holding this book, you want to learn Java. And you
probably don't want to spend a lot of time.
To get the most from this book, or any book or learning experience, take
responsibility for your brain. Your brain 00 thai content.
The trick is to get your brain to see the new material you're learning
as Really Important. Crucial to your well-being. As important as
a tiger. Otherwise, you're in for a constant battle, with your brain
doing its best to keep tile new content from sticking.

So Just how DO you get your brain to treat Java like It


was a hungry tiger?
There's the slow, tedious way, or the faster, more effective way. The
slow way is about sheer repetition. You obviously know that you are
able to learn and remember even the dullest of topics, if you keep pounding
on the same thing. With enough repetition, your brain says, "This doesn'tfeel
important to him, but he keeps looking at the same thing overand over and over, so
I suppose it must be."
The faster way is to do anything that increases brain activity, especially different types
of brain activity. The things on the previous page are a big part of the solution,
and they're all things that have been proven to help your brain work in your favor.
For example, studies show that putting words within the pictures they describe (as
opposed to somewhere else in the page, like a caption or in the body text) causes
your brain to try to makes sense of how the words and picture relate, and this
causes more neurons to fire. More neurons firing = more chances for your brain
to get that this is something worth paying attention to, and possibly recording.

A conversational style helps because people tend to pay more attention when they
perceive that they're in a conversation, since they're expected to follow along and
hold up their end. The amazing thing is, your brain doesn't necessarily care that
the "conversation" is between you and a book! On the other hand, if the writing
style is formal and dry, your brain perceives it the same way you experience being
lectured to while sitting in a roomful of passive attendees. No need to stay awake.
But pictures and conversational style are just the beginning.

you are here ~ xxv


how to use this book

Here"s what WE did:


We used pidures, because your brain is tuned for visuals, not text As fur as your
brain's concerned, a picture really ssworth 1024 words. And when text and pictures
work together, we embedded the text in the pictures because your brain works
more effectively when the text is wiihin the thing the text refers to, as opposed to in
a caption or buried in the text somewhere.
We used repetitUm, saying the same thing in different ways and with different media
types, and multiplesenses, to increase the chance that the content gets coded coded
into more than one area of your brain.
We used concepts and pictures in ~ways because your brain is tuned for
novelty, and we used pictures and ideas with at least SO'1M emf>tional content, because
your brain is tuned to pay attention to thebiochemlstry of emotions. That which
causes you to feel something is more likely to be remembered. even if that feeling is
nothing more than a little humor; SU1"f1rise, or interest.
We used a personalized, conversational style, because your brain is tuned to pay more
attention when it believes you 're in a conversation than if it thinks you're passively
listening to a presentation. Your brain does this even when you're reading.
We included more than 50 ~ , because your brain is tuned to learn and
remember more when you do things than when you readabout things. And we
made the exercises challenging-yet-do-able, because that's what most pet1J/.e prefer.
We used multiple learning styles, because you might prefer step-by-step procedures,
while someone else wants to understand the big picture first, while someone else
just wants to see a code example. But regardless of your own learning preference,
everyone benefits from seeing the same content represented in multiple ways.
We include content for both rides ofyour brain; because the more of your brain you
engage, the more likely you are to learn and remember, and the longer you can
stay focused. Since working one side of the brain often means giving the other side
a chance to rest, you can be more productive at learning for a longer period of
time.
And we included storie: and exercises that present J'TUWe than one point ofview,

~8\"Barlle"
because your brain is tuned to learn more deeply when it's forced to make
evaluations and judgements.
We included chaIknges, with exercises, and by asking qrustions that don't always have
a straight answer, because your brain is tuned to learn and remember when it has
to work at something (just as you can't get your body in shape by watching people
at the gym). But we did our best to make sure that when you're working hard, it's
on the right things: That you'renot spending one exITa denLfrile processing a hard-to-
understand example, or parsing difficult,jargon-Iaden, or extremely terse text.
We used an 80/20 approach. We assume that if you 're going for a PhD in java,
this won't be your only book. So we don't talk about everything. Just the stuff you'll
actually use.

xxvi Intra
the intra
Herels what YOU ca., do to be.,d your
brah1 i"to subltdssiot1.
So, we did our part. The rest is up to you . These tips are a
starting point; Listen to your brain and figure out what works
for you and what doesn't. Try new things.

lki. -this OUt dhd sf.itk 't


Oh yOlJ.'r l'"e+l'"id9tt"ak .I
. _ - - _ . _ - - - - - - - - - - -~ -----------------------------------------------------------
~ . Slow down. The more you understand,
the less you have to memorize.
Don't just 'read. Stop and think. When the
book asks you a question, don't just skip to
• Drink water. Lots of It.
Your brain works best in a nice bath of fluid.
Dehydration (which can happen before you
ever feel thirsty) decreases cognitive function.


the answer. Imagine that someone really is
asking the question. The more deeply you Talk about It. Out loud.
force your brain to think, the better chance Speaking activates a different part of
you have of learning and remembering. the brain. If you're trying to understand
something, or increase your chance of
Do the exercises. Write your own notes. remembering it later, say it out loud. Better
We put them in, but if we did them for you, still, try to explain it out loud to someone
that would be like having someone else else . You'll learn more quickly, and you might
do your workouts for you . And don't just uncover ideas you hadn't known were there
look at the exercises. Use a pencil. There's when you were reading about it.
plenty of evidence that physical activity
while learning can increase the learning. Listen to your brain.
Pay attention to whether your brain is getting
Read the "There are No Dumb Questions" overloaded. If you find yourself starting to ski m
That means all of them. They're not the surface or forget what you just read, it's
optional side-bars-they're part of the core time for a break. Once you go past a certain
contentl Sometimes the questions are more point, you won't learn faster by trying to shove
useful than the answers. more in, and you might even hurt the process.

Don't do all your reading In one place. • Feel somethlngl


Stand-up, stretch, move around . change Your brain needs to know that this mauers. Get
chairs, change rooms. It'll help your brain involved with the stories. Make up your 0\\>11
feel something, and keeps your learning from captions for the photos. Groaning over a bad
being too connected to a particular place. joke is still better than feeling nothing at all.

Make this the last thing you read before . . Type and run the code.
bed. Or at least the last challengIng thing. Type and run the code examples. Then you
Part of the learning (especially the transfer can experiment with changing and improving
to long-term memory) happens afleryou put the code (or breaking it, which is sometimes
the book down. Your brain needs time on the best way to figure alit what's really
its own , to do more processing. If you put in happening). For long examples or Ready-bake
something new during that processing-time, code, you can download the source files from
some of what you just learned will be lost. headfirstjava.corn

you are here. xxvII


how to use this book

What you heed for this book:


You do not need any other development tool. such as an Integrated
Development Environment (IDE). We strongly recommend that you not
use anything but a-basic text editor until you complete this book (and
especially not until after chapter 16). An IDE can protect you from some of
the details that really matter. so you're much bener off learning from the
command-line and then. once you really understand what's happening.
move to a tool that automates some of the process.

SmlNG UP JAVA - - - - - - - - - - - - - - - - - - ,
• If you don't already have a 1.5 orgreater Java 2 Standard Edition SDK (Software
Development Kit), you need it. If you're on Linux, Windows, or Solaris, you can gellt for free
from java.sun.com (Sun's websile forJava developers). It usually takes nomore than two clicks
from the main page togel to the J2SE downloads page . Get the latest non-beta version posted.
The SDK includes everything you need tocompile and run Java.
If you're running Mac OS X10.4. the Java SDK isalready installed. It's partof OS X, and you
don't have todo anything else. If you're on an earlier version of OS X. you have an earlier
version ofJava that will wor1< for95% of the code in this book.
Note: This book is based on Java 1.5, but forstunningly unclear mar1<eting reasons, shortly
before release, Sun renamed It Java 5, while still keeping "1 .5" asthe version number forthe
developer's kit So, if you see Java 1.5 orJava 5 orJava 5.0, or "Tiger" (version 5's original
code-name), they all mean the same thing. There was never a Java 3.0 or 4.Q--it jumped from
version 1.4 to5.0,bu1 you will still find places where it'scalled 1.5 instead of 5. Don'l ask.
(Oh, and just 10 make il more entertaining, Java 5 and the Mac OS X 10.4 were both given the
same code-name of"Tiger", and since OS X 10.4 is the version of the Mac OS you need to run
Java 5, vou'llhear people talk about "Tiger on TIger". II justmeans Java 5 on OS X 10.4).

• The SDK does not include the API documentatIon, and you need that! Go back tojava.sun.
com and get the J2SE APr documentation. You can also access the API docs online, without
downloading them, but thaI's apain. Trusl us, irs worth the download.

• You need a texteditor. Virtually any text editor will do (vi, emacs, pica), including the GUI ones
that come with most operating systems. Nolepad, Wordpad, TextEdlt, etc. allwork, aslong as
you make sure they don'l append a ".txt" on tothe end of your source code.

• Once you've downloaded and unpackedfzippedfwhatever (depends on which version and for
which OS). you need to add an entry toyour PATH environment variable that points tothe fbln
directory inside the main Java directory. For example, if the J2SDK puts a directory on your
drive called "j2sdk1.5,O', look inside that directory and you'lI find the "bin" directory where the
Java binaries (the tools) live. The bin directory is the one you need a PATH to, sothaI when you
type:
% javac
atthe command-line, your terminal will know how tofind the javac compiler.
Note: if you have trouble with you installation, we recommend you gotojavaranch.com, and join
the Java-Beginning forum! Actually, you should dothat whether you have trouble or not.
Nole: much of the code from this book Is available at wlckedlysmart.com

xxvlll intra
the intro

Last.. tMinute thhtgs you need to know:


This is a learning experience, not a reference book. We deliberately
stripped out everything that might get in the way of lmrningwhatever it
is we're working on at that point in the book. And the first time through,
you need to begin at the beginning, because the book makes assumptions
about what you've already seen and Learned.

We use simple UML.-IIke diagrams. Dog


Ifwe'd used pure UML, you'd be seeing something that looks like Java , but
with syntax that's just plain 1UTfYflf;. So we use a simplified version ofUML size
that doesn't conflict with Java syntax. If you don't already know UML. you
won't have to worry about leamingJava and UML at the same time. barkQ
eatO
chaseCatQ
We don't worry about organizing and packaging your own
code until the end of the book.
In this book, you can get on with the business of learningJava , without
-
stressing over some of the organizational or administrative details of
deveLopingJava programs. You will, in the real world, need to know-and
use--these details, so we cover them in depth. But we save them for the end
of the book (chapter 17) . Relax while you ease intoJava, gently.

The end-of-chapter exercises are mandatory; puzzles are


optional. Answers for both are at the end of each chapter.
One thing you need to know about the puzzles-tmy 're puxxles. As in Logic
puzzles, brain teasers, crossword puzzles, etc. The exercises are here to help
}'ou practice what you've learned, and you should do them all. The puzzles
are a different story, and some of them are quite challenging in a puzzle
way. These puzzles are meant for pualets, and you probably already know if
you are one. If you're not sure, we suggest you give some of them a try, but
whatever happens, don't be discouraged if you can't solve a puzzle or if you
simply can't be bothered to take the time to work them out.

The 'Sharpen Your Pencil' exercises don't have answers.


Not printed in the book, anyway. For some of them, there is no right
answer, and for the others, part of the learning experience for the Sharpen
activities is for you to decide if and when your answers are right, (Some of
our suggested answers are available on wickedlysman.com)

The code examples are as lean as possible


It's frustrating to wade through 200 lines of code looking for the two lines
you need to understand. Most examples in this book are shown within the
smallest possible context, so that the part you're trying to learn is clear and
simple. So don't expect the code to be robust, or even complete. That's
Jour assignment for after you finish the book. The book examples are
written specifically for learning, and aren't always fully-functional.
you are here ~ xxix
tech editing: Jessica and Valentin

fecht-tical Editors
"Credit goes to all, but mistakes are the sale reponsibility of the
author...", Does anyone really believe that? See the two people on
this page? If you find technical problems, it's probably theirfaulL : )

Vjj\el'lt,i,,'s ·be

Valentin Valentin Creuaz has a Masters degree


in Information and Computer Science from
Jess works at Hewlett-Packard on the Self- the Swiss Federal Institute of Technology in
Healing Services Team. She has a Bachelor's Lausanne (EPFL). He has worked as a software
in Computer Engineering from Villanova engineer with SRI International (Menlo Park,
University, has her SCPJ 1.4 and SCWCD CA) and as a principal engineer in the Software
certifications, and is literally months away Engineering Laboratory of EPFL.
from receiving her Masters in Software Valentin is the co-founder and CTO of Condris
Engineering at Drexel University (whewl) Technologies, a company specializing in the
When she's not working, studying or development of software architecture solutions.
motoring in her MINI Cooper S,jess can His research and development interests
be found fighting her cat for yam as she include aspect-oriented technologies, design
completes her latest knitting or crochet and architectural patterns, web services, and
project (anybody want a hat?) She is software architecture. Besides taking care of
originally from Salt Lake City, Utah (no, his wife. gardening, reading. and doing some
she's not Mormon ... yes, you were too sport, Valentin moderates the SCBCD and
going to ask) and is currently living near SCDJWS forums atJavaranch.com . He holds
Philadelphia with her husband. Mendra, and the SCJP, SCjD, SCBCD, scwco, and SCD]WS
two cats: Chai and Sake. certifications. He has also bad the opporruniry
You can catch her moderating technical to serve as a co-author for Whizlabs SCBCD
forums acjavaranch.com. Exam Simulator.
(We're still in shock from seeing him in a tie.)

XXX intra
the in tra
t\'"~dit
Other people to b~e: $OfrIe ~ 0".... Java
!')I.~t .... t . . !vi~e ....s...
•41 O'Reilly:
Our biggest thanks to Mike Loukides at O'Reilly, for taking a
chance on this , and helping to shape the Head First concept into
a book (and series) . As this second edition goes to print there
are now five Head First books, and he's been with us all the way.
To Tim O'Reilly, for his willingness 10 launch into something
completely new and different. Thanks to the clever Kyle Hart for
figuring out how Head First fits into the world, and for launching
the series . Finally, to Edie Freedman for designing the H ead First
"emphasize the head" cover.
Our intrepid beta testers and reviewer team:
Our top honors and thanks go to the director of our javaranch
tech review team.johannes deJong. This is your fifth time around
with us on a Head First book, and we're thrilled you're still speaking
to us, Jeff Cumps is on his third book with us now and relentless
about finding areas where we needed to be more clear or correct.
Corey McGlone, you rock. And we think you give the clearest
explanations on javaranch, You'll probably notice we stole one or
two of them. Jason Menard saved our technical butts on more
than a few details, and Thomas Paul, as always, g-ave us expert
feedback and found the subtle Java issues the rest of us missed.
Jane Griscti has herJava chops (and knows a thing or two about
",-riting) and it was great to have her helping on the new edition
along with long-timejavarancher Barry Gaunt
:\farilyn de Queiroz gave us excellent help on both editions of the
book. Chris Jones,Jobn Nyquist, James Cubeta, Terri Cubeta,
and Ira Becker gave us a ton of help on the first edition.
Special thanks to a few of the Head First ers who've been helping
us from the beginning: Angelo Celeste, Mikalai Zaikin, and
Thomas Duff (twduff.corn). And thanks to our terrific agent, David
Roge1berg of StudioB (but seriously, what about the movie rights?)

you are here ~ xxxi


" still more acknowledgements

Just whet1 you thought there wouldt1't be at1Y


tMore ackt1owledgetMet1ts*.

MoreJava technical experts woo helped out on the first edition (in pseudo-random order):
Emiko Hori, Michael Taupitz, Mike Gallihugh, Manish Hatwalne,James Chegwidden,
Shweta Mathur, Mohamed Mazahim,John Paverd,Joseph Bih, Skulrat Patanavanich,
Sunil Palicha, Suddhasatwa Ghosh, Ramki Srinivasan, Alfred Raouf, Angelo Celeste,
Mikalai Zaikin,John Zoetebier,Jim Pleger, Barry Gaunt, and Mark Dielen.

The first edition puzzle team:


Dirk Schreckmann, Mary 'JavaCross Champion" Leners, Rodney J. Woodruff, Gavin Bong,
and Jason Menard. Javaranch is lucky to have you all helping out.

Other co-conspirators to thank:


Paul Wheaton, the javaranch Trail Boss for supporting thousands ofJava learners.
Solveig Haugland, mistress ofJ2EE and author of "Dating Design Patterns".
Authors Don Smith and Tom Negrino (backupbrain.com) , for helping us navigate the
tech book world.
Our Head First partners in crime, Eric Freeman and Beth Freeman (authors of Head First
Design Patterns) , for giving us the Bawls" to finish this on time.
Sherry Dorris, for the things that really matter.

Brave Early Adopters of the Head First series:


Joe Litton, Ross P. Goldberg, Dominic Da Silva, honestpuck, Danny Bromberg, Stephen
Lepp, Elton Hughes, Eric Christensen, Vulinh Nguyen, Mark Rau, Abdulhaf, Nathan
Oliphant, Michael Bradly, Alex Darrow, Michael Fischer, Sarah Nottingham, Tim Allen,
Bob Thomas, and Mike Bibby (the first).

"The large number of acknOWledgements is because we're testing the theory that everyone mentioned in
a book acknowledgement will bUy at least one copy, probably more , what with relatives and everyth ing. If
you'd like to be in the acknowledgement of our next book, and you have a large family, write to us.

xxxii intro
1 dive in A Quick Dip

Breaking the Surface


Come on, the water's
great! We'll dive right in and
write some code, then compile and
run it. We're talking syntax, looping
and branching, and a look at what
makes J alia so cool. You'll be
coding in no time.

Java takes you to new places. From its humble release to the public as the
(wimpy) version 1.02,Java seduced programmers with Its friendly syntax, object-orlented features,

memory management, and best of aU-the promise of portability. The lure of wrlte-once/run-

anywhere Isjust too strong. A devoted followlnq exploded, as programmers fought against bugs,

limitations, and, on yeah, the fact that it was dog slow. But that was ages ago. If you're just starting in
Java, you're lucky. Some of us had to walk five miles in the snow, uphill both ways (barefoot), to
get even the most trivial applet to work. But you, why,yov get to ride the sleeker, faster. much
more powerful Javaof today. .....".--..•.

this is a new chapter 1


the way Java works

fhe Way Java Works


The goal Is to write one application (in this
example, an interactive party Invitation) and have
It work on whatever device your friends have.

source code (or Method Pany()


Oalo;l<'-O
the Interactive
1 invobspe-
party hwltaUon. ----.. clal #1 <Method
java.lang.Obf&dO>
4 rerum

Source Output
(code)
o
Create a source
COIMpiler Virtual
Machh'u
document. Use an
established protocol The compiler creates a
Run your document new document, coded
(In th is case, the Java
t hro ugh a source code into Java bytecode.
language). Your friends don't have
complier. The complier Any device capable of
checks for errors and running Java will be able a physical Java Machine,
won't let you compile to Interpret/translate but they all have a
until It's satisfied that this file into something virtual Java machine
everything will run It can run .The complied (implemented In
correctly. bytecode is platform- software) running inside
Independent. their electronic gadgets.
The virtual mach ine reads
and runs thebytecode.

2 chapter 1
dive In A Quick Dip

What you'll do in Jav~


You'll type a source code file, compile It using the
Javac complier, then run the complied bytecode
on a .Java virtual machine.

java.awl·; Method Party()


r:.pon java.awtevenL·; oaload_O
:tass Party (
1Invokespedal #1 <Method
pc.;b!ic void bu~dlnvlte() ( Java,lang.ObjedO> PartY at Tim's1
Fl3me r=IlllW FtameO;
4 return
Labell =new LabellParty atTlm's1;
B tton b =new ButIoI'I('You ber) ; Method void bulidInviteO
Button C =te« Button("Shool me'):
onew #2 <Class java.aWl.Frame>
Panel p =new PanelO; Virtual
p.addO): 3 dup
} II more code here...
4 Invokespec1al #J <Method
MachlttU
)

Source
Java.aWl.FrameQ>
o
o Output
(code)
Run the program by
starting the Java Virtual
Machine (JVM) with the
Party.doss file. The JVM
Type your source code. translates the bytecode
into something the
Saveas: Party.Java
underlying platform
Complied code: Party.dass understands, and runs
your program .

(NoU: U,is is ~ ....e.l"t to be d h-kial... '101<'11 bt


'OI\'"H:i~ Yedl tilde ill a ....OIO'O\t, bl.t .f~ MW, 'ole jll1t
wa,,-t: 'fO'J. U> ~tt d .fccl .f~ how it all .fib ~etkcYJ

you are here ~ 3


Avery brief history of Java
~ 3500
I!
~ 3000
'!lIlI
"a
2500
c
S
lill 2000
~

.,>
CII 1500

..
G)
.z:.
.5
1000

1ft
G)
500
1ft
1ft
lIlI 0
U
Java 1.02 Java 2 Java 5.0
250 classes 500 classes (wnloKs 1.2 .. t~) (wrsloKs 1.5 attd up)
Slow. A little faster. 2300dasses 3500 classes
Cute name and logo. More capable, friendlier. Much faster. More power, ~/e, to
Fun to use. Lots of Becoming very popultJr. Can (sometimes) run at develop with.
bugs. Applets are Better GUI code. native speeds. Serious, Besides adding more than a
the Big Thing. powerful. Comes in three thousand additional classes,
flavors: Micro Edition (J2ME), Java 5.0 (known as"Tiger"')
~
> Standard Edition (J2SE) and added major changes to ....
«l '-
~ Enterprise Edition (J2EE). the language itself, making 2
a.
'0 Becomes the langutlge of it easier (at least in theory) III
s:
~ chola for new enterprise for programmers and giving o
.s
01
(especially web-based) and
mobile applications.
it new features that were
popular in other languages.
:c ~
dive In A Quick Dip

Look how easy It


Try to guess what each line of code Is doinq.;
is towrite Java. (answersare on the next page),

.int size = 27;


String name = UFido";
Dog rnyDog = new Dog(name, size);
x = size - 5j
if (x < 15) rnyDog.bark(8);

while (x > 3) {
myDog.play();
}

.int [ ] nurnList = {2,4,6,S};


System. out. print ( u Be110" ) ;
System.out.print(UDog: U + name);
String nurn = US";
int Z = Integar.parselnt(nurn);

-:.....-y {
readTheFila(UrnyFile.txt H ) ;

catch(FileNotFoundException ex) {
syetem.out.print(UFile not found.");
}

once again that the changes were so dramatic that a


Q..: I see Java 2 and Java 5.0, but was there a Java 3 new name was needed (and most developers agreed), so
-.d 41 And why Is It Java 5.0 but not Java 2.07 they looked at the options. The next number In the name
sequence woul d be ·3: but caIIing Java 1.5 Java 3 seemed
more confusing, so they decided to name It Java 5.0 to
: The joys of marketing... when the version of Java match the "5~ in version "l.S~
ed from 1.1 to 1.2, the changes to Java were so So, the original Java was versions 1.02 (the first official
rna t ic that the marketers decided we needed a whole release) through 1.1 were just "Java" Versions 1,2,1.3, and
"name: so they started calling It Java 2, even though 1.4 were "Java 2~ And beginning with version 1.5, Java is
actual version of Java was 1.2. But versions 1.3 and 1.4 called "Java 5.0~ But you'll also see it called "Java 5· (without
ftfe still considered Java 2. There never was a Java 3 or the ",0") and "Tiger" (its original code-name). We have no
~_ Be9inning with Java version 1.5,the marketers decided idea what will happen with the next release...

you are here ~ 5


.'
why Java Is cool

pen your pencil answers

Don't wotry about whether you understand any ofthis yeti


look how easy It Everything here Is explained in great detall!n the book, most
Is towrite Java. within the first 40 pages).If Java resembles a language you've
used in the past, some of th is will be simple. If not, don't worry
about it. We'llget there...

int size::; 27;


String name = #FidoHj dett.rt ~ ~~ of l~,)lW1"aridbl, Nlr.ed '~ ..c' ~r.d ~i'" it ~ ."Iot "Fido'
Dog myDog ::; new Dog (name, size); du.lm .1 _ D~ v~blc '..yD~' a.v:l ~U ~ _ D~ 1Iii~ (~' ..rod 'siu'
x = size - 5; wbu-att".fro,. 2.1 (.,,,Iot of 'siu') ~,J it to ~ y~bl, ...a",«l'1.'
if (x < 15) myDog .bark(8);

while (x > 3) {
myDog.play ( l ;
}

intl] numList = {2,4,6,8};


System.out.print(HHello R ) ;

System.out.print(HDogl U + name);
String num ::; US";
fnt z = Integer.parselnt(num);

try { try to do ~i~ ...~ybc ~ thi~ 'IlI('l"t try~ isJ,'t ~.lI'.Ued to ~ .


~ ~ tot file IIolMCll "..yFile.bi· (ar .Ii. lust TRy' 1;0 ~e.ld ~ fild
} ..lIS! be the erod of ~ "I:.h~ to try", so r ~lOC.U 'f'" te<Jd &-y Md~Y th~ ..
catch(FileNotFoundException ex) { this ~ be wkrt Oil fi,.o Nt ~ u.e tho h-led did,,'i warle._
System.out.print(HFile not found."); ~ !he I:.hi~ u-ied t~iled , rri"t "Fil, root fOllNl" out at the ~-liM
'Ill(

} locks li~ t"Icryl:.hi~ i" the { } is wlIat to do ~ the 'fry' did,,'t ~ ...

6 chapter 1
dive In A Quick Dip

Code structure i., Java

public class Dog {


What goes in a
source file?
A source code file (with the .java
extension) holds one class defini-
tion. The class represents a piece
of your program, although a very
tiny application might need just
a single class. The class must go
within a pair of curly braces. class

Put a class in a source file. What goes in a public class Dog {


class? void bark () {
Put methods in a class.
A class has one or more methods.
In the Dog class, the bark method
Put statements In a method. will hold instructions for how the
Dog should bark. Your methods
must be declared inside a class
(in other words, within the curly
braces of the class). tttefho~

public class Dog l


What goes In a
method? void bark () {
s ta temen tl ;
Within the curly braces of a
method, write your instructions statemen t2 ;
for how that method should be
performed. Method code is basi-
cally a set of statements, and for }
now you can think of a method sfafetttet1fs
kind of like a function or proce-
dure.

you ar e here • 7
a Java class

Attafottty of aclass
When thejVM starts running, it looks for the class you give it at the com-
mand line. Then it starts looking for a specially-Written method that looks
exactly like:
public static void main (String() argsl (
II your code goes here

Next, theJVM runs everything between the curly braces { }of your main
method. EveryJava application has to have at least one class. and at least
one main method (not one main per class;just one main per applU:ation).

DOI'l'i warry aW ",e"'O'riz.j..~ a..yt.hiIl9 \"'i~ht l'IOW ...

this tholf'W" is }st to ~d yC'J. sta....ud.

8 chapter 1
dive In A Quick Dip

Writi"Q aclass with amain


InJava, everything goes in a class. You'll type your source code file (with a
.java extension), then compile it into a new class file (with a . class extension).
When you run your program, you're really running a class.
Running a program means telling the Java VIrtual Machine (JVM) to "Load the
Hello class, then start executing its main () method. Keep running 'til all the
code in main is finished."
In chapter 2. we go deeper into the whole class thing, but for now, all you need to
think is, how cUJ 1 writeJava code $0 that it will run 1 And it all begins with mainf).
The mamO method is where your program starts running.
No matter how big your program is (in other words, no matter how many classes
your program uses), there's got to be a mainO method to get the ball rolling.

public class MyFirst.Aflp ( o Save


MyFirstApp. java
public static void main (strinq[] arqs)
Systall.out.priJ)t1n("I Ma!H);
System. out . println ('''l.'be World") ;
)
o Compile
javac MyFirstApp.java

-
MyFlrstApp.Java
~~
4t.. ,,\~ E)Run
~
t %j a va MyFirstApp
I Rule!
''''''
The World

MyFlratApp.clau
-
you are here ~ 9
statements, looping, branching

What ca., you say I., the",al., ",ethod1


Once you 're inside main (or any method), the fun
begins. You can say all the normal things that you say
in most programming languages to make the computer
do something.
Your code can tell the JVM to :

o do solttethi.,g
Statements: declaratlons, assignments.
method calls.etc,
int x ~ 3;
String name = ~Dirk";
x = x * 17;
System .ouc .print("x is " + x);
double d = Math.random();
II this is a comment
Syntax
Fun
e do solttethlttQ agal., and agal"
Loops: (or and while
while (x > 12)
x = )( - 1; .. Each statement must end in a
semicolon.
x=x+1;
for (int x ee 0; x < 10; x = x + 1) (
System.out.print("x is now + x); II
.. A single-line comment begins
with two forward slashes.

e do solttethlttQ uttder this CO.,dltlon


Branching: If/else tests
x = 22;
II this line disturbs me

if (x == 10) 1 .. Most white space doesn't maner.


System.out.print("x mUSt be 10"); x 3
else {
System.out.print("x isn 't lO ll); .. Variables are declared with a
name and a type (you'll learn about
if «x < 3) & (name.equals("Dirk ll » ) )
all the Java types In chapter 3).
System.out.println(~Gently "); int weight;
Iitype: int, name: weight
System .out.print("this line runs no matter what ll ) ;
.. Classes and methods must be
deflned within a pair of curly braces.

public void go ( ) (
II amazing code here
}

10 chapter 1
dive In A Quick Dip

while (more Balls == true) {


keepJugg/ing() ;
}

ShMple boolean tests


.» You can do a simple boolean test by checking
Loopit1g a.,d loopi.,g at'd... the value of a variable, using a comparison operator
including:
Java has three standard Looping constructs: uihile;
do-iahile, and for. You'll get the full loop scoop later < (less than)
in the book, but not for awhile, so let's do whi~for
> (greater than)
now.
The syntax (not to mention logic) is so simple = (equality) (yes, that's two equals signs)
you're probably asleep already. As long as some Notice the difference between the assignment
condition is true, you do everything inside the operator (a single equals sign) and the equals
loop block. The loop block is bounded by a pair of operator (two equals signs). Lots of programmers
curly braces, so whatever you want to repeat needs accidentally type • when they want -. (But not
to be inside that block. you.)
The key to a loop is the conditional test. lnJava, a iot x ~ 4; II assign 4 to x
conditional test is an expression that results in a while > 3) {
(x
boolean vaJue-in other words, something that is II loop code will run because
either true or false.
II x is greater than 3
lfyou say something like , "While i.aCnamlnTMTub x = x-I; II or we'd loop forever
is true; keep scooping", you have a clear boolean
test. There either is ice cream in the cub or there inc z = 27; II
isn't. But if you were to say. "While Bob keep while (z =~ 17)
scooping" , you don't have a real test, To make
II loop code will not run because
that work, you'd have to change it to something
like. "While Bob is snoring... ~ or "While Bob is not II z is not equal to 17
wearing plaid..."
you are here ~ 11
Java basics

Exall1ple of a while loop


public class Loopy {
Q: Whydoes everything have
public static void main (String[] args) (
to be In a dass7
int x .. 1;

A: ~ava is an object-oriented
(00) language. It's not Iikethe
System.out.println("Before the Loop");
while (x < 4) {
System.out.println("In the loop");
old days when you had steam-
System.out .prlntln("Value of x is " + x);
driven compliers and wrote one
monolithic source file with a pile x = x + 1;
of procedures. In chapter 2 you'll )
learn that a class Is a blueprint for System.out.println("This is after the loop");
an object, and that nearly every-
thing in Java Is an object.

Q: Do I have to put a main In % java Loopy


every class I write1 Before the Loop
In the loop

A: Nope .A Java prog ram


might use dozens of classes (even
Va.lue
In the loop
ot x is 1

hundreds), but you might only Va.lue of x i8 2


have one with a maIn method- In th8 loop
the one that starts the program Value of x is 3
running.You might wrIte test
This is aft.r the loop
classes, though, that have main
methods for testing your other

POI~
classes,
, - - - - - - BULLD ----------,
Q: In my other language I can
• Statements end ina semicolon;
do a boolean test on an Integer.
In Java, can I say something like: • Code blocks are defined by apair of cu~y braces { }
int x .. 1;
• Declare an int variable with a name and a type: Intx;
while (J&:) (
• The assignment operator Is one equals sign =
A: No.A boolean and an
integer are not compatible types In
• The equals operator uses two equals signs ==
• Awhile loop runs everything within its block (defined by cu~y
Java. Since the result of a condi-
tional test must be a boolean, the
braces) as long as the conditional test Is true.
only varIable you can directly test • If the conditional test is fa1S8, the while loop code block won't
(without using a comparison op-
run, and execution will move down to the code Immediately
erator) Is a boolean. For example,
efterthe loop block.
you can say:
boolean isBot • true; • Put a boolean test Inside parentheses:
while (x = 4) ( }
while (llIHot) ( )

12 chapter 1
dive In A Quick Dip

Conditlo"al bra"chl"Q
Java, an if test is basically the same as the boolean test in a
'le loop - except instead of saying, ~UJhile there's still beer.,",
u ']] say, ~ifthere's still beer.,"
cLa s s I f Test (
public static void main (String[) args) {
int x = 3;
i f (x == 3)
System.out.println("x must be 3 H ) ;

System.out .println( "This runs no matter what");

, java If'rest
JI: must be 3
This runs no matter what
Glv~n the output:
The code above executes the line that prints "x must be 3" only
if the condition (x is equal to 3) is true. Regardless of whether % javaDooBee
it's true, though, the line that prints, "This runs no matter what" DooBeeDooBeeDo
~ill run. So depending on the value of x; either one statement
or two will print out. FJIIln th~ missing code:

But we can add an else to the condition, so that we can public class DooBee {
say something like, "Iftbere's still beer, keep coding, else
public static void main (StringO args) I
(otherwise) get more beer, and then continue on..."
intx=l;
::lass IfTest2 { while (x < _ _ }{
public static void main (String!) a rqs ) ( System.out. ("Doo");
int x = 2;
System.out. (MBee");
i f (x == 3)
System.out.println("x must be 3 H ) ; x = x + 1;
else ( }

System.out.println("x is NOT JH); If(x== _ _ }{


H
System.o ut.pri nt("Do };

System.out.println("This runs no matter what ");


I
}

, java If'l'est2
II is ~ 3
'1'hi1 runs no matter what

you are here ~ 13


serious Java app

Coding aSerious fushtess


Applicatfott
Let's put all your"new Java skills to good use with
something practical. We need a class with a mains); an int
and a String variable. a whik loop, and an if test. A little
more polish, and you'll be building that business back-
end in no time. But beJoreyou look at the code on this
page, think for a moment about how youwould code that
classic children's favorite, "99 bottles of beer."

pUblic class BeerSong (


public static void main (String[) args) (
int beerNum 99;
String word ~ "bottles";

while (beerNum > 0) I

if (beerNum == 1) (
word - "bottle H ; II s i ng ul a r , as in ONE bo ttl e .

System.out.println(beerNum + " H + word + " of beer on the wall H ) ;

System.out.println(beerNum + " H + word + " of beer.");


System.out.println("Take one down. H ) ;
System .out .println( "Pass it around. ") ;
beerNum = beerNum - 1;

if (beerNum > 0) (
System.out .println(beerNum + " H + word + " of beer on che wall H ) ;

else (
System.out.println("No more bottles of beer on the wall H ) ;
) II end else
f II end while loop
) II end main method
II en~ class

There's stili one little flaw In our


code. It complies and runs. but the
output Isn't 100% perfect. See If
you can spot the flaw, and fix It.

14 chapter 1
dive In A Quick Dip

Bob's alarm clock rings at 8:30 Monday morning, just like every other weekday.
But Bob had a wild weekend, and reaches for the SNOOZE button.
And that's when the action starts, and the Java-enabled appliances
come to life.
First, the alarm clock sends a message to the coffee maker* "Hey, the geek's
sleeping in again , delay the coffee 12 minutes."
The coffee maker sends a message to the Motorola'>'
toaster, "Hold the toast, Bob's snoozing." ( -
The alarm clock then sends a message to Bob's
Nokia Navigator™ cell phone, "Call Bob's 9
o'clock and tell him we're running a little late."
Finally, the alarm clock sends a message to
Sam's (Sam is the dog) wireless collar, with the too-familiar signal that
means, "Get the paper, but don't expect a walk."
A few minutes later, the alarm goes off again . And again Bob
hits SNOOZE and the appliances start chattering. Finally,
the alarm rings a third time. But just as Bob reaches for the
sn ooze button, the clock sends the "jump and bark" signal to Sam's
collar. Shocked to full consciousness, Bob rises, grateful that hisJava
skills and a Little trip to Radio Sbackn< have enhanced the daily
routines of his life.
His toast is toasted.
His coffee steams.
His paper awaits.
Just another wonderful morning in TheJava--ErUlbled HOMSB.
You can have aJava~enabledhome. Stick with a sensible solution using Java,
Ethernet, andJini technology. Beware of imitations using other so-called "plug
and play" (which actually means "plug and play with it for the next three days
trying to get it to work") or "p ortable" platforms. Bob 's sister Berry Died one of
those others, and the results were, well, not very appealing, or safe.
Bit of a shame about her dog, too...

Could this story be true? Yes and no.While there are versions of Java running in de-
vices Including PDAs, cell phones (especially cell phones), pagers, rings, smart cards,
and more -you might not find a Java toaster or dog collar. But even jf you can't
find a Java-enabled version of your favorite gadget. you can stili run it as if it were a
Java device by controlling it through some other Interface (say, your laptop) that is
runnIng Java.This Is known as the Jini surrogate architecture. Y~ you con have that
geek dream home.

·IPmulticast If you're gonna be all picky about protocol

you are her e ~ 15


let's write a program

Try my new
phrase-a-matic and
you'll be a slick talker
just like the boss or
those guys in marketing.

public class PhraseQlatic (


public static void main (String(l args) {

/ / iliaD thNt sets of words to choose from. leW yoar own!


String[] wordListOne ::: {"24/7" /'multi-
Tiar","30,OOO foot", "B-to-B" , "win-win" , "front-
end" , "web- based" , "pervasive", "smart", "six-
sigma", " cri tical -path" , "dynamic"} j

Strinq[] wordListTwo ::: I "empowered", "sticky",


"value-added.", "oriented", "centric", "distributed",
"clustered", "branded", "outaide-the-box", ''positioned'',
"networked", " f ocused" / "leveraged", "aligned",
"targeted", "shared" / "cooperative", "accelerated"};

Strinq[] wordListThree = {"process", "tipping-


OK, so the beer song wasn't really a serious
business application. Still need something
point", "solution", "architecture", "core competency" ,
practical to show the boss? Check out the "strategy", "mindshare", "portal" , "apace" / "vision",
Phrase-O-Matlc code. '~adigm", ~ssion"};

/ / find out !low many word. aN In ...d11bt


iot one.Lenqth '" wordListOne . length;
int twoLength '" wordListTwo .length;
int threeLength =
wordListThree.lenqthj

/ / generate .... random numbers


int randl :lII (int) (Math.random() '" ooeLenqth) j
int rand2 ::: (int) (Math .randomO • twoLength);
int rand3 '" (int) (Math.randa:n() " threeLength);

O //now build a pllrue


String phrase'" wordListOne [randl] + " " +
wordListTwo[rand2] + " " + wordListTbree[rand3] ;

/ / print oat the phra..


Sys.tem.out.println("What we need is a " + phrase);
}

16 ch apter 1
dive In A Quick Dip

Phrase.. O.. Matlc


low Itworks,
In a nutshell, the program makes three lists of words, then randomly picks one word
from each of the three lists; and prints out the result, Don't worry if you don't under-
m.nd exactly what's happening in each line. For gosh sakes, you've got the whole book
~d of you, so relax. This isjust a quick look from a 30,000 foot outside-the-box
a.rgeted leveraged paradigm.

i. The first step is to create three String arrays - the containers that will hold all the
-..ords . Declaring and creating an array is easy; here's a small one:

bch word is in quotes (as all good Strings must be) and separated by commas.

• For each of the three lists (arrays), the goal is to pick a random word, so we have
know how many words are in each list, If there are 14 words in a list, then we need
random number between 0 and 13 (Java arrays are zero-based, so the first word is at
ition 0, the second word position I, and the last word is position 13 in a 14-element what we need
here Is a •••
~') . Quite handily, ajava array is more than happy to tell you its length. You just
to ask. In the pets array, we'd say.
sat z =: pets . length ; pervasive targeted
z would now hold the value 3. process

, . We need three rand~m numbers. Java ships out-of-the-box, off-the-shelf, shrink- dynamic outside-
the-box tipplng-
pped, and core competent with a set of math methods (for now, think of them as
point
ctions). The random () method returns a random number between 0 and not-
'te-l , so we have to multiply it by the number of elements (the array length) in the
we're using. We have to force the result to be an integer (no decimals allowed!) so smart distributed
put in a cast (you'll get the details in chapter 4). It's the same as ifwe had any float- core competency
point number that we wanted to convert to an integer.
~t z • (int) 24.6;
24/1 empowered
mindshare
ow we get to build the phrase, by picking a word from each of the three lists,
smooshing them together (also inserting spaces between words). We use the ,,+n
30,000 fool win-win
rator, which concatenaus (we prefer the more technical' S1TU>OShes') the String objects
vision
ether. To get an element from an array, you give the array the index number (posi-
- n) of the thing you want using:
SUinq s '" pet. [0 l : / / s is now the String "FiOO" stx-slqrna net-
.... + " " + "is a dog"; / / • is now "Fido ill a dog" worked portal

5. Finally, we print the phrase to the command-line and... voila I Wen in marketing.
you are here ~ 17
the complier and the JVM

Fireside Chats Ton1gb.t's Talk: The compller and

~
~e JVM battle over the question.
"Who's more lmportaJlU"

!he Java Vlrtual Machine The Complier


What, are you kidding? HELLO. I amJava.
I'm the guy who actually makes a program
run. The compiler just gives you a file. That's
it. Just a file. You can print it out and use it
for wall paper, kindling, lining the bird cage
whateuer, but the file doesn't do anything un-
less I'm there La run it.
I don't appreciate that tone.
And that's another thing. the compiler has
no sense of humor. Then again. if ycm had to
spend all day checking nit-picky little syntax
violations... Excuse me, but without me, what exactly
would you run? There's a TMSonJava was
designed to use a bytecode compiler, for your
information. IfJava were a purely interpreted
language, where-s-at runtime-s-the virtual
machine had to translate straight-from-a-text-
editor source code, a java program would
run at a ludicrously glacial pace. java's had a
challenging enough time convincing people
that it's finally fast and powerful enough for
I'm not saying you're, like, complmly useless. mostjobs.
But really, what is it that you do? Seriously. I
have no idea. A programmer could just write
bytecode by hand, and I'd take it. You might
be out ofajob soon, buddy.
Excuse me, but that's quite an ignorant (not
to mention arrogant) perspective. While it
is true that-tJuoretically--you can run any
properly formatted bytecode even if it didn't
come out of a Java compiler, in practice that's
absurd. A programmer writing bytecode by
hand is like doing your word processing by
writing raw postscript. And I would appreciate
it if you would not refer to me as "buddy."
(I rest my case on the humor thing.) But you
still didn't answer my question, what do you
actually do?

18 chapter 1
dive In A Quick Dip

The Java Virtual Machine The Compiler


Remember thatJava is a strongly-typed lan-
guage, and that means I can't allow variables
to hold data of the wrong type. This is a
crucial safety feature, and I'm able to stop the
But some still get through! I can throw Class- vast majority of violations before they ever get
CastExceptions and sometimes I get people to you. And I also-
trying to put the wrong type of thing in an
array that was declared to hold something
else, and-
Excuse me, but I wasn't done. And yes, there
are some datatype exceptions that can emerge
at runtime, but some of those have to be
allowed to support one ofJava's other impor-
tant features--dynamic binding. At runtime,
aJava program can include new objects that
weren't even known to the original program-
mer, so I have to allow a certain amount of
flexibility. But my job is to stop anything that
would never-could never-succeed at run-
time. Usually I can tell when something won 't
work, for example, if a programmer acciden-
tally tried to use a Button object as a Socket
connection, I would detect that and thus
OK. Sure. But what about security? Look at all protect him from causing harm at runtime.
the security stuff I do , and you're like, what,
checking for semicolons? Oooohhh big security
risk ! Thank goodness for youl Excuse me, but I am the first line of defense,
as they say. The datatype violations I previous-
ly described could wreak havoc in a program
if they were allowed to manifest. I am also
the one who prevents access violations, such
as code trying to invoke a private method, or
change a method that - for security reasons
- must never be changed. I stop people from
touching code they're not meant to see,
including code trying to access another class'
critical data. It would take hours, perhaps days
even, to describe the significance of my work.
Whatever. I have to do that same stuff too,
though, just to make sure nobody snuck in
after you and changed the byte code before
running it.
Of course, but as I indicated previously, if I
didn't prevent what amounts to perhaps 99%
of the potential problems, you would grind to
a halt. And it looks like we're out of time, so

we'll have to revisit this in a later chat.
Oh, you can count on it. Buddy.

you a re here ~ 19
exercise: Code Magnets

Code Magnets
A working Java program is all scrambled up
on the fridge. Can you rearrange the code
snippets to make a working Java program
that produces the output listed below?
Some of the curly braces fell on the floor if (
JC <: <: 1) (
and they were too small to pick up, so feel
free to add as many of those as you need! SYSt.,~
...... OUt .
JC .. ..
·Pr.lnt( "d" ) •
... - 1: '

i f (x == 2) {

class Shuftlel (
public static Void
main(String I) args) (

if pc. > 2) {

sygtem.out.print(~a~);

int x 3;

>r .. x-I;
System. Out .
. pr.l n t(,,_,,);

while (x > 0) {

~
'I., java Shufflel
a-b c-d
dive In A Quick Dip

B
public static void main(String [] args)
int x = 5;
while ( x > 1 )
x = x-I;

"BE the oomriler if ( x < 3) {


System.out.println(~small X~)i

Each of the JIlVll files on this page


represents 11 complete source file.
Your job is to pIa}' cotJ1Piler and
determine whether each of these
files will cottlPile. If-they
won't cottlPile. how
woald you l"lX them?

A
c
class Exerciselb {
~_ass Exerciselb {
int x • 5;
public static void main(String [) args)
while ( x > 1 )
int x '" Ii
x =x - Ii
while ( x < 10
if ( x < 3) (
if ( x > 3) (
System.out.println(~small x~);
systam.out.println(~big X")i

you are here ~ 21


puzzle: crossword

1 2 J

4 S f-

I
Ja~Cr~ss t. O
II ~ '---

8 - 9 10 ~
l..-

let's give your right brain somethIng to do. 2


I- -
It'syour standard crossword, but almost all f- ~ I-- 13
of the solution words are from chapter 1.Just
4 5 6
to keep you awake, we alsothrew in a few
(non-Java) words from the high-tech world.

- - - - ~

18 9

Across I-
20 -
4. Command-line invoker
6. Back again?
L- '--
bL
21
8. Can't go both ways 1 \
9. Acronym for your laptop'S power
12. number variabletype
13. Acronym for a chip Down
14. SaysomethIng 1. Not an integer (or _ _ your boat)

18. Quite a crew of characters 2. Come back empty-handed

19. Announce a new class or method 3. Open house

21. What'sa prompt good for? 5. 'ThIngs' holders


7. Until attitudes improve
10. Sourcecode consumer
11 . Can't pin it down
13. Dept. of LANJockeys
1S. Shocking modifier
16. Justgona haveone
17. How to get things done
20. Bytecode consumer

22 chapter 1
dive In A Quick Dip

A short Java program is listed below. One block of the program


is missing. Your challenge is to match the candidate block of
code (on the left),with the output that you'd see if the block
were inserted. Not all the lines of output will be used, and some
of the lines of output might be used more than once. Draw lines
connecting the candidate blocks of code with their matching
command-line output. (The answers are at the end of the chapter).

class Test {
public static void main (String [) args)
int x 0;
int y = 0;
while x < 5 )

System.out.print(x + "" + y +" ");


x = x + 1;

candidates: Possible output:

00 11 21 32 42

lJ. 21 32 42 53

00 11 23 36 410

02 14 25 36 41

you are here ~ 23


puzzle: Pool Puzzle

class PoolPu2zleOne {
public static void main(String (I arga) {
int x = OJ
P~l puzzle while ( ) {
Your job is to take code snippets from the
pool and place them into the blank
lines in the code. You may not use the
if ( x < 1 ) {
same snippet more than once,and
you won't need to use all the snip-
}
pets. Your goal is to make a cia 5S that
will compile and run and produce the
output listed. Don't be fooled-this one's
harder than it looks. if ( ) {

Output }
if ( x 1 ) {

%java PoolPuzzleOne
a noise }
if ) {
annoys
an oyster
}
System.out.println("");

Note: Each snippet


from the pool can be
used only oncel

24 chapter 1
dive In A Quick Dip
class Exercise1b {
public static void main(String I] arqs) {
int x = 1;
while ( x < 10 )
x=x+l;
if ( x > 3) {
A
System.out.println("big x")j

e Magnets:
__~ss Shuftlel {
~~lic static void main(String (J args) {
This will compile and run (no output), but
} without Q line added to the program, it
int x = 3; would run forever inan infinite 'while' loop!
....nile (x > 0) {

i f (x > 2) {
Systern.out.print(Ua")i
class Foo {
}
public static void main(String I] args) {
x = x - Ij int x = s;
System.out.print("-"); while ( x > 1 )
x =x - Ii
i f (x == 2) { B if ( x < 3) {
systern.out.print(Nb e")j
system.out.println("small x");
}

i f (x == 1), { This file won't compile without 0


Systern.out.print("d")j } class d~c1Qratlon, and don't forget
x = x - Ij ) the matching curly brace!
}
}

class Exerciss1b {
public static void main(String Uargs) {
int x = Sj
j a v a Shuffle!
while ( x > 1
a- b c - d
x .. x - 1;
C if ( x < 3)
System.out.println(~smallX·]i

The 'while' loop code must be in-


} side a method. It can't just be
hanging out inside the class.

you are here ~ 25


puzzle answers

fF IV
-P
•J s
'L 0 0 p
A V A
R
,,- -U
W .E- I
-B
D It 'V
IS
B R A IN C H A
'"- l
A 1: N T 0 A I
- - - It
Y L M R t
's y s ir
8
E M a u T P R r N T
L.

I
class PoolPuzzleOne {
public static void main(String (] args) {
-
T
A
A
-
I
-
L
-AB ~
M
~

int x == 0; 18
S T R I N G
9
D E C L A R e
while ( X • 4 ) { I R E T
f-- f--
~J
System.out. prlntf'Q'');
C
'---- - -H
if ( x < 1 ) { V 0
System.out.prirrt( "): 11 C 0 M M A N D
}
System.out .prlrrt(n"); class Tesc I
public scat:ic void main (Scr ing [ 1 args) (
if(X>l){ i n c l< ~ 0;
i n c y - 0;
wh i Ie ( x < 5 l (
System.out. prfnt(' oyster");
x =x + 2;
}
i f ( x == 1 ) { Syscern .ou c.print( x · -" • y .- "I;
x = x + 1;
System. out. prfnt('noysj;
}
if ( X • 1 ) {
"""slble output:

Syst£ln. out. prlnt('olsej;


}
System.out.println(UU);

X =X + 1; 'y j ava PoolPuzzl c One


}
Ct noise
}
anno~'s
} an o ~'s t e r

32 U 53
.I.f I Y < 5 )
II - X + 1,
UIy<3
:It - x-II

)
1. • Y. + 2.
26 ch apter 1
2 classes and objects

A Trip to Objectville

We’re going to
Objectville! We’re
leaving this dusty ol’
procedural town for good.
I’ll send you a postcard.

I was told there would be objects. )NCHAPTER WEPUTALLOFOURCODEINTHE


MAIN METHOD4HATSNOTEXACTLYOBJECT ORIENTED)NFACT THATSNOTOBJECT ORIENTEDATALL7ELL
WEDIDUSEAFEWOBJECTS LIKETHE3TRINGARRAYSFORTHE0HRASE / -ATIC BUTWEDIDNTACTUALLY
DEVELOPANYOFOUROWNOBJECTTYPES3ONOWWEVEGOTTOLEAVETHATPROCEDURALWORLDBEHIND
GETTHEHECKOUTOFMAIN ANDSTARTMAKINGSOMEOBJECTSOFOUROWN7ELLLOOKATWHATMAKES
OBJECT ORIENTED// DEVELOPMENTIN*AVASOMUCHFUN7ELLLOOKATTHEDIFFERENCEBETWEEN
ACLASSANDANOBJECT7ELLLOOKATHOWOBJECTSCANGIVEYOUABETTERLIFEATLEASTTHEPROGRAM
MINGPARTOFYOURLIFE.OTMUCHWECANDOABOUTYOURFASHIONSENSE 7ARNINGONCEYOUGET
TO/BJECTVILLE YOUMIGHTNEVERGOBACK3ENDUSAPOSTCARD

this is a new chapter 27


once upon a time in Objectville

Chair Wars
(or How Objects Can Change Your Life)
the spec

O
NCEUPONATIMEINASOFTWARESHOP TWO
PROGRAMMERSWEREGIVENTHESAMESPECANDTOLDTO
hBUILDITv4HE2EALLY!NNOYING0ROJECT-ANAGER
FORCEDTHETWOCODERSTOCOMPETE
BYPROMISINGTHATWHOEVERDELIVERS
lRSTGETSONEOFTHOSECOOL!ERON©
CHAIRSALLTHE3ILICON6ALLEYGUYSHAVE
,ARRY THEPROCEDURALPROGRAMMER AND
"RAD THE//GUY BOTHKNEWTHISWOULD
BEAPIECEOFCAKE
,ARRY SITTINGINHISCUBE THOUGHTTO
HIMSELF h7HATARETHETHINGSTHISPROGRAM
HASTODO7HATPROCEDURESDOWENEEDv
!NDHEANSWEREDHIMSELF hROTATEAND
PLAY3OUNDv3OOFFHEWENTTOBUILDTHE
PROCEDURES!FTERALL WHATISAPROGRAMIFNOT
APILEOFPROCEDURES
"RAD MEANWHILE KICKEDBACKATTHECAFE
ANDTHOUGHTTOHIMSELF h7HATARETHETHINGS
INTHISPROGRAMWHOARETHEKEYPLAYERSv(E
lRSTTHOUGHTOF4HE3HAPES/FCOURSE THERE
WEREOTHEROBJECTSHETHOUGHTOFLIKETHE5SER THE3OUND
ANDTHE#LICKINGEVENT"UTHEALREADYHADALIBRARYOFCODE
FORTHOSEPIECES SOHEFOCUSEDONBUILDING3HAPES2EAD
ONTOSEEHOW"RADAND,ARRYBUILTTHEIRPROGRAMS AND the chair
FORTHEANSWERTOYOURBURNINGQUESTION h3O WHOGOTTHE
!ERONv

In Larry’s cube At Brad’s laptop at the cafe


!SHEHADDONEAGAZILLIONTIMESBEFORE ,ARRY "RADWROTEACLASSFOREACHOFTHETHREESHAPES
SETABOUTWRITINGHIS)MPORTANT0ROCEDURES
(EWROTEROTATEANDPLAY3OUNDINNOTIME
rotate(shapeNum) {
// make the shape rotate 360º
}
playSound(shapeNum) {
// use shapeNum to lookup which }
// AIF sound to play, and play it
}
}
}

28 chapter 2
classes and objects

Larry thought he’d nailed it. He could almost feel the rolled
steel of the Aeron beneath his...

But wait! There’s been a spec change.


h/+ TECHNICALLYYOUWERElRST ,ARRY vSAIDTHE-ANAGER hBUTWEHAVETOADDJUSTONE
TINYTHINGTOTHEPROGRAM)TLLBENOPROBLEMFORCRACKPROGRAMMERSLIKEYOUTWOv
h)F)HADADIMEFOREVERYTIME)VEHEARDTHATONEv THOUGHT,ARRY KNOWINGTHATSPEC
CHANGE NO PROBLEMWASAFANTASYh!NDYET"RADLOOKSSTRANGELYSERENE7HATSUPWITH
THATv3TILL ,ARRYHELDTIGHTTOHISCOREBELIEFTHATTHE//WAY WHILECUTE WASJUST
SLOW!NDTHATIFYOUWANTEDTOCHANGEHISMIND YOUDHAVETOPRYITFROMHISCOLD
DEAD CARPAL TUNNELLEDHANDS
shape
l b e a n amoeba rs.
There wil en, with the othe what got added to the spec
r e
on the sc ser clicks on the
t h e u ke the
When il l rotate li und file 
a , it w
amoeb .hif so
t h e r s , a nd play a
o

Back in Larry’s cube At Brad’s laptop at the beach


4HEROTATEPROCEDUREWOULDSTILLWORKTHECODEUSED "RADSMILED SIPPEDHISMARGARITA ANDWROTEONE
ALOOKUPTABLETOMATCHASHAPE.UMTOANACTUAL NEWCLASS3OMETIMESTHETHINGHELOVEDMOST
SHAPEGRAPHIC"UTPLAY3OUNDWOULDHAVETOCHANGE ABOUT//WASTHATHEDIDNTHAVETOTOUCHCODE
!NDWHATTHEHECKISAHIFlLE HEDALREADYTESTEDANDDELIVEREDh&LEXIBILITY
playSound(shapeNum) { EXTENSIBILITY vHEMUSED REmECTINGONTHE
// if the shape is not an amoeba, BENElTSOF//
// use shapeNum to lookup which Amoeba
// AIF sound to play, and play it rotate() {
// else // code to rotate an amoeba
// play amoeba .hif sound }
}
playSound() {
)TTURNEDOUTNOTTOBESUCHABIGDEAL BUTITSTILL
// code to play the new
MADEHIMQUEASYTOTOUCHPREVIOUSLY TESTEDCODE/F // .hif file for an amoeba
ALLPEOPLE HESHOULDKNOWTHATNOMATTERWHATTHE }
PROJECTMANAGERSAYS THESPECALWAYSCHANGES

you are here4 29


once upon a time in Objectville

Larry snuck in just moments ahead of Brad.


(AH3OMUCHFORTHATFOOFY//NONSENSE "UTTHESMIRKON,ARRYSFACEMELTEDWHENTHE
2EALLY!NNOYING0ROJECT-ANAGERSAIDWITHTHATTONEOFDISAPPOINTMENT h/H NO THATSNOT
HOWTHEAMOEBAISSUPPOSEDTOROTATEv
4URNSOUT BOTHPROGRAMMERSHADWRITTENTHEIRROTATECODELIKETHIS
1) determine the rectangle that surrounds the shape
2) calculate the center of that rectangle, and rotate the shape around that point.
"UTTHEAMOEBASHAPEWASSUPPOSEDTOROTATEAROUNDAPOINTONONEEND LIKEACLOCKHAND
h)MTOASTvTHOUGHT,ARRY VISUALIZINGCHARRED7ONDERBREAD©h!LTHOUGH HMMMM)COULD
JUSTADDANOTHERIFELSETOTHEROTATEPROCEDURE ANDTHENJUSTHARD CODETHEROTATIONPOINT
CODEFORTHEAMOEBA4HATPROBABLYWONTBREAKANYTHINGv"UTTHELITTLEVOICEATTHEBACKOF
HISHEADSAID h"IG-ISTAKE$OYOUHONESTLYTHINKTHESPECWONTCHANGEAGAINv

Larry
r o t a t io n point in
Ameoba version:
’s
and Brad
What the spec conveniently
forgot to mention

tatio n
e r e t h e ameba ro
Wh
uld be:
point sho

Back in Larry’s cube At Brad’s laptop on his lawn


(ElGUREDHEBETTERADDROTATIONPOINTARGUMENTS chair at the Telluride Bluegrass Festival
TOTHEROTATEPROCEDURE!LOTOFCODEWASAFFECTED 7ITHOUTMISSINGABEAT "RADMODIlEDTHEROTATE
4ESTING RECOMPILING THEWHOLENINEYARDSALLOVER METHOD BUTONLYINTHE!MOEBACLASS(ENEVER
AGAIN4HINGSTHATUSEDTOWORK DIDNT TOUCHEDTHETESTED WORKING
rotate(shapeNum, xPt, yPt) { COMPILEDCODEFORTHEOTHER Amoeba
// if the shape is not an amoeba, PARTSOFTHEPROGRAM4O int xPoint
// calculate the center point GIVETHE!MOEBAAROTA int yPoint
TIONPOINT HEADDEDAN rotate() {
// based on a rectangle,
ATTRIBUTETHATALL!MOEBAS // code to rotate an amoeba
// then rotate WOULDHAVE(EMODI // using amoeba’s x and y
// else lED TESTED ANDDELIVERED }
// use the xPt and yPt as WIRELESSLY THEREVISED playSound() {
// the rotation point offset PROGRAMDURINGASINGLE // code to play the new
"ELA&LECKSET // .hif file for an amoeba
// and then rotate }
}
30 chapter 2
classes and objects

So, Brad the OO guy got the chair, right ?


.OTSOFAST,ARRYFOUNDAmAWIN"RADSAPPROACH!ND
SINCEHEWASSURETHATIFHEGOTTHECHAIRHEDALSOGET,UCY
INACCOUNTING HEHADTOTURNTHISTHINGAROUND
,!2299OUVEGOTDUPLICATEDCODE4HEROTATE
PROCEDUREISINALLFOUR3HAPETHINGS
"2!$)TSAMETHOD NOTAPROCEDURE!NDTHEYRECLASSES
NOTTHINGS
,!2297HATEVER)TSASTUPIDDESIGN9OUHAVETO
MAINTAINFOURDIFFERENTROTATEhMETHODSv(OWCANTHAT
EVERBEGOOD
"2!$/H )GUESSYOUDIDNTSEETHElNALDESIGN,ETME
SHOWYOUHOW//INHERITANCEWORKS ,ARRY
What Larry wanted
(figured the chair would impress her)

1
Square Circle Triangle Amoeba
I looked at what all four
rotate() rotate() rotate() rotate() classes have in common.
playSound() playSound() playSound() playSound()

2
They’re Shapes, and they all rotate and Shape
playSound. So I abstracted out the
common features and put them into a
rotate()
playSound()
3
new class called Shape. Then I linked the other
Shape
superclass four shape classes to
rotate()
playSound() the new Shape class,
in a relationship called
inheritance.
You can read this as, “Square inherits from Shape”,
“Circle inherits from Shape”, and so on. I removed subclasses
rotate() and playSound() from the other shapes, so now
there’s only one copy to maintain.
Square Circle Triangle Amoeba
The Shape class is called the superclass of the other four
classes. The other four are the subclasses of Shape. The
subclasses inherit the methods of the superclass. In other
words, if the Shape class has the functionality, then the
subclasses automatically get that same functionality.
you are here4 31
once upon a time in Objectville

What about the Amoeba rotate()?


,!2297ASNTTHATTHEWHOLEPROBLEMHEREˆTHATTHEAMOEBASHAPE
HADACOMPLETELYDIFFERENTROTATEANDPLAY3OUNDPROCEDURE
rride Now
"2!$-ETHOD ve

O
,!2297HATEVER(OWCANAMOEBADOSOMETHINGDIFFERENTIF
As w
IThINHERITSvITSFUNCTIONALITYFROMTHE3HAPECLASS k Me Ho

"2!$4HATSTHELASTSTEP4HE!MOEBACLASSOVERRIDESTHE
METHODSOFTHE3HAPECLASS4HENATRUNTIME THE*6-KNOWSEXACTLY
WHICHROTATE METHODTORUNWHENSOMEONETELLSTHE!MOEBATOROTATE

superclass
(more abstract)
Shape 4
rotate()
playSound()
madethe
I Imade Amoebaclass
theAmoeba override
classoverride
the and playSound()
rotate()method
therotate() of the
methods of the
superclass Shape. superclass Shape.
subclasses justmeans
Overridingjust thataa
meansthat
(more specific) Overriding
subclassredefines
subclass oneof
redefinesone its
ofits
inherited methods when it
inherited methods when it needs needs
Square Circle Triangle Amoeba to change or extend the behavior
to change or extend the behavior
of method.
thatmethod.
ofthat
rotate() {
// amoeba-specific
// rotate code {
Overriding methods
playSound() {
// amoeba-specific
// sound code {

I can take
,!229(OWDOYOUhTELLvAN!MOEBATO
care of myself.
DOSOMETHING$ONTYOUHAVETOCALLTHE I know how an Amoeba
PROCEDURE SORRYˆMETHOD ANDTHENTELLIT I know how a Shape is is supposed to rotate
WHICHTHINGTOROTATE supposed to behave. Your and play a sound.
job is to tell me what to
"2!$4HATSTHEREALLYCOOLTHINGABOUT//
do, and my job is to make it happen.
7HENITSTIMEFOR SAY THETRIANGLETOROTATE Don’t you worry your little program-
THEPROGRAMCODEINVOKESCALLS THEROTATE mer head about how I do it.
METHODONTHETRIANGLEOBJECT4HERESTOFTHE
PROGRAMREALLYDOESNTKNOWORCAREHOWTHE
TRIANGLEDOESIT!NDWHENYOUNEEDTOADD
SOMETHINGNEWTOTHEPROGRAM YOUJUSTWRITE
ANEWCLASSFORTHENEWOBJECTTYPE SOTHENEW
OBJECTSWILLHAVETHEIROWNBEHAVIOR

32 chapter 2
classes and objects

The suspense is killing me.


Who got the chair?

!MYFROMTHESECONDmOOR
UNBEKNOWNSTTOALL THE0ROJECT
-ANAGERHADGIVENTHESPECTO
THREEPROGRAMMERS

YiX`e
What do you like about OO? gfn\i
4IMETOPUMPSOMENEURONS
“It helps me design in a more natural way. Things 9OUJUSTREADASTORYBOUTAPROCEDURAL
have a way of evolving.” PROGRAMMERGOINGHEAD TO HEADWITHAN//
-Joy, 27, software architect PROGRAMMER9OUGOTAQUICKOVERVIEWOFSOME
KEY//CONCEPTSINCLUDINGCLASSES METHODS AND
ATTRIBUTES7ELLSPENDTHERESTOFTHECHAPTER
“Not messing around with code I’ve already LOOKINGATCLASSESANDOBJECTSWELLRETURNTO
tested, just to add a new feature.” INHERITANCEANDOVERRIDINGINLATERCHAPTERS 
-Brad, 32, programmer "ASEDONWHATYOUVESEENSOFARANDWHATYOU
MAYKNOWFROMAPREVIOUS//LANGUAGEYOUVE
WORKEDWITH TAKEAMOMENTTOTHINKABOUT
“I like that the data and the methods that oper-
THESEQUESTIONS
ate on that data are together in one class.”
-Josh, 22, beer drinker 7HATARETHEFUNDAMENTALTHINGSYOUNEEDTO
THINKABOUTWHENYOUDESIGNA*AVACLASS7HAT
“Reusing code in other applications. When I write ARETHEQUESTIONSYOUNEEDTOASKYOURSELF
a new class, I can make it flexible enough to be )FYOUCOULDDESIGNACHECKLISTTOUSEWHEN
used in something new, later.” YOUREDESIGNINGACLASS WHATWOULDBEONTHE
-Chris, 39, project manager CHECKLIST

“I can’t believe Chris just said that. He hasn’t


written a line of code in 5 years.”
-Daryl, 44, works for Chris metacognitive tip
If you’re stuck on an exercise, try talking about
“Besides the chair?”
it out loud. Speaking (and hearing) activates
-Amy, 34, programmer
a different part of your brain. Although it
works best if you have another person to
discuss it with, pets work too. That’s how
our dog learned polymorphism.

you are here4 33


thinking about objects

When you design a class, think about the objects that


will be cre ated from that class t ype. Think about:
Nthings the object knows
Nthings the object does

ShoppingCart Button Alarm

label alarmTime
cartContents knows color knows alarmMode knows
setColor() setAlarmTime()
addToCart() does setLabel() does getAlarmTime()
setAlarm() does
removeFromCart() dePress() isAlarmSet()
checkOut() unDepress() snooze()

Things an object knows about itself are called Song

Ninstance variables instance title knows


variables artist
(state)
setTitle()
Things an object can do are called methods setArtist() does
(behavior) play()
Nmethods

4HINGSANOBJECTKNOWSABOUTITSELFARECALLEDINSTANCE Sharpen your pencil


VARIABLES4HEYREPRESENTANOBJECTSSTATETHEDATA AND
CANHAVEUNIQUEVALUESFOREACHOBJECTOFTHATTYPE &ILLINWHATATELEVISIONOBJECT
MIGHTNEEDTOKNOWANDDO
Think of instance as another way of saying object.
4HINGSANOBJECTCANDOARECALLEDMETHODS7HENYOU
DESIGNACLASS YOUTHINKABOUTTHEDATAANOBJECTWILLNEED
TOKNOWABOUTITSELF ANDYOUALSODESIGNTHEMETHODS
THATOPERATEONTHATDATA)TSCOMMONFORANOBJECTTO
HAVEMETHODSTHATREADORWRITETHEVALUESOFTHEINSTANCE
VARIABLES&OREXAMPLE !LARMOBJECTSHAVEANINSTANCE
VARIABLETOHOLDTHEALARM4IME ANDTWOMETHODSFOR
GETTINGANDSETTINGTHEALARM4IME
3OOBJECTSHAVEINSTANCEVARIABLESANDMETHODS BUTTHOSE
INSTANCEVARIABLESANDMETHODSAREDESIGNEDASPARTOFTHE
CLASS

34 chapter 2
classes and objects

What’s the difference between


a class and an object?

A class is not an object.


(but it’s used to construct them)

!CLASSISABLUEPRINTFORANOBJECT)TTELLSTHE
VIRTUALMACHINEHOWTOMAKEANOBJECTOFTHAT
JVM
PARTICULARTYPE%ACHOBJECTMADEFROMTHAT
CLASSCANHAVEITSOWNVALUESFORTHE
INSTANCEVARIABLESOFTHATCLASS&OR
EXAMPLE YOUMIGHTUSETHE"UTTON
CLASSTOMAKEDOZENSOFDIFFERENT
BUTTONS ANDEACHBUTTONMIGHTHAVE
class
ITSOWNCOLOR SIZE SHAPE LABEL ANDSOON

Look at it this way... !NOBJECTISLIKEONEENTRYINYOURADDRESSBOOK


/NEANALOGYFOROBJECTSISAPACKETOFUNUSED2OLODEX»CARDS
%ACHCARDHASTHESAMEBLANKFIELDSTHEINSTANCEVARIABLES 7HEN
YOUFILLOUTACARDYOUARECREATINGANINSTANCEOBJECT ANDTHE
ENTRIESYOUMAKEONTHATCARDREPRESENTITSSTATE
4HEMETHODSOFTHECLASSARETHETHINGSYOUDOTOAPARTICULARCARD
GET.AME CHANGE.AME SET.AME COULDALLBEMETHODSFOR
CLASS2OLODEX
3O EACHCARDCANDOTHESAMETHINGSGET.AME CHANGE.AME
ETC BUTEACHCARDKNOWSTHINGSUNIQUETOTHATPARTICULARCARD

you are here4 35


making objects

Making your first object


3OWHATDOESITTAKETOCREATEANDUSEANOBJECT9OUNEEDTWOCLASSES/NE
CLASSFORTHETYPEOFOBJECTYOUWANTTOUSE$OG !LARM#LOCK 4ELEVISION The Dot Operator (.)
ETC ANDANOTHERCLASSTOTESTYOURNEWCLASS4HETESTERCLASSISWHEREYOUPUT
THEMAINMETHOD ANDINTHATMAIN METHODYOUCREATEANDACCESSOBJECTS 4HEDOTOPERATOR GIVES
OFYOURNEWCLASSTYPE4HETESTERCLASSHASONLYONEJOBTOTRYOUTTHEMETH YOUACCESSTOANOBJECTS
ODSANDVARIABLESOFYOURNEWOBJECTCLASSTYPE STATEANDBEHAVIORINSTANCE
VARIABLESANDMETHODS 
&ROMTHISPOINTFORWARDINTHEBOOK YOULLSEETWOCLASSESINMANYOF
OUREXAMPLES/NEWILLBETHEREALCLASSnTHECLASSWHOSEOBJECTSWE
REALLYWANTTOUSE ANDTHEOTHERCLASSWILLBETHETESTERCLASS WHICHWE MAKEANEWOBJECT
CALLWHATEVER9OUR#LASS.AME)STestDrive&OREXAMPLE IFWEMAKEA $OGDNEW$OG 
Bungee CLASS WELLNEEDABungeeTestDriveCLASSASWELL/NLYTHE
SOME#LASS.AMETestDrive CLASSWILLHAVEAMAIN METHOD ANDITSSOLE
PURPOSEISTOCREATEOBJECTSOFYOURNEWTYPETHENOT THE TESTERCLASS AND TELLITTOBARKBYUSINGTHE
THENUSETHEDOTOPERATOR TOACCESSTHEMETHODSANDVARIABLESOFTHENEW DOTOPERATORONTHE
VARIABLEDTOCALLBARK
OBJECTS4HISWILLALLBEMADESTUNNINGLYCLEARBYTHEFOLLOWINGEXAMPLES
DBARK 

1 Write your class


SETITSSIZEUSINGTHE
class Dog { DOTOPERATOR
instance va DOG DSIZE
riables
int size; size
String breed; breed
name
String name;
a method bark()
void bark() {
System.out.println(“Ruff! Ruff!”);
}
} 2 Write a tester (TestDrive) class
class DogTestDrive {
d
a m a i n metho de public static void main (String[] args) {
just co
na puetxt step) // Dog test code goes here
’r e g o n
(we it in the n }
in }

In your tester, make an object and access


3 the object’s variables and methods
class DogTestDrive {
public static void main (String[] args) {
Dog d = new Dog(); make a Dog
object
d.size = 40; use the dot operator (.)
dot r d.bark(); to set the size of the Do
operato } and to call its bark g If you already have some OO savvy,
you’ll know we’re not using encapsulation.
} () method We’ll get there in chapter 4.

36 chapter 2
classes and objects

Making and testing Movie objects


class Movie {
String title;
String genre;
int rating;
void playIt() {
System.out.println(“Playing the movie”);
}
}

public class MovieTestDrive {


public static void main(String[] args) {
Movie one = new Movie();
one.title = “Gone with the Stock”;
one.genre = “Tragic”;
one.rating = -2;
Movie two = new Movie();
two.title = “Lost in Cubicle Space”;
two.genre = “Comedy”;
two.rating = 5;
two.playIt();
Movie three = new Movie();
three.title = “Byte Club”;
three.genre = “Tragic but ultimately uplifting”;
three.rating = 127;
}
}
Sharpen your pencil

title
MOVIE
object 1 genre
title
genre rating
rating
playIt()
title

4HE-OVIE4EST$RIVECLASSCREATESOBJECTSINSTANCES OF object 2 genre


THE-OVIECLASSANDUSESTHEDOTOPERATOR TOSETTHE
rating
INSTANCEVARIABLESTOASPECIFICVALUE4HE-OVIE4EST$RIVE
CLASSALSOINVOKESCALLS AMETHODONONEOFTHEOBJECTS
&ILLINTHECHARTTOTHERIGHTWITHTHEVALUESTHETHREE title
OBJECTSHAVEATTHEENDOFMAIN 
object 3 genre

rating

you are here4 37


get the heck out of main

Quick! Get out of main!


!SLONGASYOUREINMAIN YOURENOTREALLYIN/BJECTVILLE)TSlNEFORATEST
PROGRAMTORUNWITHINTHEMAINMETHOD BUTINATRUE//APPLICATION YOU
NEEDOBJECTSTALKINGTOOTHEROBJECTS ASOPPOSEDTOASTATICMAIN METHOD
CREATINGANDTESTINGOBJECTS

The t wo uses of main:


Nto test your real class
Nto launch/start your Java application
!REAL*AVAAPPLICATIONISNOTHINGBUTOBJECTSTALKINGTOOTHEROBJECTS)NTHIS
CASE TALKINGMEANSOBJECTSCALLINGMETHODSONONEANOTHER/NTHEPREVIOUS
PAGE ANDINCHAPTER WELOOKATUSINGAMAIN METHODFROMASEPARATE
4EST$RIVECLASSTOCREATEANDTESTTHEMETHODSANDVARIABLESOFANOTHERCLASS)N
CHAPTERWELOOKATUSINGACLASSWITHAMAIN METHODTOSTARTTHEBALLROLLING
ONAREAL*AVAAPPLICATIONBYMAKINGOBJECTSANDTHENTURNINGTHOSEOBJECTS
GameLauncher
LOOSETOINTERACTWITHOTHEROBJECTS ETC
make
!SA@SNEAKPREVIEW THOUGH OFHOWAREAL*AVAAPPLICATIONMIGHTBEHAVE GuessGs a
HERESALITTLEEXAMPLE"ECAUSEWERESTILLATTHEEARLIESTSTAGESOFLEARNING*AVA object ame
WEREWORKINGWITHASMALLTOOLKIT SOYOULLlNDTHISPROGRAMALITTLECLUNKY main(String[] args) tells it and
ANDINEFlCIENT9OUMIGHTWANTTOTHINKABOUTWHATYOUCOULDDOTOIMPROVE startG to
IT ANDINLATERCHAPTERSTHATSEXACTLYWHATWELLDO$ONTWORRYIFSOMEOFTHE ame
CODEISCONFUSINGTHEKEYPOINTOFTHISEXAMPLEISTHATOBJECTSTALKTOOBJECTS

The Guessing Game GuessGame


instan
3UMMARY p1 variablecse
4HEGUESSINGGAMEINVOLVESA@GAMEOBJECTANDTHREE@PLAYEROBJECTS4HEGAMEGEN p2 forth
ERATESARANDOMNUMBERBETWEENAND ANDTHETHREEPLAYEROBJECTSTRYTOGUESS p3 playerse three
IT7EDIDNTSAYITWASAREALLYEXCITINGGAME
startGame()
#LASSES
GuessGame.class Player.class GameLauncher.class
the
4HE,OGIC Player this pnlumber
guessedayer
 4HE'AME,AUNCHERCLASSISWHERETHEAPPLICATIONSTARTSITHASTHEMAIN METHOD number
 )NTHEMAIN METHOD A'UESS'AMEOBJECTISCREATED ANDITSSTART'AME METHOD meth
guess()
ISCALLED makingod for
 4HE'UESS'AMEOBJECTSSTART'AME METHODISWHERETHEENTIREGAMEPLAYSOUT guess a
)TCREATESTHREEPLAYERS THENhTHINKSvOFARANDOMNUMBERTHETARGETFORTHEPLAYERS
TOGUESS )TTHENASKSEACHPLAYERTOGUESS CHECKSTHERESULT ANDEITHERPRINTSOUT
INFORMATIONABOUTTHEWINNINGPLAYERS ORASKSTHEMTOGUESSAGAIN

38 chapter 2
classes and objects

public class GuessGame { GuessGame has ree


Player p1; variables for thth
e th re
instance
Player p2; objects e Player
Player p3;
public void startGame() { create three Play
p1 = new Player();
assign them to theerthobrejec
e
ts and
p2 = new Player();
instance variables Pl ayer
p3 = new Player();
int guessp1 = 0; declare three variables to hold the
int guessp2 = 0; three guesses the Players mak
int guessp3 = 0; e
boolean p1isRight = false;
boolean p2isRight = false;
declare three variables to hold a true or
boolean p3isRight = false; false based on the player’s answer
int targetNumber = (int) (Math.random() * 10); make a ‘target’ number that the
System.out.println(“I’m thinking of a number between 0 and 9...”); players have to guess
while(true) {
System.out.println(“Number to guess is “ + targetNumber);
p1.guess();
p2.guess();
call each player’s guess() method
p3.guess();
guessp1 = p1.number;
System.out.println(“Player one guessed “ + guessp1);
guessp2 = p2.number; get each player’s guess (the result their
System.out.println(“Player two guessed “ + guessp2); guess() method running) by accessingofthe
guessp3 = p3.number; number variable of each player
System.out.println(“Player three guessed “ + guessp3);

if (guessp1 == targetNumber) {
p1isRight = true;
} check each player’s guess to see if it matches
if (guessp2 == targetNumber) { the target number. If a player is right ,
p2isRight = true; then set that player’s variable to be true
} (remember, we set it false by default)
if (guessp3 == targetNumber) {
p3isRight = true;
}
if player one OR player two OR player three is right
if (p1isRight || p2isRight || p3isRight) {
(the || operator means OR) ...
System.out.println(“We have a winner!”);
System.out.println(“Player one got it right? “ + p1isRight);
System.out.println(“Player two got it right? “ + p2isRight);
System.out.println(“Player three got it right? “ + p3isRight);
System.out.println(“Game is over.”);
break; // game over, so break out of the loop
otherwis
players feo,rsta ay in the loop and ask
} else {
// we must keep going because nobody got it right!
System.out.println(“Players will have to try again.”);
nother guess. the
} // end if/else
} // end loop
} // end method
} // end class

you are here4 39


Guessing Game

Running the Guessing Game


public class Player {
int number = 0; // where the guess goes

public void guess() { /UTPUTITWILLBEDIFFERENTEACHTIMEYOURUNIT


number = (int) (Math.random() * 10);
System.out.println(“I’m guessing “ File Edit Window Help Explode

+ number); %java GameLauncher


}
} I’m thinking of a number between 0 and 9...
Number to guess is 7
public class GameLauncher { I’m guessing 1
public static void main (String[] args) { I’m guessing 9
GuessGame game = new GuessGame();
game.startGame(); I’m guessing 9
} Player one guessed 1
}
Player two guessed 9
Player three guessed 9
Players will have to try again.
Java takes out the
Garbage Number to guess is 7
I’m guessing 3
%ACHTIMEANOBJECTISCREATED
IN*AVA ITGOESINTOANAREAOF I’m guessing 0
MEMORYKNOWNAS4HE(EAP I’m guessing 9
!LLOBJECTSˆNOMATTERWHEN WHERE
Player one guessed 3
ORHOWTHEYRECREATEDnLIVEONTHE
HEAP"UTITSNOTJUSTANYOLDMEMORY Player two guessed 0
HEAPTHE*AVAHEAPISACTUALLYCALLEDTHE Player three guessed 9
'ARBAGE #OLLECTIBLE(EAP7HENYOU
CREATEANOBJECT *AVAALLOCATESMEMORY
Players will have to try again.
SPACEONTHEHEAPACCORDINGTOHOW Number to guess is 7
MUCHTHATPARTICULAROBJECTNEEDS!N I’m guessing 7
OBJECTWITH SAY INSTANCEVARIABLES
WILLPROBABLYNEEDMORESPACETHANAN I’m guessing 5
OBJECTWITHONLYTWOINSTANCEVARIABLES I’m guessing 0
"UTWHATHAPPENSWHENYOUNEEDTO Player one guessed 7
RECLAIMTHATSPACE(OWDOYOUGETAN
OBJECTOUTOFTHEHEAPWHENYOUREDONE Player two guessed 5
WITHIT*AVAMANAGESTHATMEMORY Player three guessed 0
FORYOU7HENTHE*6-CAN@SEETHATAN
We have a winner!
OBJECTCANNEVERBEUSEDAGAIN THAT
OBJECTBECOMESELIGIBLEFORGARBAGE Player one got it right? true
COLLECTION!NDIFYOURERUNNINGLOWON Player two got it right? false
MEMORY THE'ARBAGE#OLLECTORWILLRUN
THROWOUTTHEUNREACHABLEOBJECTS AND Player three got it right? false
FREEUPTHESPACE SOTHATTHESPACECAN Game is over.
BEREUSED)NLATERCHAPTERSYOULLLEARN
MOREABOUTHOWTHISWORKS

40 chapter 2
classes and objects

there are no
Dumb Questions
Q: 7HATIF)NEEDGLOBAL Q: 7HATISA*AVAPROGRAM
VARIABLESANDMETHODS(OW 7HATDOYOUACTUALLYDELIVER
DO)DOTHATIFEVERYTHINGHASTO
GOINACLASS
A: !*AVAPROGRAMISAPILE
Make it Stic
A: 4HEREISNTACONCEPTOF
OFCLASSESORATLEASTONECLASS 
)NA*AVAAPPLICATION ONEOF
k
@GLOBALVARIABLESANDMETHODSIN THECLASSESMUSTHAVEAMAIN
!CLASSIS
A*AVA//PROGRAM)NPRACTICAL METHOD USEDTOSTART UPTHE LIKEARECI
P E
USE HOWEVER THEREARETIMES PROGRAM3OASAPROGRAMMER /BJEC TSA
RELIKE
WHENYOUWANTAMETHODOR YOUWRITEONEORMORECLASSES COOKIES
ACONSTANT TOBEAVAILABLE !NDTHOSECLASSESAREWHATYOU
TOANYCODERUNNINGINANY DELIVER)FTHEEND USERDOESNT
PARTOFYOURPROGRAM4HINK HAVEA*6- THENYOULLALSO
OFTHErandom()METHODIN NEEDTOINCLUDETHATWITH
THE0HRASE / -ATICAPPITSA YOURAPPLICATIONSCLASSES
METHODTHATSHOULDBEC ALLABLE SOTHATTHEYCANRUNYOUR
FROMANYWHERE/RWHATABOUT PROGRAM4HEREAREANUMBER
ACONSTANTLIKEPI9OULLLEARN OFINSTALLERPROGRAMSTHAT
INCHAPTERTHATMARKING LETYOUBUNDLEYOURCLASSES
AMETHODASpublic AND WITHAVARIETYOF*6-SSAY FOR
static MAKESITBEHAVEMUCH DIFFERENTPLATFORMS ANDPUTITALL
LIKEA@GLOBAL!NYCODE INANY ONA#$ 2/-4HENTHEEND USER BULLET POINTS
CANINSTALLTHECORRECTVERSIONOF
CLASSOFYOURAPPLICATION CAN
THE*6-ASSUMINGTHEYDONT
ß Object-oriented programming lets you extend
ACCESSAPUBLICSTATICMETHOD
ALREADYHAVEITONTHEIRMACHINE
a program without having to touch previously-
!NDIFYOUMARKAVARIABLEAS
public static ANDfinal tested, working code.
nYOUHAVEESSENTIALLYMADEA ß All Java code is defined in a class.
GLOBALLY AVAILABLECONSTANT
Q: 7HATIF)HAVEAHUNDRED ß A class describes how to make an object of
that class type. A class is like a blueprint.
CLASSES/RATHOUSAND)SNT
ß
Q: 4HENHOWISTHISOBJECT
THATABIGPAINTODELIVER
ALLTHOSEINDIVIDUALlLES
An object can take care of itself; you don’t
have to know or care how the object does it.
ORIENTEDIFYOUCANSTILLMAKE #AN)BUNDLETHEMINTOONE
ß An object knows things and does things.
GLOBALFUNCTIONSANDGLOBAL !PPLICATION4HING
DATA ß Things an object knows about itself are called
instance variables. They represent the state

A: A: 9ES ITWOULDBEABIG of an object.


&IRSTOFALL EVERYTHING PAINTODELIVERAHUGEBUNCHOF ß Things an object does are called methods.
IN*AVAGOESINACLASS3OTHE INDIVIDUALFILESTOYOUREND USERS They represent the behavior of an object.
CONSTANTFORPIANDTHEMETHOD BUTYOUWONTHAVETO9OUCAN
FORrandom() ALTHOUGHBOTH PUTALLOFYOURAPPLICATIONFILES ß When you create a class, you may also want
PUBLICANDSTATIC AREDEFINED INTOA*AVA!RCHIVEnAJARFILEn to create a separate test class which you’ll
WITHINTHEMathCLASS!NDYOU THATSBASEDONTHEPKZIPFORMAT use to create objects of your new class type.
MUSTKEEPINMINDTHATTHESE )NTHEJARFILE YOUCANINCLUDE ß A class can inherit instance variables and
STATICGLOBAL LIKE THINGSARETHE ASIMPLETEXTFILEFORMATTEDAS methods from a more abstract superclass.
EXCEPTIONRATHERTHANTHERULE SOMETHINGCALLEDAMANIFEST THAT
IN*AVA4HEYREPRESENTAVERY DEFINESWHICHCLASSINTHATJAR ß At runtime, a Java program is nothing more
SPECIALCASE WHEREYOUDONT HOLDSTHEMAIN METHODTHAT than objects ‘talking’ to other objects.
HAVEMULTIPLEINSTANCESOBJECTS SHOULDRUN

you are here4 41


exercise: Be the Compiler

1dQ^OU_Q "%THECOMPILER
Each of the Java files on this page
represents a complete source file.
Your job is to play compiler and
determine whether each of
these files will compile.
If they won’t compile,
how would you fix them,
and if they do compile,
what would be their output?

A
class TapeDeck {

boolean canRecord = false; B


class DVDPlayer {
void playTape() {
System.out.println(“tape playing”); boolean canRecord = false;
}
void recordDVD() {
void recordTape() { System.out.println(“DVD recording”);
System.out.println(“tape recording”); }
} }
}
class DVDPlayerTestDrive {
class TapeDeckTestDrive { public static void main(String [] args) {
public static void main(String [] args) {
DVDPlayer d = new DVDPlayer();
t.canRecord = true; d.canRecord = true;
t.playTape(); d.playDVD();

if (t.canRecord == true) { if (d.canRecord == true) {


t.recordTape(); d.recordDVD();
} }
} }
} }

42 chapter 2
classes and objects

Code Magnets
1dQ^OU_Q !*AVAPROGRAMISALLSCRAMBLEDUPON
THEFRIDGE#ANYOURECONSTRUCTTHE
CODESNIPPETSTOMAKEAWORKING*AVA
PROGRAMTHATPRODUCESTHEOUTPUTLISTED d.playSnare();
BELOW3OMEOFTHECURLYBRACESFELLON
THEFLOORANDTHEYWERETOOSMALLTOPICK DrumKit d = new DrumKit();
UP SOFEELFREETOADDASMANYOFTHOSE
ASYOUNEED
= true;
boolean topHat
= true;
boolean snare

void playSnare() {
ang”);
System.out.println(“bang bang ba-b
}

public static void main(String [] args) {

if (d.s
nare == tr
ue) {
d.playS
nare();
}

d.snare = false;

class DrumKitTestDrive {

();
TopHat
d.play
class DrumKit {

void playTopH
at () {
System.out.p
rintln(“ding
ding da-ding”
File Edit Window Help Dance
} );
% java DrumKitTestDrive
bang bang ba-bang
ding ding da-ding

you are here4 43


puzzle: Pool Puzzle

public class EchoTestDrive {


public static void main(String [] args) {
Echo e1 = new Echo();
_________________________
Pool Puzzle int x = 0;
9OURJOBISTOTAKECODESNIPPETSFROM while ( ___________ ) {
THEPOOLANDPLACETHEMINTOTHE
BLANKLINESINTHECODE9OUMAY e1.hello();
USETHESAMESNIPPETMORETHAN __________________________
ONCE ANDYOUWONTNEEDTOUSE
if ( ____________ ) {
ALLTHESNIPPETS9OURGOALISTO
MAKECLASSESTHATWILLCOMPILEAND e2.count = e2.count + 1;
RUNANDPRODUCETHEOUTPUTLISTED }
if ( ____________ ) {
/UTPUT e2.count = e2.count + e1.count;
File Edit Window Help Implode }
%java EchoTestDrive x = x + 1;
helloooo... }
helloooo... System.out.println(e2.count);
helloooo... }
helloooo... }

10
class ____________ {
int _________ = 0;
void ___________ {
"ONUS1UESTION
System.out.println(“helloooo... “);
)FTHELASTLINEOFOUTPUTWAS }
INSTEADOFHOWWOULD }
YOUCOMPLETETHEPUZZLE

.OTE%ACHSNIPPET
FROMTHEPOOLCANBE
USEDMORETHANONCE
X X
Y X %CHO
E X 4ESTER
COUNT X ECHO EE
EE  COUNT %CHOE
ECOUNT  HELLO %CHOEE
%CHOENEW%CHO  X
ECOUNTCOUNT 
X
ECOUNTECOUNT 

44 chapter 2
classes and objects

!BUNCHOF*AVACOMPONENTS INFULLCOSTUME AREPLAYINGAPARTY


GAME h7HOAM)v4HEYGIVEYOUACLUE ANDYOUTRYTOGUESSWHO
THEYARE BASEDONWHATTHEYSAY!SSUMETHEYALWAYSTELLTHETRUTH
ABOUTTHEMSELVES)FTHEYHAPPENTOSAYSOMETHINGTHATCOULDBETRUE
FORMORETHANONEOFTHEM CHOOSEALLFORWHOMTHATSENTENCECAN

m I ? APPLY&ILLINTHEBLANKSNEXTTOTHESENTENCEWITHTHENAMESOFONEOR
MOREATTENDEES4HEFIRSTONESONUS

ho a 4ONIGHTSATTENDEES
W #LASS-ETHOD/BJECT)NSTANCEVARIABLE

I am compiled from a .java file. class


My instance variable values can
be different from my buddy’s
values.

I behave like a template.

I like to do stuff.

I can have many methods.

I represent ‘state’.

I have behaviors.

I am located in objects.

I live on the heap.

I am used to create object instances.

My state can change.

I declare methods.

I can change at runtime.

you are here4 45


exercise solutions

Be the Compiler:
1dQ^OU_Q class TapeDeck {
boolean canRecord = false;
%XERCISE3OLUTIONS void playTape() {
System.out.println(“tape playing”);
A }
void recordTape() {
System.out.println(“tape recording”);
}
}

Code Magnets: class TapeDeckTestDrive {


public static void main(String [] args) {
class DrumKit {
TapeDeck t = new TapeDeck( );
boolean topHat = true; t.canRecord = true;
boolean snare = true; t.playTape();

void playTopHat() { if (t.canRecord == true) {


System.out.println(“ding ding da-ding”); t.recordTape();
} }
} We’ve got the template, now we have
void playSnare() { } to make an object !
System.out.println(“bang bang ba-bang”);
}
}
class DVDPlayer {
boolean canRecord = false;
class DrumKitTestDrive {
void recordDVD() {
public static void main(String [] args) {
System.out.println(“DVD recording”);
}
DrumKit d = new DrumKit();
void playDVD ( ) {
d.playSnare();
System.out.println(“DVD playing”);
d.snare = false;
}
d.playTopHat();
}
if (d.snare == true) {
class DVDPlayerTestDrive {
d.playSnare();
public static void main(String [] args) {
}
DVDPlayer d = new DVDPlayer();
}
B d.canRecord = true;
}
d.playDVD();
if (d.canRecord == true) {
File Edit Window Help Dance
d.recordDVD();
% java DrumKitTestDrive
}
bang bang ba-bang
ding ding da-ding
} The line: d.playDVD( ); wouldn’t
} compile without a method !

46 chapter 2
classes and objects

0UZZLE3OLUTIONS

Pool Puzzle
public class EchoTestDrive {
public static void main(String [] args) { 7HOAM)
Echo e1 = new Echo();
Echo e2 = new Echo( ); // the correct answer I am compiled from a .java file. class
- or - My instance variable values can be
Echo e2 = e1; // is the bonus answer! different from my buddy’s values. object
int x = 0;
while ( x < 4 ) {
I behave like a template. class
e1.hello(); I like to do stuff. object, method
e1.count = e1.count + 1;
if ( x == 3 ) {
I can have many methods. class, object
e2.count = e2.count + 1; I represent ‘state’. instance variable
}
if ( x > 0 ) {
I have behaviors. object, class
e2.count = e2.count + e1.count; I am located in objects. method, instance variable
}
x = x + 1; I live on the heap. object
} I am used to create object
System.out.println(e2.count); instances. class
}
} My state can change. object, instance variable
I declare methods. class
class Echo {
int count = 0; I can change at runtime. object, instance variable
void hello( ) {
System.out.println(“helloooo... “); Note: both classes and objects are said to have state and behavior.
} They’re defined in the class, but the object is also said to ‘have’
} them. Right now, we don’t care where they technically live.

File Edit Window Help Assimilate


%java EchoTestDrive
helloooo...
helloooo...
helloooo...
helloooo...
10

you are here4 47


3 primitives and references

Know Your Variables

Variables come in two flavors: primitive and reference. So far you've

used variables In two places-as object state (instance variables), and as local variables

(variables declared within a method) . Later, we'll use variables as arguments (values sent to a

method by the calling code), and as return types (values sent back to the caller of the method).

You've seen variables declared as simpie prj m IUve integer vaIues (type in c). You've seen

variables declared as something more complex like a String or an array. But there's gotta be
more to life than integers, Strings, and arrays.What If you have a PetOwner object with a Dog

instance variable? Or a Car with an Engine? In this chapter we'll unwrap the mysteries of Java

types and look at what you can declare as a variable, what you can pur In a variable, and what you

can do with a variable. And we'll finally see what life Is truly like on the garbage-collectible heap.

this Is a new chapter 49


declaring a variable

Peclarittg avariable
Java cares about type. It won't let you do
something bizarre and dangerous like stuff a
Giraffe reference into a Rabbit variable-what
happens when someone tries to ask the so-called
Rabbit to hop ()? And it won't let you put a
floating point number into an integer variable,
unless you lKknowledge to thecompiler that you
know you might lose precision (like, everything
after the decimal point).
The compiler can spot most problems:
Rabbit hopper = new Giraffe();
Don't expect that to compile. Thankfully .
For all this type-safety to work, you must declare
the type of your variable. Is it an integer? a Dog?
A single character? Variables come in two flavors:
primitive and object reference. Primitives hold
fundamental values (think: simple bit patterns)
including integers, booleans, and floating point
numbers. Object references hold. well, references
to objects (gee, didn't that clear it up.)
We'Ulook at primitives first and then move
on to what an object reference really means.
But regardless of the type, you must foUow two
declaration rules:

variables must have a type


Besides a type, a variable needs a name, so that
you can use that name in code.

variables must have a name

int count;
;?1 <,
type na.....e

Note: When you see a statement like: "an object


of type X", think of l)'Peand classes synonyms.
(We'll refine that a little more in later chapters.)

50 chapter 3
primitives and references

Primitive Types
n you think ofJava variables, think of cups. Coffee cups, tea cups, giant Type Bit Depth Value Range
that hold lots and lots of beer, those big cups the popcorn comes in at boolean and char
movies, cups with curvy, sexy handles, and cups with metallic trim that
learned can never, ever go in the microwave. boolean (JVM .. pedfic) true or false

wariable is just a cup. A container. It holds something. char 16 bits 0 to 65535

a size, and a type. In this chapter, we're going to look first at the numeric (all are signed)
- bles (cups) that hold primitives, then a little later we'll look at cups Integer
hold references to objects. Stay with us here on the whole cup analogy-as
byte 8 bits -128 to 127
pie as it is right now, it'll give us a common way to look at things when
discussion gets more complex. And that'll happen soon. short 16 bits -32768 to
32767
- itives are like the cups they have at the coffeehouse. If you've been to a
int 32 bits -2147483648
ucks, you know what we're talking about here. They come in different
and each has a name like 'short', 'tall', and, "I'd like a to 2147483647
de' mocha half-eaffwith extra whipped cream". long 64 bits -huge to huge
migh t see the cups displayed on the counter,
u can order appropriately: floating point
float 32 bits varies
double 64 bits varies

Primitive declarations
small short tall grande
with assignments:
Int ){i
--'!II" And inJava, primitives come in different sizes, and those sizes
have names. When you declare a variable in Java, x = 234;
E ::a-YoU must declare it with a specific type. The byte b = 89;
I four containers here are for the four boolean isfun = true;
integer primitives in Java.
double d = 3456,98j
char c ='f'j
fang int short byte lnt z e x:
cup holds a value, so for Java primitives, rather than saying, "I'd like a boolean IsPunkRock;
french roast", you say to the compiler, "I'd like an int variable with the
isPunkRock = false;
ber 90 please." Except for one tiny difference ... in Java you also have to
your cup a name. So it's actually, "I'd like an int please, with the value boolean powerOn;
:H86, and name the variable height." Each primitive variable has a fixed powerOn = IsFun;
ber of bits (cup size). The sizes for the six numeric primitives inJava long big = 3456789j
shown below:
float f = 32.5i

.( qatta "a~t -that


Nott tht ~ btU\,<St ja~a thi"~
..,i-th a ~\. ~\oab~ foi"t I~
byte short int long float double '"'ythi,,~ 'fI1-th a \,<St '~'.
8 16 32 64 32 64 a ci~\e, "",\65 'fO'#

you are here ~ 51


prlmltlve assignment

You really dot1~t wat1t to spill that...


Be sure the value can fit into the variable.
You can't put a large value into a
small cup. The compiler won't let you put
a value from a large cup into
WeU, OK, you can, but you'll a small one. But what about
lose some. You'll get, as we say, the other way-pouring a
spillage. The compiler tries to small cup into a big one7 No
help prevent this ifit can tell problem.
from your code that something's Basedon what you know
not going to fit in the container about the size and type of the
(variable/cup) you're using. pri mitive va rlables, see if you
can figure out which of these
For example, you can't pour an are legal and which aren't,
int-full of stuff into a byte-sized We haven't covered all the
container, as follows: rules yet, so on some of these
you'll have to use your best
int x = 24;
judgment. Tip: The compiler
byte b = x; always errs on the side of
safety.
//won't work!!

From the following list Circle


the statements that would be
Why doesn't this work, you ask? After all, the value of x is 24, and 24 is definitely
legal if these lines were in a
small enough to fit into a byte. You know that, and we know that, but all the single method:
compiler cares about is that you're trying to put a big thing into a small thing.
and there's the possibility of spilling. Don't expect the compiler to know what the 1. int x = 34.5;
value of xis. even if you happen to be able to see it literally in your code. 2 . boolean boo x;
You can assign a value to a variable in one of several ways including:
3 . int g = 17;
• type a litera/value after the equals sign (x=12. isGood = true, etc.)
4. int y '" 9;
• assign the value of one variable to another (x =y)
5 . Y = Y + 10;
• use an expression combining the two (x = y + 43)
In the examples below, the literal values are in bold italics: 6. short s;

int size = 32; declare an int named size, assIgn ilthe value 32 7. s = y;
char initial = 'j'; declare a char named initial, assign itlhe value T 8. byte b = 3;
double d = 456.709; declare a double named d, assign it the value 456.709
9 . byte v = b;
boolean isCrazy; declare a boolean named IsCrazy (no assignment)
10. short n '" 12;
isCrazy true; assign the value true to thepreviously-declared ;sCrazy
int y = x + 456; declare an int named y, assign Itlhe value that is the sum 11. v '" n ;
of whatever x is now plus 456
12. byte k 128;

52 chapter 3
prlmitJves and references

Jack away frotH that keyword!


lbu know you need a name and a type for your variables.
YOu already know the primitive types.
. , what can you we as names? The rules are simple. You
an name a class, method, or variable according to the
owing rules (the real rules are slightly more flexible,
t these will keep you safe) :
ftIfIeS ote:
. ' b\e
• It must start with a letter, underscore U, or , /'It primitIve '7" float do U .
dollar algn ($). You can't atart a name with a The elg e s\"lOft lot long . t/'lem:
number. eao char byt membermg
boO\ onic for re
, om nem
• After the first character, you can u. . numbers as And here S , gest urge
S u\dn't n
well. Just don't atart It with a number, CafefU\~ 8ea's \"10
• It can be anything you like, subject to those two
8e bertet.
furry Oogs 't'll stick even
rules, JU8t 80 long as It Isn't one of Java's reserved out own, I
words. It yoU make up Y D
S I LF- -
B_ c- B_ - -

public static void

And the primitive types are reserved as well:

boolean char byte short int long floa.t double


t there are a lot more we haven't discussed yet. Even if you don't
ed to know what they mean, you still need to know you can 't use
'em yourself. Do not-under any circumstances-try to memorize these
.w. To make room for these in your head, you'd probably have to
something else . Like where your car is parked. Don't worry, by
the end of the book you'll have most of them down cold.

fhls table reserved.


boolean byte mar double flom Inl long
protected abstract flnal native storic strictfp syndJronlzed transient If
else do while swllm case delauh for break continue assart
doss ex1and~ implements import rnstanceof interface new package super this
catch flnol~ try throw throws return void canst gala enum
Java's keywords and other reserved words (In no useful order). If you use these for names, the complier will be very, vel}' upset.

you are here I 53


object references

Controlling your ~og object


You know how to declare a primitive variable and assign it a
value . But now what about non-primitive variables? In other
words, what about objects? Dog d = new Dog();
d.bark();
• There Is actually no such thing as an object variable.
• There's only an object reference variable. \ thi.k ot this
• An object reference variable holds bits that represent a
way to access an object.
• It doesn't hold the object Itsetf, but It holds something
like a pointer. Or an address. Except., in Java we don't
really know what Is Inside a reference variable. We do
know that whatever It Is, It represents one and only one
object. And the JVM knows how to use the reference to
get to the object.

You can ' 1 stuff an object into a variable. We often think of


it that way... we say things like, "I passed the String to the
System.out.printlnf) method." Or, "The method returns a Dog",
or, "I put a new Foo object into the variable named rnyf'oo."
But that's not what happens. There aren't giant
expandable cups that can grow to the size of any Thillk o-f a D~
object. Objects live in one place and one place referente vdl'iable al
only-the garbage collectible heap! (You'll
learn more about that later in this chapter) a D~ l'en-ote to.\h-ol.
Although a primitive variable is full of You. IUC it to ~tt -t\l~
bits representing the actual value of the
objut to do ~tthill9
variable, an object reference variable is full
of bits representing a way to get to the (h'IVolcc ",et.h~) .
obJect.
You use the dot operator (.)
on a reference variable 10 say,
"use the thing before the dot to
get me the thing after the dot." For
example:
myDog.bark() ;
means, "use the object referenced by the variable myDog to
invoke the barkt) method." When you use the dot operator on
an object reference variable, think of it like pressing a button
on the remote control for that object.

54 chapter 3
primitives and references

The 3 steps of object


declaration, creation and
assignment

1 2
~3~
byte short int long reference
Dog myDog = new Dog();
8 16 32 64 Ibll depth not relevant)

At1 object referet1ce is just Declare a reference


a"other variable value. O variable
Something that goes In a cup. Doq myDoq = new Dog () ;
Only this time, the value 15 a remote control. Tells the JVM to allocate space for a
reference variable, and names that
Prhldtlve Variable ~\.\. variable myDog. The reference variable

J~itive
Is, forever. of type Dog.ln other words,
byte x = 7; a remote control that has buttons to
the bits representing 7 go
to the variable. (00000111),
Ubyte
vall.4t
control a Dog, but not a Cat or a Button
or a Socket.
Dog

e Create an object
Dog myDog '" new Dog () ;
Dog myDog = new Doq() ;
Tells the JVM to allocate space for a
new Dog object on the heap (we'll
learn a lot more about that process,
especially in chapter 9,)
Dog object

e Link the object


and the reference
Dog myDog = new Dog () ;
Assigns the new Dog to the reference
variable myDog.ln other words,
programs the remote control,

Dog object

~n care how meny t's and O's tho,o are In a (afare~08l1tlriabla lrs UP10 a&eh
: " a."ld Ihe phase of Ihe moon , Dog
you are he re . 55
object references

,
D:therel~o
.
"
ume ~uest19115 Java,£Nposecl
Q: How big 15 a reference This week's Interview:
variable?
Object Reference

A. :Vou don't know. Unless


you're cozy with someone on the
HeadFirst So, tell us, what's life likefor an object reference?
Reference: Pretty simple, really. I'm a remote control and I can be programmed to
JVM's development team, you control different objects.
don't know how a reference is
HeadArst Do you mean different objects even while you're running? Like, can you
represented. There are pointers
in there somewhere, but you refer to a Dog and then five minutes later refer to a Car?
can't access them .You won't Reference: or course not- Once I'm declared, that's it. If I'm a Dog remote control
need to. (OK, Ifyou Inslst, you then ru never be able to point (oops- my bad, we're not supposed to say poin~ I mean rifer
might as well Just imagine It to anything but a Dog.
to be a 54-bit value.) But when
you're talking about memory HeadFirst Does that mean you can refer to only one Dog?
allocation issues, your Big
Reference: No. I can be referring to one Dog, and then five minutes later I can refer to
Concern should be about how
many objects (as oppose-d to some other Dog. As long as it's a Dog, I can be redirected (like reprogranuning your remote
object references) you're creating, to a different TV) to it. Unless... no never mind.
and how big they (the objects) HeadFirst No, tell me. What were you gonna say?
really are.
Reference: I don't think you want to get into this now, but I'lljust giveyou the short
version - if I'm maned as final, then once I am assigned a Dog, I can never be repro-
grammed to anything else but I1ul1 one and only Dog: In other words, no other object can
Q:So, does that mean that be assigned to me.
all object references are the HeadFirst You're right, we don't want to talk about that now. OK, sounless you're
same size, regardless of the size final, then you can refer to one Dog and then refer to a differentDog later. Can you ever
of the actua I objects to which
refer to fIl)tJring at alP. Is it possible to not be programmed to anything?
they refer?
Reference: Yes, but it disturbs me to talk about it.

A.: Yep. All references for a


given NM will be the same
HeadArst Why is that?
Reference: Because it means I'm null, and that's upsetting to me.
size regardless of the objects
HeadFirst You mean. because then you have no value?
they reference, but each JVM
might have a different way of Reference: Oh, null isa value. I'm stilla remote control, but it's like you brought
representing references, so home a new universal remote control and you don't have a TV I'm not programmed to
references on one JVM may be control anything. They can press my buttons all day long, but nothing good happens. I
smaller or larger than references just feel so... useless. A waste of bits. Granted, not that many bits, but still. And that's not
on another JVM.
the worst part. If I am the only reference to a panicular object, and then I'm set to null
(deprogrammed), it means that now rwboqy can get to that object I had been referring to.
Q:can I do arithmetic on a HeadFirst And that's bad because...
reference variable, Increment It
you know - C stuff7 Reference: You have to ask? Here I've developed a relationship with thisobject, an
intimate connection, and then the tie issuddenly, cruelly, severed. And I will never see

A.: Nope. Say It with me again,


"Java Is not C."
that object again, because now it's eligible for [producer, cue.tragic music) garbage collection.
Sniff. But do you think programmers ever consider !haP. Snif. Why, wIrY can't I be a primi-
tive? I hate being a refcrcut. The responsibility, all the broken attachments...

56 chapter 3
primitives and references

ott the garbage..collectible heap

= new Book();
= new Book();
e two Book reference
- les.Create two new Book
. Assig n the Book objects to
reference variables.
Book
two Book objects are now living
e heap.

Obiects: 2
Book
Book d = c;
re a new Book reference variable.
r than creating a new, third Book
•assign the value of variable c to
. ble d. But what does th is mean?
li ke saying, "Take the bits In c, make a
of them, and stick that copy Into d."
..... c and d refer to the same
....ect.
The c and d variables hold
Book
two dlHerent copies of the
. .me value. Two remotes
.....grammed to one TV.
ferences: 3
Objects: 2
Book
c = h;
Assign the value of variable b to
variab le c. By now you know what
is means. The bits inside variable
at are copied, and that new copy Is
stuffed into variable c.
Both band c refer to the
same object.
References: 3
Objects : 2

you are here ~ 57


objects on the heap

Ufe a.,d death 0., the heap


Book b = new Book() ;
Book c = new Book() i
Declare two Book reference variables.
Create two new Book objects. Assign
the Book objects to the reference
variables.
The two book objects are now living
on the heap.
ActIve References: 2
Reachable Objects: 2
Book
b = Ci
Assign the value of variable c to variable b.
The bits Inside variable c are copied, and
that new copy is stuffed Into variable b.
Both variables hold identical values.
Both band c refer to the ••me
object. Object 1 I. abandoned
and eligible for Garbage Collec-
tion (GC).
Active References: 2
Reachable Objects: 1
Abandoned Objects: 1
The first object that b referenced, Object 1,
has no more references. It's unreachable.

C = null;
Assign the value nu 11 to variable c.
This makes c a null reference, meaning
It doesn't refer to anything. But It's still
a reference variable, and another Book
object can stili be assigned to It .
Object 2 .tlll h •• an active
reference (b), and •• long
as It does, the object I. not
eligible for GC.
ActIve References: 1
null References: 1
Reachable Objects: 1
Abandoned Objects: 1
Book
68 chapter 3
primitives and references

An array is like atray of cups


o Declare an int array verinble. An array variable is
a remote control to an array object.
int[] nums;

Create a new int array with a length


of 7 and assign it to the previously-
I

declared int r J variable nums

nums = new int[7] ;

Give each element in the array


an int value.
Remember, elements in on int
array are just int variables.

~
.:is
.3'
nums [0] = 6;
~
~ nums[l] = 19 ;
~
·s nums[2] = 44:
nums[3] = 42: int array object (int[])
nums [4] = 10:
nums[5] = 20;
nums [6] ='1; int[] Notit~ that. -tne a'rYa'f ihtlt is dl'l objtd:,
evel'l t.h~h ~e I tltMtl'lt.s art f\"i",j·I:.'Ives.

Arrays are objects too


Java standard library includes reference variable. Anything you Be sure to notice one key thing
of sophisticated data structures would put in a variable of that rype in the picture above - the arm)' is
uding maps, trees. and sets can be assigned to an array element an object, even though it's an array of
Appendix B). but arrays are of that type. So in an array of type primitives.
t when you just want a quick. int (int[]) . each element can hold
Arrays are always objects, whether
red, efficient list of things. an int, In a Dog array (Dog[]) each they're declared to bold primitives
,"'5 give you fast random element can hold... a Dog? No. or object references. But you can
ess by letting you use an index remember that a reference variable have an array object that's declared
ition to get to any element in just holds a reference (a remote to hold primitive values. In other
array. control), not the object itself. So words, the array object can have
in a Dog array, each element can elements which are primitives. but
ry element in an array isjust
hold a remote control to a Dog. Of the array itself is nevera primi tive,
nriable. In other words, one of
course, we still have to make the Regardless of what the array holds,
eight primitive variable types
. k: Large Furry Dog) or a Dog objects... and you'll see all that the array itself is always an objectl
on the next page.
you are here. 59
an array of objects

Make att array of Pogs

o Declare a Dog array variable


Dog[] pets;

A Create a new Dog array with


W a length of 7, and assign it to
the previously-declared Dog [J
variable pets

pets = new D09[7];

What~ .ttfsShtg1
Dogsl We have an array
of Dog rmrence$, but no
actual Dog obJects I
Dog array object (Dog[])

A Create new Dog objects, and


V assign them to the array
elements.
Remember, elements in a Dog
array are just Dog reference
variables. We still need Dogs!

pets[D] = new Dog();


pets[l] = new Dog();

_~~~~i:/_t
n,~~:':~:f
--~dmake
_
-ne ofthe
11 objects? Dog array object (Dog[])

58 (.. .r 3
primitives and references

, name
Dog Cot1trol your ~og
(with a referetlce variable)
barkO
Dog fide = new Dog();
eatO fido.name = ~FidoN;
chaseCalO
We created a Dog object and
used the dot operator on the
reference variable fido to access
the name variable."
We can use the fido reference
to get the dog to barkt) or
eat/) or chaseCatO .
fido.bark() i Dog
Java cares about type. fido .chaseCat();
Once you've declared an array. you
can't put anything an It except thing-
that are of the declared array type.
What happetts ifthe POQ is Itt
For example, you can't put Q COt into a Dog
a OOQ array?
array (it would be pretty awful if someone ~e know we can access the Dog's
thinks that only Dogs are inthe orrat, so Instance variables and methods using
the.y ask eoch one to ~ark, and th~n to their the dot operator, but em what1
horror discoverthere s a cat lurkmg.) And
you can't stick a double into on int orr'atl When the Dog is in an array, we don't
(spillage., remember?). You can, however. have an actual variable name (like
put Qbyte into on in t arraf, b~QuSe a fido). Instead we use array notation and
byte will always fit into on int-SIZed cup. push the remote control button (dot
This is known as an Implicit wid&ning. We''' ~perator) on an object at a particular
gat Into the details tater. for now just Index (position) in the array:
remember that the compiler won't 1st you
put the wrM'9 thing In on orraf, based on Dog[] myDogs = new Dog[3];
the Gtf'OY's d&elored type. myDogs[O] = new Dog() ;
myDogs[O].name = "Fido";
myDogs[O] .bark();

'Yes weknow we're notdemonslralin -


trying tokeep it simple. For now. We'1IgdencapsuiatiOn he_reo butwe're
0 encapsulation 10 chapter 4.

you are here ~ 61


using references

class Dog (
Str ing name ; A Pog exatMple
publ i c static void main (String() args) Dog
II make a Dog ob ject and a c cess it
name
Dog dogl = new Dog();
dogl.bark{) ; barkO
eatO
dogl.name = "Bart" ;
chaseCal()

I I now mak e a Dog ar ra y


Dog() myDogs = new Dog[3); Output
I I a nd put s ome dog s i n i~

myDogs[O ) ne w Dog () ;
myDogs[l ) new Dog () ;
myDogs [2 ) dog!;

/1 now Rece s s t he Dogs u s i ng t he ar r a y


I I r e f e r e nce s
myDogs(O).name " Fr e d " ;
myDogs(l).narne "Marge " ;

II Hmmnm . . . wha t i s myDogs (2 j name?


System.out .print( "!ast dog's name is ");
Sys t em. ou t . pr in t l n (myDogs (2) . narne ) ;
• Variables come intwo flavors: primitive and
II now 100 t hr ough t he a r r y reference.
I I a nd t e l l all dog s t o ba rk • Variables must always be declared with aname
and a type.
i nt x = 0;
mYDOgs .1ength)~
• Aprimitive variable value isthe bits representing
whi1e(x < J
the value (5, 'a', true, 3.1416, etc.).
myDogs [xl .ba r k () ; a \/aYiab\c l'~~ • Areference variable value isthe bits
x = X + 1; ay-yii'(S ha\/C t."c l'I~bCl" representing away to get to an object on the
t)lat. ~\\/ts 'lOlA a'J heap.
L' t,\lc jlY"Y I
e\e,.,.tf\'V 11'1
• Areference variable is like aremote control.
Using the dot operator (.) on a reference
variable islike pressing a button on the remole
pUblic void bark() (
control to access amethod orinstance variable.
System.out.prin tln(narne i- " says Ruff !");
• Areference variable has a value of n u 11 when
it is not referencing any object
pUblic vo i d ea t ( ) { • An array is always an object, even if the" array
p ub lic voi d c ha s e Ca t () isdeclared to hold primitives" There is no such
thing as a primitive array, only an array that
holds primitives.

62 chapter 3
prlmltlves and references

BE the cornriler
Each of the Java nles on this page
represents a cOtIlplete source file.
Your job is to play compiler and
detel"llline whether each of these files
will compile. If they won't
cmqpile, how would rOll
fIX them?

A B
class Books { class Hobbits {
String title;
String author; String name;
}
public static void main(String (J args) {
class BooksTestDrive
public static void main(String Ij args) Hobbits () h = new Hobbits[3]i
int z = 0;
Books () myBooks :: new Books(3);
int x :: 0; while (z < 4) {
myBooks{Oj.title :: "The Grapes of Java"; z = z + 1;
myBooks(lj.title = ~The Java Gatsby"i hlz] :: new Hobbits();
myBooks(2).title :: ~The Java Cookbook"; h{z] .name = "bilbo"i
myBooksIO).author = "bob"; if (z == I) {
myBooksllj.author:: "sue"; hlz].name:: "frodo";
myBooks(2).author = "ian"; }
if(z==2){
wbile (x < 3) { h[z).name = Usam";
System.ou t.print(myBookslxj.title)i
System.out.print(" by U)i System.out.print (h{z).name + " is a H);
System.out.println(rnyBooks[xj.author) ; System.out.println(Ugood Hobbit name");
x = x + 1;
} }

you are here. 63


exercise: Code Magnets

Code Magnets
Aworking Java program Is all scrambled up int Y ==
on the fridge. Can you reconstruct the code
snippets to make a working Java program index(y) ;
that produces the output listed below?
Some of the curly braces fell on the floor
and they were too small to pick up, so feel
free to add as many of those as you need!

int ref;
while (y < 4) {

System.out.print1n(islands{refj)i

index(Ol .,. 1;
index(ll '" 3;
index (21 == 0;
index[31 .,. 2; ~

String (] islands new String(4)i

System.out.print(Uisland ; U);

int [1 index ""


new int[4Ji
y y + 1;

class TestArrays {

public static void main(Strin N


":J rJ args) {

64 chapter 3
primitives and references

class Triangle
double arear
int height;
pool puzzle iot length;
public static void main(String [] args)
Your Job is to take code snippets from
the pool and place them into the
blank lines in the code. You may
use the same snippet more than while ( ) {
once, and you won't need to use
all the snippets .Your gOlll is to _______ .height (x + 1) * 2:
make a class that will compile and
run and produce the output listed. _______ .leogth x + 4:

System.out.print( "triangle "+x+" I area"};


Output
System.out.println(" =" + .area):

x = 27:
Triangle tS = ta[2]:
ta[2J.area = 343:
System.out.print(uy = U + y):
System.out.println(", tS area = "+ tS.area};
Bonus Questlonl }
For extra bonus points, use snippets void setArea() {
from the pool to fill in the missing
output (above). (height * length) / 2;
}
} Note: Each lnlppet
from the pool nn be
used more than oncel

yo u are here ~ 65
puzzle: Heap o' Trouble

class HeapQuiz {
int id == 0;
A Heap 0' Trouble public static void main(String [] argsl
int x = 0;
A short Java program is listed to the
HeapQuiz ( ] hq = new HeapQuiz(S]i
right. When '/1 do stuff' is reached, some
objects and some reference variables while ( x < 3 1 (
will have been created. Your task Is hq[x) = new HeapQuiz();
to determine which of the reference hq(x] . id == Xi
variables refer to which objects. Not all x = X + 1i
th e reference variables will be used, and
}
some objects might be referred to more
than once. Draw lines connecting the hq[3] == hq[l]i
reference variables with their matching hq[4] hq[l] ;
objects. hq[3] = null;
Tip: Unless you 're way smarter than us, hq (4) hq (0] ;
you probably need to draw diagrams hq(Ol == hq(31i
like the ones on page 55 and 56 of th is
hq(3] hq[2];
chapter. Use a pencil so you can draw
and then erase reference li nks (the hq[2] = hq [0] ;
arrows goIng from a reference remote II do stuff
control to an object).

Reference Variables: HeapQulz Objects:

hq[O]

hq[1]

hq[2]

10

~~
hq[3]

hq[4]
ftil
64 chapter 3
primitives and references

The case of the pilfered references

It was a clark and stormy night Tawny strolled into the programmers' bullpen like she
owned the place. She knew that all the programmerswould still be hard at work, and she
wanted help. She needed a new method added to the pivotal class that was to be loaded into the
client's new top-secretJava-enabledcell phone. Heap space in the cell phone's memory was
as tight as Tawny's top, and everyone knew it The normally raucous buzz in the bullpen fell to
silence as Tawny eased her way to the white board. She sketched a quick overview of the new
method's functionality and slowly scanned the room. 'Well boys, it's cnmch time", she purred.
'Whoever creates the most memory efficientversion ofthis method is coming with me to the
client's launch party on Maui tomorrow... to help me install the new software."
The next morning Tawny glided into the bullpen wearing her short Aloha dress.
"Gentlemen", she smiled, "the plane leaves in a few hours, show me what you've
got!". Bob went first; as he began to sketch his design on the white board Tawny
said, "Let's get to the point Bob, show me how you handled updating the list of con-
tact objects." Bob quickly drew a code fragmenton the board:

Contact I) ca = new Contact[10];


while ( x < 10 ) { II make 10 contact objects
calx) new Contact()i
x = x + 1;

II do complicated Contact list updating stuff with ca

"Tawny r know we're tight on memory,but your spec said that we had to be able to access
individualcontact informationfor all ten allowablecontacts, this was the best scheme I could
cookup", said Bob. Kent was next, already imagining coconut cocktails with Tawny, "Bob,"
he said, "your solution's a bit kludgy don't you think?" Kent smirked,"Take a look at this
baby":

Contact. refc;
while ( x < 10 ) { II make 10 contact. objects
refe = new Cont.act()i
x = x + 1;
I
II do complicated Contact list updating stuff with rete

"I saved a bunch of reference variables worth ofmemory,Bob-o-rino, so put away your
sunscreen", mocked Kent "Not so fast Kent!", said Tawny, "you've saved a little memory, but
Bob's coming with me.''.

Why did Tawny choose Bob's method over Kent's, when Kent's used Jess memory?

you are here t 67


exercise solutions

class Books {
Exercise Solutions String title;
String autbor;

class BooksTestDrive (
public static void main{String I) args)
Books II myBooks = new Books(3);
int x = 0:
A myBooks[O] :: ntw 9ooksO; IUrnanber: We hGvt to
Code Magnets: myBooks[1] :: ntw BooksO: actuclily InQJc.e the BooI<s
myBooks[2] :: new BooksO: objects I ~~----=- ----l

class TestArrays myBooksIO].title = uThe Grapes of Java';


myBooksll] .title = "The Java Gatsby·;
pUblic static void main(String () args) {
myBooks[2].title = NThe Java Cookbook';
int [) index = new int{4]:
myBooks[O].author = Nbob';
index[O) I: myBooks[l].author = Nsue";
Lndex] 1) 3: myBooks[2].author = "ian";
index[ 2) 0: while (x < 3) {
index(3) 2; System.out.print(myBoOks(x).title)i
String (] islands = new String[4]: System.out.print(" by ")j
system.out.println(myBooks[x).author);
islandslO] "Bermuda":
x e X + 1;
islandsjl] = "Fiji";
islands(2] "Azores H :

islands{3] "Cozumel";
int y = 0:
class Hobbits {
int ref;
String name:
while (y < 4) {
public static void main{String I) args) {
ref = index(yl;
Hobbits () h = ne_w=--H..:.ob::..:b7i:...:t..:.s~(3:....:)~: ~,....,....-,
system.out.print("island = H); Int :z :: -1; I
Remember: o.rrcys start with
System.out.println(islandslref]l; whfle (z ( 2) ( element 0 )
y = y + 1; z = z + 1i ------------

}
h[z] = new Hobbits{):
B h[z].name = "bilbo';
if (z == 1) {
} b[z].name = "frodo"j
)
if(z==2){
b[z].name = "sam";
}
System.out.print(hlz).name + " is a H);
system.out.println{"good 80bbit nameH)j

68 chapter 3
primitives and references

Puzzle Solutions

The case of the pilfered references

class Triangle Tawny could see that Kent's method had a serious
double area; flaw. It's true that he didn't use as many reference
int height; variables as Bob , but there was no way to access any
int length, but the last of the Contact objects that his method cre-
public static void main(String [1 argB) {
lnt x = 0:
ated. With each trip through the loop, he was assign -
Triangle [ ] tel = new Trlangle[4]; ing a new object to the one reference variable, so the
while ( x • 4 ) { previously referenced object was abandoned on the
tel[x] =new Tr/ClllglcQ; heap - unreachable. Without access to nine of the ten
~x].he19ht ~ (x + 1) * 2; objects created, Kent's method was useless.
talx]. length =x + 4; (The software was 8 huge success atKl the dlent gave Tawny and Bob anextra week
talx) . set.Arec(); In Hawa~. we'dlike to ~ you that byfinishing this book you too wil get stuff like IhaL)
System.out.print(~triangle ~+X+". area"),
System.ouLprintln(U - N + talx).area);
x=x+1; HeapQulz Objects:
Reference Variables:
}
Int 'I = x:
x - 27;
Triangle tS ~ ta[2J;
ts[2J.area = 343; hq[O]
Syatem.out.print(Ny = U + Y);
System .out.println(", tS area " U+ tS.area);
}
void setArea() {
~ = (height· length) J 2;

~
;, java Triangle
triangle 0, area 4.0
triangle 1. area 10 .0
criangle 2 , area 19 .0
triangle 3 , area 28.0
'i = 4, t5 arca = 343

you are here ~ 69


4 methods use Instance variables

How Objects Behave

State affects behavior, behavior affects state. We know that objects

have state and behavior, represented by Instance variables and methods. But until now, we

haven't looked at how state and behavior are related . We already know that each instance of a

class (each object of a particular type) can have its own unique values for its instance variables.

Dog A can have a name "Fido" and a weight of 70 pounds. Dog B Is"Killer" and weighs 9 pounds.

And If the Dog class has a method makeNoiseO,well , don't you think a 70-pound dog barks a

bit deeper than the little 9-pounder7 (Assuming that annoying ylppy sound can be considered

a bark.) Fortunately, that's the whole point of an object-It has behavior that acts on its state. In

other words, methods use /nstllnn vllt/llb/Ift values . Like,"if dog Is less than 14 pounds, make

ylppy sound, else..." or "Increase weight by 5~ Let's go chllnge some stat«,

this Is a new chap ter 71


objects have state and behavior

RetMetMber: a class describes what an


object knows and what at1 object does
A class is the blueprint for an object. When you Song

write a class, you're describing how theJVM lt1stat1ce title kt10ws


should make an object of that type. You already variables artist
know that every object of that type can have (state)
different instance variable values. But what about setTItleO
the methods? 'Methods setArtlstO does
(behavior) playO
Ca" every object of that type have dlfferettt
lMethod behavior?
Well... sort cif.*
Every instance of a particular class has the same
methods, but the methods can behave differently
based on the value of the instance variables.
The Song class has two instance variables, title
and artist. The playO method plays a song. but
the instance you call playO on will play the song
represented by the value of the title instance
variable for that instance. So, if you call the playO
method on one instance you'll hear the song
"Politik", while another instance plays "Darkstar",
The method code, however, is the same.
void pla.y ( ) {
soundPlayer.playSound(title);
}

Song
Song t2 = new Song(); 83 .play () ;
t2.setArtist("Travis");
t2.setTitle("Sing");
Song s3 = new Song();
I
C-illi~ playO 0l'I this iflSta~te
s3.sstArtist("Sex Pistols"); will t4lASe "My W;Y:: to play.
s3 . setTi tie ("My Way") ;
(blAt PI~ the ~r.ab-a ~d

·Yes. another stunningly clearanswerl

72 chapter 4
methods use instance variables

esize affects the bark


AtlD3cIJ Dog's bark is different from a big Dog 's bark.
og class has an instance variable size, that the
me th od uses to decide what kind of bark sound

Dog
Dog (
s i ze ; size
name
;;: =':' ng name;
bark()
_:'0 ba r k () {
:.f (size> 60)
System .out.println("Wooof! Wooof!"};
el s e i f (size> 14) {
System ,out.println("RUff! Ruff!");
else (
System.out.println("Yip! Yip!-);

~: = s s DogTestDrive {

pub li c static void main (String! J args) {


Dog one = new Dog();
one.size = 70;
Dog two = new Dog();
two ,size = 8;
Dog three = new Dog();
three.size = 35;
~
~ j ava DogTestDrive
one. ba rk () ;
Wooof! Wooof I
two.bark () ;
'lip! Yip!
three.bark/);
Ruff! Ruff!

you are here. 73


method parameters

You can send things to a tttethod


Just as you expect from any programming language, you aU1 pass values into
your methods. You might, for example, want to tell a Dog object how many
times to bark by calling:
d.bark(3) ;
Depending on your programming background and personal preferences,
you might use the term arguments or perhaps paramet.ers for the values passed
in to a method. Although there emformal computer science distinctions that
people who wear lab coats and who will almost certainly not read this book.
make. we have bigger fish to fry in this book. So yuu can call them whatever
you like (arguments, donuts, hairballs, etc.) but we're doing it like this:
A method ~ parameters. A caller passes arguments.
Arguments are the things you pass into the methods. An argument (a value
like 2, "Faa", or a reference to a Dog) lands face-down into a... wait for it..
parameter. And a parameter is nothing more than a local variable. A variable
with a type and a name, that can be used inside the body of the method
But here's the"important part: If a method takes a parameter, you mustpass
it something. And that something must be a value of the appropriate type.

Dog d = new Dog() ;


Call the bark method on the Dog refer-
O ence, and pass in the value 3 (as the d.bark(3) ;
argument to the method). ~ aY'~~",e~t.
A The bits representing the int
W value 3 are delivered into the
bark method.

P~,"d_~," l:>''\. A
V
The bits land in the numOfBarks
parameter (an int-stzec variable).
~ in
void bark (int numO arks) {
Use the numOfBarks
while (numOfBarks > 0) { O parameter as a variable in
the method code.
System.out.println("ruff");
numOfBarks = numOfBarks - 1;
}
}
74 chapter 4
methods use instance variables

You ca., get thi.,gs backfrottt a lMethod.


ods can return values. Every method is declared with a return
. but until now we've made all of our methods with a void
type, which means they don't give anything back.

re can declare a method to give a specific type of value


to the caller, such as:
~ giveSecret ()
return 42;

declare a method to return a value, you must


a value of the declared rypel (Or a value
. (()mpatiblewith the declared type. We'll get
at more when we talk about polymorphism
pter 7 and chapter 8.)

atever you say


'II give back, you
tter give back!

t - life. giveSecret () ;

giveSec et () {
return 42-
t,nis "'~ ~it.
} . tJ
ill aWl \WI\...

you are here ~ 75


.
multiple arguments

You can send ",ore than one thing


to a tMethod
Methods can have multiple parameters. Separate them
with commas when you declare them, and separate the
arguments with commas when you pass them. Most
importantly, if a method has parameters, you must pass
arguments of the right type and order.

Call1"Q a two-paralMeter IMethod, altd seltdh,g


It two arQuIMe"ts.
void qo () {
TestStuff t = new T8Ststuff()i
t.takeTwo(12, 34);

lnt z = x
\\
void takeTwo(int x, int y)

+ y;
(

Systam.out.prinUn ("Total. is " + z);


. )

You ca" pass variables h'to a IMethod, as lo"c.1 as


the variable type IMatches the paraIMefer type.
void qoO (
int faa = 7;

int bar = 3;
t. takeTwo (foo, bar);

\~
void takeTwo(int x, int y)
int z ... x + Yi
System. out . println ("Total is rr + z);

76 chapter 4
methods use instance variables

Java is pass...by...value.
=
That tMea"s pass"'by"'copy.
-----
Declare an in~nd assign it
int x = 7;
int
O the value '7. The bit pattern for 7
goes into the variable named x.

void go(int z){ }~ int


A
'iii'
Declare a method with an int
parameter named z.

f t Call the goO method, passing


W the variable x as the argument.
The bits in x are copied, and
the copy lands in z.
int int
foo.go(x) ; void qo(int z){ }

lit
e'Vb\
dots,,'f. thci
• f' ~ d~.113
,~ 4:'\1 .,
~. . . . a.,.d
~~t~g
L. j
'J.. d'f't":-\:' tf A
V
Change the value of z inside
the method. The value of x
doesn't change! The argument
><: ·.. · · · · ···0···.. · · · · ... passed to the z parameter was
int
void go(int z){
z = 0;
mt
---
only a copy of x.
The method can't change the
bits that were in the calling
variable x.
}

you are here. 77


arguments and return values

Q:What happens Ifthe argument you want to Reminder: Java


pass Is an object Instead of II primitive?
cares about type!
A: You'll learn more about this In later chapters,
but you already know the answer. Java passes
You can't return a Giraffe when
the return type Is declared
everything by value. EverythIng. But... value means as a Rabbit. Same thing with
bits Inside the vcrtable. And remem ber,you don't parameters. You can't pass a
stuff objects Into variables; the variable Is a remote Giraffe Into a method that
control-a reference to an object. So If you pass a takes a Rabbit.
reference to an object into a method, you're passing
a copy of the remote control. Stay tuned, though, we'll
have lots more to say about this.

Q..: Can a method declare multiple return values?


Or Is there some way to return more than one
value? • Classes define what an object knows and whal an
object does.

A: Sort of. A method can dec lare onIy one return


value. BUT... If you want to return, say, three int values,
• Things an object knows are its Instance variables
(state).
then the declared return type can be an Int orray.
• Things an object does are its methods (behavior).
Stuff those lnts into the array,and pass It on back. It's
a little more involved to return multiple values with • Methods can use instance variables so that objects
different types; we'll be talking about that in a later of the same type can behave differently.
chapter when ~e talk about ArrayLlst.
• Amethod can have parameters, which means you
can pass one ormore values in to the method.
'Q :Do I have to return the exact type , declared?
• The number and type ofvalues you pass inmust
A.: You can return anything that can be implicitly
promoted to that type. So, you can pass a byte where
match the order and type of the parameters
declared bythe method.
an Int Is expected .The caller won't care,because the • Values passed inand out ofmethods can be
byte fits Just fine Into the tnt the caller will use for implicitly promoted to a larger Iype orexplicitly cast
assigning the result. You must use an explicit cast to a smaller type.
when the declared type Is smaller than what you're
trying to return. • The value you pass as an argument toa method
can be a literal value (2, 'c', etc.) ora variable of
Q..: Do I have to do something with the return the declared parameter type (for example, x where
x is an intvariable) . (There are other things you
value of a method? can IJust Ignore it?
can pass as arguments, but we're not there yet.)

A :Java doesn't require you to acknowledge a


return value. You might want to call a method with
• Amethod must declare a retum type.Avoid retum
type means the method doesn't return anything.
a non-void return type, even though you don't care • Ifa method declares a non-void return type, it must
about the return value. In this case, you're calling
return a value compatible with the declared return
the meth od for the work it does inside the method,
rather than for what the method gives returns . In
type.
Java, you don't have to assign or use the return value.

78 chapter 4
methods use instance variables

"ttgs you catt do with parameters


returtt types
_ _.... .e've seen how parameters and return types work, it's ElectrlcGultar
them to good use: Getters and Setters. If you're into
rm al about it, you might prefer to call them ACC610TS brand
.Jw.;ifO;OOIrl. But that's a waste of perfectly good syllables. numOfPickups
Gc ters and Setters fits the java naming convention. so rockStarUsesl1
~,wl:l2 l we'Il call them.

nd Setters let you, well, get and sa things. Instance van-


1r:1_JeS. usually. A Getter's sole purpose in life is to send back, getBrandO
~az!lnl value, the value of whatever it is that particular Getter selBrandO
".-as.:d to be Getting. And by now, it's probably no surprise getNumOfPickuPSO
1&3, ~ner lives and breathes for the chance to take an argu-
.~1De and use it to set the value of an instance variable. setNumOfPickupsO
getRockStarUsesltO
setRockSlarUsesllO

- i.DcJ brand i
• numOfPiclcups;
.an rockStarUs8sIt;

Si:.:-'.-nCJ qetBrand ()
return brand;

id s8tBrand (String &Brand) (


brand = &Brand i

• getNumOfPickups() {
return numOfPickups;

:.d setNumOfPickups (int num)


numOfPickups = num;

.an g8tRockStarusealt()
=-~rn rockStarUseslt;

setRockStaruseslt(boolean y&sOrNo) {
~tarU8eslt m yesOrNoi

you a re he re. 79
real developers encapsulate

Et1capsulaffot1
00 It or risk hUlMlliatiot' at'd
ridicule.
Until this most important moment, we've
been committing one of the worst 00
faux pas (and we're not talking minor
violation like showing up without the IB'
in BYOB). No, we're talking Faux Pas with
a capital 'F' . And ·P'.
Our shameful transgression?
Exposing our datal
Here we are.just humming along without
a care in the world leaving our data out
there for anyoru to see and even touch.
You may have already experienced that
vaguely unsettling feeling that comes with
leaving your instance variables exposed.
Exposed means reachable with the dot
operator, as in:
theCat.height : 27;
.T hink about this idea of using our remote
control to make a direct change to the Cat
object's size instance variable. In the hands
of the wrong person, a reference variable
(remote control) is quite a dangerous
weapon. Because what's to prevent:

~\l.ts~ Wt.
't.
eA" 1
theCa t. height = 0; 1e-t ~i5. "ayYt".

This would be a Bad Thing. We need to public void setBeight (int ht) {
build setter methods for all the instance
variables, and find a way to force other
if (ht > 9) {
code to call the setters rather than access height: ht;
the data directly. }

80 chapter 4
methods use Instance variables

'"
thedata Java'~ed
it is that simple to go from This week's Interview:
implementation that's just An Object gets candid about encapsulation.
. g for bad data to one
HeadFirst What's the big deal about encapsulation?
protects your data and
ects your right to modify Object: OK.,you know that dream where you're givinga talk to 500 people when you
implementa tion later. suddenly realize- you're TUJkaP.
so how exactly do you HeadFirst: Yeah, we've had that one. It's right up there with the one about the Nates
the data? With the machine and... no, we won't go there. OK, so you feelnaked. But other than being a little
lie and private exposed, is there any danger?
ess modifiers. You're Object Is there any danger? Is there any danger? [St3.I'1S laughing] Hey, did all you other
. iar with public-we use instances hear that, "Is lhert aT[! danger?" he asks? [falls on the floor laughing]
rith every main method.
HeadFirst: What's funny about that? Seems like a reasonable question.
re's an encapsulation
Object: OK, I'll explain it. It's [bW'StS out laughing again, uncontrollably]
nile of thumb (all stan-
disclaimers about rules HeadFirst: Can I get you anything? Water?
~ thumb are in effect): mark Object: Whew! Oh boy. No I'm fine, really. I'll be serious. Deep breath. OK, go on.
instance variables privati!
provide public getters HeadFirst: So what does encapsulation protect you from?
setters for access control. Object Encapsulation puts a force-fieldaround my instance variables, so nobody can set
you have more design them to, let's say, something inappropriaJ.e.
codi ng savvyin Java, you HeadFirst Can you giveme an example?
bably do things a little
rently, but for now. this Object: Doesn't take a PhD here. Most instance variable values are coded with certain
I!!!IlP:oach will keep you safe. assumptions about the boundaries of the values. Like, think of all the things that would
break if negative numbers were allowed. Number of bathrooms in an office. Velocity of
an airplane. Birthdays.Barbell weight Cellphone numbers. Microwaveoven powet
HeadArst: I see what you mean . So how does encapsulation let you set boundaries?
Object By forcing other code to go through setter methods. That way, the setter method
can validate the parameter and decide if it's do-able. Maybe the method will reject it and
do nothing, or maybe it'll throw an Exception (like if it's a null social security number
ark getters and for a credit card application), or maybe the method will round the panlITleter sent in to
etters pUblic. the nearest acceptable value. The point is,you can do whatever you want in the setter
method, whereas you can't do aT[!thing if your instance variables are public.
HeadFirst: But sometimes I see setter methods that simplyset the value without check-
ing anything: If you have an instance variable that doesn't have a boundary, doesn't that
sener method create unnecessary overhead? A performance hit?
·Sodly. Bill forgot to
CftCopsulQt~ his Cat class and Object: The point to setters (and getters, too) is that you can c1umge your mind later,
ended up wltk Q flat cat . H without breaking any1Jo4y else's code! Imagine if half the people in your com-
(overheard at the water cooler). pany used your classwith public instance variables, and one day you suddenly realized,
"Oops- there's something I didn't plan for with that value, I'm going to have to switchto a
setter method." You break everyone'scode. The cool thing about encapsulation is that you
get to cJumgt)'CUT mind. And nobody gets hurt The performance gain from using variables
directly is so rniniscule and would rareIy--if DJn- be worth it
you are here ~ 81
how objects behave

class GoodDog (
Ettcapsulatittg the GoodDog
t}oodPog class /I
.~.,.t,L
private int size;
size
tJ\o¥-t. .\.)\t. \. #. ,/ -
~o~
'\ ,,\ l\ t.
0
~ public int getSize ()
gelSize( }
~ ) r,turn ,i,e,
selSize( )
bark( )

t). ~~ al\G ~ public void setSi"le (int s) (


Ma'¥.t. t..1.\..~~ ~.
~tt.~ ",CV' size = s r

void bark () (
i f (size > 60)
System .out.println("wooof! Wooof!");
else i f (size> 14) (
Syscem.out.princln("Ruff! Ruff!");
else (
System .out.println( "Yip! Yip!");

I.Any place where a


particular value can class GoodDogTestDrive I
be used, a method
call that returns that public static void main (String!) args) (
type can be used. GoodDog one = new GoodDog();
one .setSize(70);
GoodDog two = new GoodDog();
Instead of:
two.setSize(8);
int x =3 + 24;
System .out.printlnI WDog one: + one.getSize(»;
you can say: System.out.printlnl"Dog two: " + tWQ.getSize(»;
int x =3 + one.gdSize(); one. bark ();
two. bark () ;

82 chapter 4
methods use instance variables

How do objects I" a" array


have?
like any other object. The only difference is
. you get to them. In other words, how you get
remote control. Let's try calling methods on
objects in an array.

Declare and create a Dog array,


to hold 7 Dog references.
Doq[] pets;
pets = new Doq[7];

Dog array object (Dog[])


Dog[]

Create two new Dog objects.


and assign them to the first
two array elements.
pets [0] = new Dog () ;
pets[l] = new Dog();

Call methods on the two Dog


objects.
pet8[O].setSize(30) ;
int x =
pets[O] .qetsize();
peta[l) .setSize(8);

Dog array object (Dog[])


Dog[]
you are here ~ 83
Initializing instance variables

Peclarfttg and initializing


ittstatlce variables
Instance variables
You already know that a variable declaration needs at least a name
and a type : always get a
int size; default value. If
String name;
you don't explicitly
And you know that you can initialize (assign a value) to the assign a value
variable at the same time:
to an instance
int size =420;
String name =
"Donny"; variable, or you
don't call a setter
But when you don't initialize an instance variable, what happens
when you call a getter method? In other words, what is the value of
method, the
an instance variable bejoreyou initialize it? instance variab'e
t,al'll.t IIayia\,\es, still has a value!
class PoorDog ( dtt\a'Ct t..,o i~ ~ IIalw.
. . / } \:l",t. d()t\' t. a~I~1\ integers 0
private 1nt size; k'~
private String name; floating points 0.0
What will -tnue: 'Cd!.',",?? booleans false
P)ubliC int getsize () (~
return size; If references null
public String getName () (
return name;

, Y.-? y.l\\\
public class PoorDogTestDrive { ~\:, ~o ~O'" t.~j ,
public static void main (String [] args) ( / . "'1\ t,O"'~
PoorDog one =
new PoorDog () ; '.!. ~\~ e )
System.out.println("Dog size is " + one.getSize(»);
System.out.println("Dog name is " + one.getName(»);

% java PoorDogTestDrive
Dog size is 0
Dog name is null

84 chapter 4
methods use instance variables

fhe differet1ce betwee" it1sfat1ce


at1d local variables

o Instance variables are declared


inside a class but not within a method. Local variables do
class Horse ( NOT get a default
private double height 15.2; value! The compiler
private String breed;
II more code . . . complains if you
try to use a local
variable before

e Local variables are declared within a method.


the variable is
initialized.
class AddThing {
iot a;
int b = 12;

public iot add() {


int total = a + b;
return total;
Q: What about method parameters?
How do the rules about local variables
apply to them?

A:
e Local variables ~UST be initialized before usel
Method parameters are virtually the
same as local variables-they're declared
Inside the method (well, technically they're
declared in the argumenr ltst of the method
class Foo { "I\e" Yov. u~ rather than within the body of the method,
public void go () W()\'l t to"''' ' t~ ~ a 'Ja\~,
(
Ln t x; deda ye Yo WI 0 b-1
nl.&t. as $CO¥\ as 'f~ .
but they're still local variables as opposed to
Instance variables). But method parameters
Lrrt z = x + 3; to ~ it, ~e l.oft<~\ tr will never be uninitialized, so you'll never get
"------- ~~ea~ ol.&-t. a complier error telling you that a parameter
variable might not have been initialized.
But that's because the compiler will give
you an error if you try to invoke a method
File Edit Window He! 'r'lke6
without sending arguments that the method
% javac Foo.java needs. So parameters are ALWAYS initialized,
because the compiler guarantees that
Foo.java:4: variable x might methods are always called with arguments
not have been initialized that match the parameters declared for the
method, and the arguments are assigned
int z = x + 3; (automatically) to the parameters.
1 error

you ar e he re . 85
object equality

Colttpari"Q variables (primitives or refere.,ces)


Sometimes you want to know if two primitives are the same. That's easy
enough, just use the = operator. Sometimes you want to know if two
Use ==to compare
reference variables refer to a siogle object ~>n the heap. Easy as well, jusl use two primitives,
the == operator. But sometimes you want to know if two objects are equal. or to see if two
And for that, you need the .equals 0 method. The idea of equality for references refer to
objects depends on the type of object. For example, if two different String the same object.
objects have the same characters (say. "expeditious"), they are meaningfully
equivalent, regardless of whether they are two distinct objects on the heap. Use the equalsO
But what about a Dog? Do you want to treat two Dogs as being equal if they method to see
happen to have the same size and weight? Probably not. So whether two
different objects should be treated as equal depends on what makes sense for
if two diHerenf
that particular object type . We'll explore the notion of object equality again objects are equal.
in later chapters (and appendix B), but for now, we need to understand that (Such as two different
the == operator is used emly to compare the bits in two variables. What those String objects that both
bits represent doesn't matter. The bits are either the same, or they're not. represent the characters
In "Freel")
To compare two primitives, use the == operator
The = operator can be used to compare two variables of any kind, and it
simply compares the bits.
if (a = b) {...j looks at the bits in a and b and returns true if the bit pattern
is the same (although it doesn't care about the size of the variable, 50 all the
extra zeroes on the left end don't matter). ~~ 0" )(~\
oV'e u'( t
in t Ii = 3;

byte b
i f (a
= 3;
== b) { II tl:Ue }
(t.t.t'«( aye.'" J t"e iYl ,
rt ~\de
.lc.he \tJ(
\,~t. 'Ole o.~
t.'hat n('(e) ,
L~t
't. (.4'(e 61l
.
a--
int
--
byte

To see If two references are the same (which means they


refer to the same object on the heap) use the operator ==
Remember, the == operator cares only about the pattern of bits in the
variable. The rules are the same whether the variable is a reference or
primitive . So the == operator returns true if two reference variables refer to
the same objectl In that case, we don't know what the bit pattern is (because
it 's dependent on theJVM, and hidden from us) but we M know that whatever
it looks like, it wiU be the samefor two refmrues to a singleobject.
Foo a = new Foo();
Foo b = new Foo();
Foo c = a;
if (a == b) { II false } Foo
a=t.ish"\oI.e
if (a -- c) ( II true )
a = b is .falst
i f (b --
c) ( II false ) Foo
Foa

86 chapter 4
methods use Instance variables

Make ,t st,tk
Roses are red,
this poem ischopPY,
. byvalue
passing
;s passing by copy,
1 it.Replace our
can do better? r'J 8e~ryet.
Oh,like yoU d llne with your ow'" wn wOld~
dumb secon I thing with YOUl 0
theY/ho e
replace forget it.
a"d you'll never

int a '" calcArea(7, 12);


What's legal?
Given the method below, which
KEEP short c '" 7;

of the method calls listed on the


right ore legalt
Put a checkmcrk next to the
+-
RIGHT
calcArea (c,15) ;

int d '" calcArea(S7);

calcArea (2,3) ;
ones that are legal. (Some
statements are there to assign long t '" 42;
values used in the method colis).
int f = calcArea(t,17);

int 9 '" calcArea();


int calcArea(int height, int width) calcArea () ;
return height • width; byte h = calcArea(4,20);

int j = calcArea(2,3,5);

you are here ~ 87


exercise: Be the Compiler

BE the oomriler
Each ofthe Java files on this page
represents a complete source file.
Your joh is to play collll'iler and
determine whether each ofthese files
will compile. If they won't
compile. how would you
rIX them, and if they do
c011lpile. what would he
their output'i'

A B

class XCopy { class Clock {


String time;
public static void main(Strinq [) arqs) {
void setTime(String t)
int orig = 42;
time = t j
Xcopy x = new xCopy();

int y : x.go(orig)j void getTime()


return time;
System.out.println(orig + U U + y); }

int go(int arg)


class ClockTestDrive {
arg = arg * 2; public static void main(String (] args) {

return arg; Clock c = new Clock();


}
}
c.setTime(U124S n ) j
String tad = c.getTime()i
System.out.println(Utime: u + tod)j

88 chapter 4
methods use instance variables

A bunch of Java components, in full costume, are playing a party


game,· Wha am W They gille you a clue, and you try to guess who
they are, based on what they say.Assume they always tell the truth
about themselves. If they happen to say something that could be true
for more tha n on e guy, then write down all fa r whom that sentence
applies. Fill In the blanks next to the sentence with the names of one
or more attendees.
Tonight's attendees:
Insta nee variable, argument, return, getter, setter,
encapsulation, public, private, pass by value, method

A class can have any number of these.

A method can have only one of these.

This can be Implicitly promoted.

I prefer my Instance variables private.

It really means 'make a copy'.

Only setters should update these.

A method can have many of these.

I return something by definition.

I shouldn't be used with instance variables.

I can have many arguments.

By definition, I take one argument.

These help create encapsulation.

I always fly solo.

you are here. 89


puzzle: Mi)(ed Messages

Mixed
Messages
A short Java program Is listed to your right. public class Mix4 (
Two blocks of the program are missing.
Your challenge Is to match the candIdate int counter = OJ
blocks of code (below) , with the output public static void main (String [) args) (
that you'd see if the blocks were Inserted. int count = 0;
Not all the lines of output will be used, and Mix4 [) m4a =new Mix4[20lj
some of the lines of output might be used
int x = 0;
more than once. Draw lines connecting
the candidate blocks of code with their
matching command-line output.
while (I I)
m4a [x] = new Mix4 ();
m4a(x] . counter = m4a(xl .counter + 1;
count count + 1;
count count + m4a[x) .maybeNew(x);
x = x + 1;

System. out.println(count + ~ "


+ m4a[1) .counter);
CandIdates: Possible output:

x ·< 9 public iot maybeNew(int index)


index < 5 ,!
if (I I') (
Mix4 m4 = new Mix4();
x < 20 m4.counter = m4.counter + 1;
return 1;
index < 5 .~

return 0;

x <7

index < '1

x < 19
index < 1 •.

90 chapter 4
methods use Instance variables

public class Puzzle4 {


public static void main(Strinq [] arqs) {

int y = I:
int x = 0:
int result = 0;
Your Job is to take code snippets from the
pool and place them Into the blank lines while (x < 6) {
in the code. You may not use the same
snippet more than once, and you won't
need to use all the snippets. Your goal
is to make a class that will compile and y y * 10;
run and produce the output listed.
}
x = 6;
while (x > 0) {

result = result + __
Output }
system.out.println("result " + result);
}
}

class {
int ivar;
_____ doStuff(int ) {
if (ivar > 100) {
return _
} else {
- return
}
---------------------
}
}
Note: Eachsnippet
"om the pool can be
used only oncel

you are here) 91


puzzle: Five Minute Mystery

Fast TImes in Stim-Clty

When Buchanan jammed his twitch-gun into Jai's side , Jai froze. Jai knew that Buchanan
was as stupid lis he was ugly and he didn't want to spook the big guy. Buchanan ordered Jai
into his boss's office, but Jai'd done nothing wrong, (lately), so he figured a little chat with
Buchanan's boss Leveler couldn't be too bad. He'd been moving lots of neural-stimmers in
the west side lately and he figured Leveler would be pleased. Black market stimmers weren't
the best money pump around, but they were pretty harmless. Most of the slim-junkies he'd
seen tapped out after a while and got back to life, maybe just a little less focused than before.

Leveler's ' office ' was a skungy looking skimmer, but once Buchanan shoved him in, Jai
could see that it'd been modified to provide aIL the extra speed and armor that a local boss like
Leveler could hope for. "Jai my boy", hissed Leveler, "pleasure to see you again". "Likewise
I'm sure...", said Jai, sensing the malice behind Leveler's greeting, "We should be square
Leveler, have r missed something?" "Ha! You're making it look pretty good Jai, your volume
is up, but I've been experiencing, shall we say, a little 'breach'lately..." said Leveler.

Jai winced involuntarily, he'd been a top drawer jack-hacker in his day. Anytime someone
.figured out how to break: a street-jack's security, unwanted attention turned toward Jai, "No
way it's me man", said Jai, "not worth the downside. I'm retired from hacking, [just move
my stuffand mind my own business", "Yeah, yeah", laughed Leveler, "I'm sure you're
clean on this one, but I'll be losing big margins until this new jack-hacker is shut
out!" "Well, best of luck Leveler, maybe you could just drop me here and I'll go
move a few more 'units' for you before I wrap up today", said Jai.

"I'm afraid it's not that easy Jai, Buchanan here tells me that word is you're
current on 137NE", insinuated Leveler. "Neural Edition? sure I play around a bit, so
what?". Jai responded feeling a little queasy. "Neural edition's bow I let the stim-junkies
know where the next drop will be", explained Leveler. "Trouble is, some srim-junkie's stayed
straight long enough to figure out how to hack into my WareHousing database." "I need a
quick thinker like yourself Jai, to take a look at my StimDrop 137NE class; methods, instance
variables, the whole enchilada, and figure out how they're getting in. It should..", "HEY!",
exclaimed Buchanan, "I don't want no scum backer like Jai DOSin' around my code!" "Easy
big guy", Jai saw his chance, "I'm sure you did a top rate job with your access modi .. "Don't
tell me - bit twiddler!", shouted Buchanan, "1 left all of those junkie level methods public,
so they could access the drop site data, but 1 marked all the critical WareHousing methods
private. Nobody on the outside can access those methods buddy, nobody!"

"I think I can spot your leak Leveler, what say we drop Buchanan here off at the comer
and take a cruise around the block", suggested Jai. Buchanan reached for his twitch-gun but
Leveler's stunner was already on Buchanan's neck, "Let it go Buchanan", sneered Leveler,
"Drop the twitcher and step outside, I think Jai and I have some plans to make",

What did Jai suspect?


Will be get out of Leveler's skimmer with all his bones intact?
92 chapter 4
methods use Instance variables

class Clock
String time;
void setTime(~tring t) {
time:: t;
B }
String getTime ( )
return time;
}

class ClockTestDrive {
public static void main(String rl args) {
Clock c = new Clock();
c.setTime(R124S R ) j
String tod = c.getTime();
System.out.println(Utime: • + tod);

} Note: 'Getter' methods have a return


XCopy' compiles and runs as it stands I The type by definition.
84'. Remember Java is pass by value, (which
copy), the variable 'orig' is nol changed by the

dass can have any number of these. Instance varl~bles, getter, utter,method
method can have only one of these. return
I' can be implicitly promoted. return. argument
prefer my instance variables private. encapsulation
really means 'make a copy'. pass by value
setters should update these. Instance variables
method can have many of these. o.rgt.llnent
return something by definition. getter
shouldn't be used with instance variables public
can have many arguments. method
definition, , take one argument. setter
se help create encapsulation. getter. s£'tter, public. private
always fly solo . return

you are here. 93


puzzle answers

Puzzle Solutions

Answer to the 5-minute mystery...

pUblic class Puzzle4 (


Jai knew that Buchanan wasn't the sharpest
public static void main(String [] args) { pencil in the box. When J ai heard Buchanan
Puzzle4b [ ] ebs =new Puzzle4b[6J; talk about his code, Buchanan never mentioned
int y - 1; his instance variables. Jai suspected that
int K .. 0, while Buchanan did in fact handle his methods
int result = 0:
correctly, he failed to mark his instance variables
while (x < 6) (
private. That slip up could have easily cost
obs[x) =new PU2zle4b( ):
Leveler thousands.
obs[x) . ivar =y;
y - y .. 10;
x=><+1;

x = 6,
while (x > 0) {
x =x-I;
result = result + obs[x].doStuff(x): Candidates: Possible output:

System.out.println("result u + result); x < 9


}

index < 5
class Punle4b {
1nt ivar,
public int doStuff (int factor) x < 20
if (ivar > 100) {
return ivar * factor; index < 5
else {
return ivor" (5 - factor);
Output
x < 7
q\ java Puzzle4
index < 7
result 543345

x < 19

index < 1

94 chapter 4
5 writing a program

Extra-Strength Methods

Let's put some muscle In our methods. We dabbled with variables, played
with a few objects, and wrote a little code. But we were weak.We need more tools. Like
operators. We need more operators so we can do something a little more interesting than, say,
bark. And loops. We need loops, but what's with the wimpy while loops? We need 10, loops

jfwe're really serious. Might be useful to generate random numbers. And turn a String
Into an Int, yeah, that would be cool. Better learn that too. And why don't we learn It all by
building something real, to see what it's like to write (and test) a program from scratch. Maybe
a game, like Battleships. That's a heavy-lifting task,so It'll take two chapters to finish .We'll build
a simple version in this chapter, and then build a more powerful deluxe version in chapter 6.

this is a new chapter 95


building a real game

Letls build a Jattleship.. style


gattte: "Sitdc a Pot COttt
N

It's you against the computer, but unlike the real


Battleship game, in this one you don't place any ships You're going to build the
of your own. Instead, your job is to sink the computer's Sink a Dot Com game, with
ships \0 the fewest number of guesses.
a 7 x 7 grid and three
Oh, and we aren't sinking ships. We're killing Dot Dot Coms. Each Dot Com
Corns. (Thus establishing business relevancy so you can
takes up three cells.
expense the cost of this book).
Goal: Sink all of the computer's Dot Corns in the fewest
number of guesses. You're given a rating or level, based
on how well you perform.
part of a galMe it1feraetlott
Setup: When the game program is launched, the
computer places three Dot Corns on a virtual 7 x 7 ..
grid. When that's complete, the game asks for your first %j ava OotComBust
guess. Ent e r a guess A3
How you play: We haven't learned to build a CUI yet, so mi s s
this version works at the command-line. The computer
will prompt you to enter a guess (a cell), that you 'U type Ent e r a guess 82
at the command-line as ~A.3", "C5", etc.). In response mi s s
to your guess, you'll see a result at the command-
Ent e r a guess C4
line, either "Hit", "Miss", or "You sunk Pets.corn" (or
whatever the lucky Dot Com of the day is). When mi s s
you've sent all three Dot Cams to that big 404 in the Ent e r a guess 02
sky,the game ends by printing out your rating.
h it
tat.\-. 'oo~~
"7 )< "7 ~r-id ',s a "t.t\\ Ent e r a guess 03
hit
A k
Enter a guess 04
B Ouch! You sunk Pets. com
E
C 5• kill
~
e Enter a guess B4
D P4 ts.cc m
miss
E Enter a guess G3
F hit
Enter a guess G4
G
I Asi Me.c pm hit
o 1 2 3 4 5 6 Enter a guess GS
Ouch! 'lou sunk AskMe.com
'- shr-h at. ut"o, like Java d'n'ays
96 chapte r 5
writing a program

First a high.. level desigtt


'e know we'll need classes and methods. but what
uld they be? To answer that, we need more
form ation about what the game should do.
First, we need to figure out the general flow of the
zame. Here's the basic idea:

o
User starts the game

o
Game set-up

Game creates three Dot Coms

o Game places the three Dot


ColTlS onto a virtual grid

Game play begins


hit
Repeat the following until there are
no more Dot Coms:

A Prompt user for a guess 1'\


W ("'2', 'CO', etc.) . ) remove

(0 Check 'he user guess oga;nst


all Dot Coms to look for a hit,
Dot Com

miss, or kill. Take appropri-


ate action : if a hit, delete cell Adial'l\Of\d
(A2, D4, etc.). If a kill, delete yt:f""~l\b a
Dot Com. dt:t.isiOl\ ~O'l\t

Game finishes
Give the user a rating based on display user
the number of guesses. score/rating

~ ow we have an idea of the kinds of things the


rogram needs to do. The next step is figuring
ut what kind of objects we'll need to do the
loo·ork. Remember, think like Brad rather than
Larry; focus first on the things in the program
ra the r than the jrroredures.
Whoa. A real flow chait.

you are here. 97


a simpler version of the game

N
fhe "SitMple Pot CO"' .allte
a get1tler it1troductiot1
It looks like we're gonna need at least two classes, a
Game class and a DotCom class. But before we build
o 6arM starts, and creates ONE DotCom
and gives it a location on three. cells in
the single row of seven cells.
Instead of • A2", ·C4", and 50 on, the
the fuJI monty Sinh a Dot Com game, we'll start with
locations are just integers (for example :
a stripped-down. simplified version, Simple Dot Com 1,2,3 are the cell locations in this
Game. We'll build the simple version in this chapter, picture:
followed by the deluxe version that we build in the
next chapter.
Everything is simpler in this game , Instead ofa 2-D
grid, we hide the Dot Com injust a single TOW. And o 1 2 3 4 5 6
instead of three Dot Corns, we use one.
6a1U play begins. Prompt user for
The goal is the same, though, so the game still needs a guess, then check to see jf it hit
to make a DotCom instance, assign it a location any of the DotCom's three cells .
somewhere in the row, get user input, and when all If a hit , increment the numOfHits
of the DotCom's cells have been hit, the game is over, variable.
This simplified version of the
game gives us a big head start SlmpleDotCom Game 6ame 'finishes when all three cells have
on building the full game. been hit (the numOfHits variable vel-
~ ue is 3), and tells the user how many
If we can get this small one
SlmpleDofCom guesses it took to sink the DotCom.
working, we can scale it up to
the more complex one later. Inl 0localionCells
voId mail\ Intnum01Hl1s
In this simple version, the
game class has no instance
variables, and all the game String checkYou~If(Stril\g guess)
code is in the main () method,
void SetlocallonCellsQntO loe)
In other words, when the
program is launched and
main () begins to run, it will
make the one and only DotCom
instance, pick a location for it ( three
consecutive cells on the single virtual
seven-cell row), ask the user for a guess, check the
guess, and repeat until all three cells have been hit.
Keep in mind that the virtual row is... virtual: In other
words, it doesn't exist anywhere in the program . As
long as both the game and the user know that the
DotCom is hidden in three consecutive cells out ofa
possib\e seven (starting at zero) , the tOW i.tself doesn't
have to be represented in code. You might be tempted
to build an array of seven ints and then assign the
DotCom to three of the seven elements in the array,
but you don't need to. All we need is an array that
holds just the three cells the DotCom occupies.
98 chapter 5
writing a program

Pevelopit1Q aClass fhe three thlt19S we~1I wrIte for


_ a programmer, you probably have a methodology/
each class:
ess/approach to writing code. Well. so do we. Our
sequence is designed to help you see (and learn) what
're thinking as we work through coding a class. It
' t necessarily the way we (or you) write code in the
World. In the Real World, of course, you'll follow This bar Is displayed on the next set of pages to tell
approach your personal preferences, project, or you which part you're working on. For example, if you
ployer dictate. We, however, can do pretty much see this picture at the top of a page. it means you're
working on prepcode for the SimpleDotCom class.
tever we want And when we create aJava class as a
rning experience", we usually do it like this:
SlmpleDolCom class
~
D Figure out what the class is supposed to do.

D List the Instance variables and methods.


prep code
D Write prepcode for the methods. (You'll see A form of pseudocode. to help you focus on
this in Just a moment.) the logic without stressing about syntax.
D Write test code for the methods.
test code
D Implement the class. A class or methods that will test the real code
and validate that it's doing the right thing.
o Test the methods.
o Debug and relmplement as needed. rea I code
The actual implementation of the class . This is
o Express gratitude that we don't have to test _ _- - - -..... al Java code.
our so-called learning experience app on To DO.:
actuallJve users.
s'mp'eDotCOm claSS
o write prep code

o write test code


o write final Java code

s,mp'eDotCOmoame
Flex those dendrftes. cia••
How would you decide whIch class or classes
o write prep code

to build first, when you're writIng a program? write test code {nol
Assuming that all but the tiniest programs
need more than one class (If you're following
o write final Java code

good 00 principles and not having one class


do many different Jobs), where do you start?

you are here. 99


SimpleDotCom class

You'11 get the idea of how prepcode (our version of pseudocode) works as you
read through this example. It's sort of half-way between real Java code and a plain
SlmpleOolCom
English description of the class. Most prepcode includes three parts: instance
illl 0IocaIiooCelIs
inlnumOft-lils
variable declarations, method declarations, method logic. The most important
part of prepcode is the method logic, because it defines what has to happen,
String checkYourself(string guess)
which we later translate into hotu; when we actually write the method code.
void selLoca~onCells{inlj) lot)
DECLARE an int array to hold the location cells. Call it loeatJonCells.
DECLARE an int to hold the number of hits.Call it numOfHits and SET it to O.

DECLARE a checkYourset(() method that takes a String for the user's guess (" I", "3", etc),
checks it. and retums a result representing a "hit", "miss",or "kill",
DECLARE a setLocationCeJ/sO setter method that takes an int array (which has the three cell
locations as ints (1.3/1, etc.).

METHOD: String checkYourself(String userGuess)


GET the user guess as a String parameter
CONVERT the user guess to an int
REPEAT with each of the location cells in the int array
II COMPARf the user guess to the location cell
IF the user guess matches
INCREMENT the number of hits
II FIND OUT if it was the last location cell:
I F number of hits is 3, RETt,JRN "kill" as the result
ELSE it was not a kill. so RETURN"hit"
[
END IF
ELSE the user guess did not match, so RETURN "miss"
END IF
END REPEAT
END METHOD

METHOD: void setLocotJonCe//$(lnt[] eel/Locations)


GET the cell locations as an in! array parameter
ASSIGN the cell locations parameter to the cell locations instance variable
END METHOD

100 chapter 5
writing a program

Writing the tttethod


hMpletM8ntations
let's write the real
...ethod code ttOW, ittd get
this puppy worklttg.
Before we start coding the
methods, though, let's back
up and write some code to
test the methods. That's right,
we're writing the test code
1M/ore there's anything to testl
The concept of writing
the test code first is one of
the practices of Extreme
Programming (XP), and
it can make it easier (and
faster) for you to write your
code. We're not necessarily
saying you should use XP,
but we do like the part about
....Tiling tests first. And XP just
sounds cool.

Extreme Programming (XP)


Extreme Programming(XP) Is a newcomer to the software Don't put in anything that's not in the spec (no matter
evelopment methodology world.Consld ered by many how tempted you are to put In functionality "for the
t be "the way programmers really want to work ~ XP future) .
e erged In the late 90's and has been adopted by
Write the test cod e first .
•ompanies ranging from the two-person garage shop
the Ford Motor Company. The thrust of XP is that the No killer schedules;work regular hours.
sterner gets what he wants, when he wants It, even Refactor (improve the code) whenever and wherever you
en the spec changes late In the game. notice the opportunity.
is based on a set of proven practices that are all Don't release anything until it passes all the tests.
esigned to work together, although many folks do pick
and choose, and adopt only a portion of XP's rules. These Set realistic schedules, based around small releases.
ctices include things like: Keep it simple.
ke small, but frequent, releases. Program in pairs, and move people around so that
velop in Iteration cycles. everybody knows pretty much everything about the code .

you are here ~ 101


SlmpleDotCom class
prepcode

Writh1Q test code for the Shttp[eUoi'ColM class


We need to write test code that can make a SimpleDotCom object
and run its methods. For the SimpleDotCom class. we really
care about only the cMckYourselj() method, although we will have
to implement the sdLocatiun~l1s()method in order to get the
cMckYourself() method to run correctly.
Take a good look at the prepcode below for the checkYourselj()
method (the setLocaticmCells() method is a no-brainer setter method,
so we're not worried about it. but in a 'real' application we might
wan I a more robust 'setter' method. which we wouldwant to test).
Then ask yourself, "If the checkYourselfO method were
implemented. what test code could I write that would prove to me
the method is working correctly?"

'ased Ott this prepcode: Here1s what we should test:


METHOD String checkYourselffString userCuess) 1. Instantiate a SlmpleDotCom object.
GET the user guess as a String parameter 2, Assign It a location (an array of 3 ints, like
CONVERT the user guess to an Int {2,3.4}).
3. Create a SlJing to represent a user guess
REPEAT with each of the location cells in the Int array
('2", '0', etc.).
/I COMPARf the user guess to the location cell
4. Invoke the checkYourselfO method pass-
IF the user guess matches ing il the fake user guess.
INCREMENT the number of hits 5. Print out the result to see If It's correct
/ / FIND OUT if it was the last location cell: ("passed" or "failed").

IF number of hits is 3. RETURN "Kill" as the result


ELSE it was not a kill, so RETURN"Hif'
END IF
ELSE the user guess did not match, so RETURN "Miss"
END IF
END REPEAT
END METHOD

102 chapter 5

writing a program

~relare,..{l? "
fest code for the SIIMpiePotCoIM class
DiiJjjo ~uestl9ns
Q..:Maybe I'm missing some- public class SimpleDotComTestDrive ( ....sta"ba-tl. a
here, but how exactly do \~....y\e'Da\:.e,o...
run a test on something public static void main (S trinq [ ] arqs) ( do~et,t.
. . doesn't yet existI1
SimpleDotcom dot = new SimpleDotCom (); t::"
: You don't. We never said
start by running the test;
.".a't.-e 0" "'~t. il:l0'1 ~oY
-\:.be Got.
&e \ot.WOl' vb~e ,,,b
J ~'1o\t
O'>t. C,
start by writing the test. At
------ t.o"'" 1)·
. e you write the test code, int [] locations = {2 I 3 I 4}; V a Y°sJ.\
won't have anything to run
,against. so you probably won't dot.setLocationCells(locations); .
Ie to compile It until you
~ ''' ...oIc e tJ.. •.....L
e 'st ub' code that can com- .--.. ,.,tih e ~tn-
bu t that will always cause od 0,. the dot. to ....
est to fail (like, return null.)
"",Itt 0 ~ ake
String userGuess = "2 H ; ~
~tv"~~
:Then I stili don't see the
••..,rt. Why not walt until the String result = dot.checkYourself(userGuess);
Is written, and then whip
the test code? Strinq testResult = "failed" j
~i""'oke 1:~e thetJcYoursel.fO
_...1.,
m.ev\od on ille dot to...
objttt, a"d Pdss if. ill
if (result. equals ("hi t") ) ( .f<ilr:e ~LAe.11. e
: The act of th Inkl n9 th roug h
writing) the test code helps
. ...bri"tv your thoughts about what

method Itself needs to do.


)
soon as your implementation
e is done, you already have
code Just waiting to validate System.out.println(teStResult);~
Besides,you know If you don't f"'in1: 0Ii01: the wf. reslOl
't now, YOU'll never do It. } (p-aued at" .f<iiledJl) t
e's always something more
esting to do.
}

~r.~~,!::~~"
ally, write a little test code,
write only the Implementa-
code you need in order to
that test. Then write a little
of p••es w' Implemem the S1mpleDoteom class,
and then later we return to the test class. Looking at our test code
e test code and write only above, what else shou Id be added 7 What are we not testi ng in this
new implementation code code, that we should be testing for? Write your ideas (or lines of
ed to pass that new test. At code) below:
test lteratlo n, you TUn all
preViously-written tests, so
you always prove that your
t code additions don't break
iously-tested code.

you are here ~ 103


SimpleDotCom class

The checkYourselfO tttethod


There isn't a perfect mapping from prepcode to javacode; you'll see a few
adjustments. The prepcode gave us a much better idea of what the code needs to
do, and now we have to find the Java code that can do the how.
In the back of your mind, be thinking about parts of this code you might want
(or need) to improve. The numbers (18 are for things (syntax and language
features) you haven't seen yet. They're explained on the opposite page.

GET the user


public String checkYourself(String stringGuess) {
guess
I) to"veri th &t '
CONVERT
int guess = Integer.parselnt(stringGuess); L-
,--- w
L
al'l I•I'I~1- e r'''9
the user guess t o
an int String result = "miss"; ( a:
- .... e a variable
re~lAr" Plat II . "
to hold the reslAlt we'll
. . ""ss i" as the detalAlt
('.e. we clsslA....e a ......iss")
REPEAT with
each ceil in the int
array
IF the user guess

for (int cell : locationCells) {

mat ches

INCREMENT
the nUI1"lb er of
hits

~ 9d; QlAt o.f th I


to te t e <><>p, no "eed
! I e nd i f s the other tells

} II end f or
/ / FIND OUT if
it. was t he last ee l!
if (numOfHits == locationcells.length) (
IF number of hits
is 3.
result = "kill";
RETURN "kili"
as the result
/ ! end i f
ELSE it was
not a kill. so
RETURN "hit " System.out .println(result); ~ display the reslAlt.for the lASer
ELSE return result; ("Miss", lAl'lless it was tha"ged to "I-hi;" or "Kill")
RETURN
t"-. retlAr" the reslAlt bade to
} II end me thod the talli"9 ....ethod

104 chapter 5
writing a program

e things we haven't seen before


on this page. Stop worryingl The
of the details are at the end of
chapter. This isjust enough to let
keep going.

Converting a
String to an Int

n ~ ++ ... taY\1 add I to


The post-increment
operator
( 'WhaWtr'S th&e (il'l ~
'Wc*d.s, int __ e",ent by ,).
numOfHits++
roIArllOtl·hh++ i.s the sa...t (il'l
this ~) as sayi,,~ "...... O.f»its ::.
""",o.f~hh +" e~rt sli9hUt
...~~ tHitient

break statement
break;
~et.s y~ out o-f alOOf· l......ediduly. Ri~ht htl'"t.
No ihl'"atiol'l, no boolul'I ust, iwt o.d out "ow!

you are here ~ 105


SlmpleDotCom class
prep code

:therelare~~ "
DUmb ~uesti9115
public class S~leDotComTestDrive {
Q..: What happens In
Integer.pa rselnt(l If the thing you publiC s t a t i c void main (S~ringl] args) {
pau Isn't a number? And does It SimpleDotCom dot ~ new SimpleDotCom{};
recognize spelled-out numbers,
intI] locations ~ (2,3,4);
/Ike Jl t hree"?
dot , setLocationCells (locations) ;

A: Intege r.parselntO wo rks only


on Strings that represent the ascii
String userGuess
String result ~
~ "2-;
dot .checkYourself(userGuess);
values for digits (0,1,2,3,4,5,6,7,8,9).
If you try to parse something like
"two" or "blurp'; the code wi II blow
up at runtime. (By blow up, we
actually mean throw an exception,
but we don't talk about exceptions
until the Exceptions chapter. So for public class SimpleDotCom
now, blow up is close enough .)
intI) locationCells ;
int numOfHits ~ 0 ;

Q..:ln the beginning ofthe pUblic void setLocationCells(intl] locs) (


book, there was an exam pie of a locationCells = locs;
for loop that was really different
from this one-are there two
different styles of for loops? pUblic String checkYourself(String stringGuess)
int guess ~ Integer.parselnt{stringGuess);
String result - "miss ";
A:YeSl From the first version of for (int cell : IocationCells)
Java there has been a sIngle kind i f (guess ~ ~ cell) (
of (or loop (explained later In this result = " h i t - ;
chapter) that looks like this : numOfHits++;
break;
for (Int i = 0:/ < 10;1++) { ) What should we see
// do someth ing 10 times I I out o f t h e l o op when we run this code?
The test code makes a
if (numOfHits == SimpleDotCom object
You can use this format for any locationCells.length) and gives it a locat ion at
kind of loop you need. But... result ~ "kill-; 2,3,4 . Then it sends a fake
beginnIng with Java 5.0 (Tiger), ) user guess of "2" Into the
you can also use the enhancedfor System.out.println{result}; checkYouselfO method.
loop (that's the official description) return result; If the code is working
when your loop needs to iterate ) II clo se meth o ' correctly, we should see the
over the elements In an array (or I I c l o 'e c Ia s result print out:
another kind of collection, as you'll
see In the next chapter). You can
Java SlmpleDotComTestD r l ve
always use the plain old for loop
There's a little bug lurking here. It complies end lat
to iterate over an array, but the runs. but sometimes ... don't WOffY aboulll for now,
enhanced for loop makes it easier. but we will have to face it II little later,

106 chapter 5
writing a program

We built the test class, and the SimpleDotCom class.But we still haven't
made the actua I game. Given the code on the oppos Ite page, and the spec for
the actual game, write In your Ideas for prepcode for the game class. We've given
The SlmpleDotComGame
you a few lines here and there to get you started. The actual game code is on the
needs to do this:
next page, so don't tum the page until you do this exerdsel
1. Make the single
You should have somewhere between 12 and 18 lines (including the ones we wrote,
SimpleDotCom Object.
but not including lines that have only a curly brace).
2. Make a location for it (three
METHOD publicstatic void main (String 0 OI'J:S) consecutive cells on a single
DECLARE an int variable to hold the number of user guesses. named numOfGuesses row of seven virtual cells).
3. Ask the user for a guess.
4. Check the guess.
5. Repeat until the dot com is
dead .
6. Tell the user how many
guesses it took..

COMPUTE a random numberbetween0 and "I that will be the starting location cell position

WHILE the dot com IS ~i ll ahve :


GET user input (rom the command line

yo u are here. 107


SlmpleOotCom class

Prepcode for the ShMpleUo'fCottttatMe class


Everythfng happetts Itt Ittal..n
There are some things you'll have to take on faith. For example. we have one
line of prepcode that says, wCET user input from command-line". Let me tell
you, that's a little more than we want to implement from scratch right now, But
happily, we're using 00. And that means you get to ask some otherc1ass/object
to do something for you, without worrying about how it does it. When you write
prepcode, you should assume that somehoto you'll be able to do whatever you
need to do, so you can put all your brainpower into working out the logic.

public stadc voJd main (String D args)


DECLARE an int variable to hold the number of user guesses. named numO(t;uesses. set it to O.
MAKE a new SimpleDotCom instance
COMPUTE a random number between 0 and '\ that will be the starting location cell position
MAKE an int array with 3 ints using the randomly-generated number, that number incremented by I.
and that number incre mented by 2 (example: 3.4,5)

INVOKE the retLocOlionCeI!sO method on the SimpleDotCom instance


DECLARE a boolean variable representing the state of the game. named isAhve. SET it to true

WHILE the dot com is still alive (isAlive == true) :


GET user input {rom the command line
// CHECK the user guess
INVOKE the checkYourse/fO method on the SlmpleDotCom instance
INCREMENT numO(t;uesses variable
II CHECK (or dot com death
IF result is "kill"
SET isAlwe to false (which means we WOT'l'! enter the loop again)
PRINT the T'lumberof user guesses
END IF
END WHILE
END METHOD
nl~ogn.itive ttl
Don't work one part of the brain for 100 long a stretch at one time.
Working Just the left side of the brain formore than 30minules
is like working lust your left arm for 30 minutes, Give each side
of your brain a break by swilchlng sides at regular intervals. .
When you shift to one side. the other side gels 10 rest and
recover. Left-brain actJvlties Include things like step-by-step
sequences, logical prob\em-solving, and analysis. while the
right-brain kicks in formetaphors, creative problem-solving,
pattern-matching, and Visualizing.

108 chapter 5
writing a program
-
• Your Java program should start with a high· • Choose forloops over while loops when you
level design. know how many times you want torepeat the
loop code.
• Typically you'll write three things when you
create a new class: • Use the pre/post increment operator toadd 1
prepcode
to a variable (x++;)
testcode • Use the pre/post decrement tosubtract 1 from
a variable (x-;)
real (Java) code
• Use Integer .parseInt() to get the int
• Prepcode should describe what to do, not how value ofa String.
todoit. Implementation comes later.
• In teger . parseIn t () works only if the
• Use the prepcode tohelp design the test String represents a digit ("0":1',"2", etc.)
code.
• Use break 10 leave a loop early (i.e. even if
• Write test code before you implement the the boolean test condition is still true).
methods.

How many
hits did you get
last month?

you are here) 109


SimpleDotComGame class

Just as you did with the SimpleDotCom class, be thinking about parts of this code
you might want (or need) to improve. The numbered things • are for stuffwe
want to point out. They're explained on the opposite pag e. Oh, if you 're wonder-
ing why we skipp ed the test code phase for this class, we don 't need a test class for
the game. It has only one method, so what would you do in your test code? Make
a separate class that would call maini] on t~is class? We didn't bother.

public static void main(String[] arqs) (

DECLARE 3 var i-
able to hold user
guess count . set it GameBelper helper '" new GameBelper (); e-r: this is a 1ft/.'Ial t1ass \role wv~ thdt has
to 0
t.he ...dhod +OY ~d±i,,~ ~ il'lf l< t.. +OY
l""Wl'IG it's part. ~ Java
l\O'<II,

MAKE a Simplefzot -
SimpleDotCom t:.heDotCom '" new SimpleDotcomO ; ~ .....lce the dot tOO>l objet+'
Com objec t

COMPUTE ,\
rando m num be r
be tween 0 and .\
int randomNum = (int) •
(Mat:.h.random() ... 5) ;b--lft<1lce a ril,wf"", l'I"",beY.toy the
tell, and lUe it to ~ke the leU
~ lotdtiOt\.! array
.first

MAKE an int ar ray


WIth the 3 cell loca- let(] locations • (randamNum, randOlllNum+l, rand0lllNUm+2);
lions, and
thaDotCom. IIstLocationCells (locations) ; .
~ ~,ve
L1..
v>e
dot tQtI\ ih lotdtiOtlS (th, C1Yril'1)
INVOKE seu.oca -
[lonCells on the do t
corn ob ject boolean isAli va '" true;

DECLARE a boo l-
eat" sAlive

WHILE the dot


co m 1\ still alive

GET user' input


II CHE.CK It
INVOKE checkro-
ursell() on dot co m
IN C R EM E N T
nurnO fGuesses
IF re ult is " kill"
SET gameA live to
false

PRINT the number


of user gue sses II c l o s e if

II c lose while

- II close main

chap ter 5
writing a program

jf...ro things that need a bit more


,:xplain ing. are on this page, This is
. t a quick look to keep you going;
re details on the GameHelper
are at the end of this chapter.

Make a random
number

(Math.random() '" 5)
t
Atlau that tOfllts
t
A... rthoci ok the
wit.h Java. Mat.h daS$.

An 'l"rl,arU wt "'<id.t tdrlieY,


ok a t1ass that we bl/.ilt to
Getting user input hell' wit}, tnt ~...e. It' s ~lItd
using the GameHelper qaft't~tlfeY a"d 'feN haVbl t
class set" it yd ('fov wilD.
~
String guess = helper.getUserInput("enter a number");

i l'
A...ethod o..f the ~a...t!'+e'ft"r tlau
~t asks the w.ser ~ot' toow.",a"d-
li"e i"f\lt, \'"ealb it in .»u.-
-the
1ISe'r hits R~Tl).RN, ahli ~'Ives batk
the ytsl/.I-c clS a Sh-i,,~.

you are here) 111


GameHelper class (Ready-bake)

One last class: G-attteHelper


We made the dot CQtn class. Just copy* the code below and compile it into
a class named GameHelper. Drop all three
We made the game class.
classes (SimpleDotCom, SimpleDotComGame,
All that's left is the helper class- the one with the GameHelper) into the same directory. and make it
getUserInputO method . The code to get command- your working directory.
line input is more than we want to explain right now.
It opens up way too many topics best left for later. "Ready-IMke
(Later, as in chapter 14.) Whenever you see the Bell de logo, you're see-
ing code that you have to type as-is and take on faith .
Trust it, You'Illeam how that code works later.

import java.io.* ;
public class GameBelper
public String getOserlnput(String prompt)
String inputLine = null;
System.out.print(prompt +" ");
try {
Bu£feredReader is = new BufferedReader (
new InputStre~ader(SY8tem.in);

inputLine = is.readLine();
if (inputLine. length () == 0) return null;
} catch (IOException e) (
System.out.println("IOException: " + e);

return inputLine;

"We know how much you enjoy typing . bul for thoee rare
moments When you'd mlher do some\hlng else , we'vil mad II
11111 Ready-bake Code avallable on wlckedlyamart.com.

112 chapter 5
writing a program

lefs play What's this? Abug?


Gaspl
Here's what happens when we Here's what happens when we
run it and enter the numbers enter 1.1,1.
1,2,3,4,5,6. Leckin' good.

Acoltlplete gatMll lltteractlolt Adlfferettf gaIMe h,teractlotl


(your mileage may vary) (ylkes)

%j a v a SimpleDotComGame %j ava SimpleDotComGame


enter a number 1 enter a number 1
miss hit
enter a number 2 enter a number 1
miss hit
enter a number 3 enter a number 1
miss kill
enter a number 4 'lou took 3 guesses
hit
enter a number 5
hit
enter a number 6
kill
You took 6 guesses
It's a cliff-hangerl
Will we find the bug?
Will we flxthe bug?

Staytuned r the next chapter,where we answer


these quest! ns and more...
And In the meantime,see If you can come up with
Ideasfor what went wrong and howto fix It.

you are here. 113


for loops

More about for loops


We've covered all the game code for this chapter (but we'll pick it up again
to finish the deluxe version of the game in the next chapter). We didn't
want to interrupt your work with some of the details and background info,
so we put it back here. We'U start with the details of for loops, and if you're
a Ct+ programmer, you can just skim these last few pages ...

legular bto"-e.,ha"ced] for loops

repeat for 100 reps:

What It means In plain English: ~Repeat 100 times ."


How the complier sees It:
• create a variable I and set It to O.

-;. repeat while II siess tha n 100.

• at the end of each loop IteratIon, add 1 to I

Part One: Initialization


Use this part to declare and Initialize a variable to use within the loop body.
You'll most often use this variable as a counter.You can actually initialize more
than one variable here, but we'll get to that later In the book.
Part Two: boolean test
This Is where the conditional test goes. Whatever 's In there, It must resolve to a
boolean value (you know, tru« or flllu) . You can have a test" like (x >= 4), or you
can even Invoke a method that returns a boolean.
Part Three: IteratIon expression
In this part, put one or more things you want to happen with each trip through
the loop. Keep In mind that this stoff happens at the end of each loop.

114 chapter 5
writing a program

output:
sthrough a loop ~
int i = 0; i < 8; i++)
tem.out.println(i);

enter loop
body
++
Pre and Post Increment/Decrement Operator
print the value
of; The shortcut for adding or subtracting 1 from a variable.
X++;
Increment Is the same as:
(the iteration
expression) X = X + 1;
They both mean the same thing in this context:
"add 1 to the current value of x" or ·'ncrement x by 1·
And:

p has only the boolean test; It doesn't have X--;


I_!I!!I~-in in it ializat ion or Iteration expression. A while Is the same as:
good when you don't know how many times to
just want to keep going while some condl-
X = X I-I
ue. But If you know how many tl mes to loop Of course that's never the whole story.The placement of the
• e length of an array, 7 times, etc.), a for loop Is operator (either before or after the variable) can affect the re-
t , Here's the loop above rewritten using while: sult. Putting the operator before the variable (for example, ++x),
means:'!irst, increment x by 1, and then use this new value of x."
This only matters when the ++x Is part of some larger expres-
. .
11:lt 1. = 0; ~
"lII,<---~, jllitia/i~ ih
'lJe helv.. 1 d I
et. ire dl'ld
sion rather than just in a single statement.
int x = 0; int z = ++x;
while (i < 8) e lOlAl'\k
produces: )( Is I, z Is 1
System.out.println(i);
But putting the ++ after the x give you a different resuIt:
i++; ~ , J..;t have to illl
Ule lOlA;,k I'"e"'e,.,f int x '" 0; int z c x++;
produces: )( Is I, but z Is 01 z gets the value of x and then x is
Incremented.

you are he re ' 115


..
enhanced for

The etthattced for loop


Beginning with Java 5.0 (Tiger), the Java language has a second kind of Jor loop
called the enhanced jM, that makes it easier to iterate over all the elements in an
array or other kinds of collections (you'll learn about othercollections in the next
chapter). That's really all that the enhanced for gives you-a simpler way to walk
through all the elements in the collection, but since it's the most common use of a
for loop, it was worth adding it to the language. We'll revisit the enhancedfor lMp in
the next chapter, when we talk about collections that aren't arrays.

What It means In plain English: "For each element in nameArray, assign the
element to the 'narne'varlable, and run the body of the loop."

How the complier sees It:


... Create a String varIable called name and set It to null.

... Assign the first value In nameArray to name.

... Run the body of the loop (the code block bounded by curly braces).

... Assign the next value In nameArray to name.

... Repeat while there are stili elements In the array.

Part One: Iteration variable declaration


Use this part to declare and Initialize a variable to use within the loop body, With each
Iteration of the loop. this variable will hold a different element from the collection. The
type of this variable must be compatible with the elements in the arrayl For example,
you can't declare an lnt Iteration variable to use with a StrlngU array.

Part Two: the actual collection


This must be a reference to an array or other collection. Again, don't worry about the
other non-array kinds of collections yet-you'll see them in the next chapter.

116 chapter 5
writJng a program

converting a String to an int Casthtg


iDe quess = Int8qer .parseInt(strinqGuess); prhttftives
The user types his guess at the command-
line, when the game prompts hi m.That
guess comes In as a String (M2;"0~ etc.) ,
and the game passes that String into the
checkYourselfO method.
But the cell locations are simply lnts In an
array,and you can't compare an Int to a
String.
For example, this won't work:
long ~ short
can be cast to
. tx" 2;
. (x = num) II horrible explosionl
rying to compile that makes the complier
but you might
lau gh and mock you: lose something
o per a t o r ==
cannot be applied to
int,java .lang .String In chapter 3 we talked about the sizes of the various primitives. and how you
if (x == nurn) { } can'tshove a bIg thIng dlrecUy Intoa small thing:
,., 10n9 Y = 42;
int x = y; II won't compile
So to get around the whole apples and A long Is bigger than an int andthe complier can't besure where that long has
oranges thing, we have to make the String been. It might have been outdrinking with the other longs, andtaking on really
'2"into the int 2. Built Into the Java class big values. To force the complier toJam the value of a bigger primitive variable
brary is a class called Integer (that's right intoa smaller one, you can usethe casl operator. II looks likethis:
a Integer class, not the int primitive), long y == 42; II so far so good
and one of its Jobs is to take Strings that
represen: numbers and convert them Into int x = (int) y; II x = 42 oool!
actual numbers. Puttlng In the ~ tells the complier to take the value of y,chop It down to iot
size, and sat )( equal towhatever Is left. If thevalue of y was bigger then the
maximum value of x, then what's left will be a weird (butcalculable') number:
long y == 40002;
takes d ~b-i,,~ II 40002 exceeds the 16-bit limdt of a short

t short x c (short) y; II x now equ~s -25534!

teger.parseInt ("3") Stili,Ihe point is that the complier letsyou do It. And let's sayyou have a noal-
Ing point number, andyou just want to get at the whole number (in/) partof it

d ...etJ,od
I in the I"u~et"
float f .. 3.14£;
int x == (int) f; II x will equal 3
das.s that knows how io And don't even think about casting anything \0 a boolean or vice versa-just
"pa~J) a Sb-in~ i"io the walk away.
il'.t: it l"epl"C!seni.s.
'It involves sign blls, bInary, 'two's complement' and other geekery, all of which
arediscussed ai/he beginning of appendix B.
you are here _ 117
exercise: Be the JVM

BEtheJVM
The Java file on this page
represents a complete source
rue. Your job is to play JVM
and detel"llline what would be
the outpltt when the
program runs?

class Output {

pUblic static void main(String [J args) {


Output 0 = new Output();
o.go() ; -or-
}

void go() {
int y = 7;
for(int x = I: x < 8: x++) {
y++;
if (x > 4) {
System.out.print(++y + • -): -or-

i f (y > 14) {

Systern.out.println( U x = u + x);

break;
}

118 chapter 5
writing a program

Code Magnets
A working Java program Is all scrambled up on the fridge . Can you
reconstruct the code snippets to make a working Java program that
produces the output listed below? Some of the curly braces fell on the
floor and they were too small to pick up, so feel free to add as many of
those as you need!

1) {

System.out.println(x + ~ M + y):

4; Y > 2; y--) {
for(int Y

for(int :l( 0; x < 4; x++) (

you are here ~ 119


puzzle: JavaCross

JavaOr~ss
How doesa crossword puzzle
help you leam Java? Well,all
of the words are Java related.
In addition,the cluesprovide
metaphors, puns. and the like.
These mental twists and turns
bum alternateroutes to Java
knowledge,right into your
bralnl

Across Down
1. Fancy computer word 20. Automatic toolkit 2. Incrementtype 21. As if
for build 3. Classs workhorse 23. Addafter
22. Looks likea primltfve.
4. Multi-part loop buL 5. Pre Is a type of _ _ 24. PI house
6. Test first 25. Un-castable 6. For's Iteration _ _ 26. Compile it and__
7.32 bits 26. Math method
7. Establish first value 27. ++ quantity
10. Method'sanswer 28. Convertermethod
8. Whileor For
, 1. Prepcode-esque 29. Leave early
9. Updatean Instance variable
13. Change 12 Towards blastoff
15.The bigtoolkit 14. A cycle
17. An arrayunit 16.Talkative package
, 8. Instance or 10C41 19. Method messenger
(abb rev)
writing a program

A short Java program is listed below . One block of the program


is missing. Your challenge Is to match the candidate block of
code (on the left), with the output that you'd see If the block
were inserted. Not all the lines of output will be used,and some
of the lines of output might be used more than once. Draw lines
connecting the candidate blocks of code with their matching
command-line output.

class MixForS (
public static void main (String [) args)
int x = 0;
int y = 30;
for (int outer = 0; outer < 3i outer++) (
for(int inner = 4; inner> li inner--) {

y = y - 2;
if (x == 6)
break;

x = x + 3;
}
y = y - 2;
}
System.out.println(x + " " + y};

Candidates: Possible output:

X + 3~ 45 6 ~-\:t.'"' tat"
t.a~i6at.t 'fI~
x + 6~ 6 Qt\t~t.ht
yo"\b\t ~~h
x + 2~ 6

10

+ O~

you are here ~ 121



exercise solutions

Be the JVM: Code Magnets:


class Output { class HultiFor {

public static void main(String [ ) args) { public static void main(String [] args) {
Output 0 = new Output();
for(int x 0; x < 4; X++) {
o.go() ;
}
for(int y = 4; Y > 2; y--) {
void go{ ) { system.out.println(x + U U .;. y);
int y = 7; }

for(int x =: i I. x < B'I x++) {


y++;
i f (x =:= 1) { What would happen
x++ ; If this code block came
i f (x > 4) {
before the 'y' for loop?
System.out.print(++y + • h); }
} }

i f (y > 14) {

system.out.println(U x = h + x);

break;

} Did you remember to factor In the


break statement? How did that
affect the output?

122 chapter 5
writing a program

Candidates: Possible output

x • x + 3;

x • x + 6;

x • x + 2;
x++;

x--;

x - x + 0,

you are here • 123


6 get to know the Java API

Using the Java Library

Java ships with hundreds of pre-built classes. You don't have to

reinvent t he wheel If you know how to f1 nd what you need In the Java IIbra ry, known as

t he Java API. You've got better things to do . If yo u're go ing to write code, you mig ht aswell
write only the parts that are truly custom for your application. You know those programmers

who walk out the door each night at 5 PM? The ones who don't even show up until lOAM?

They use the Java API. And about eight pages from now, so will you. The core Java library
Is a giant pile of classesJust waiting for you to use like building blocks, to assemble your own

program out of largely pre-bullt code .The Ready-bake Java we use in this book Is code you

don't have to create from scratch, but you stili have to type It. The Java API is full of code you

don't even have to type. All you need to do is learn to use it .

this Is a new chapter 125



we stili have a bug

Itt our last chapter, we left you


with the cliff.. ha.,ger. Abug.

How ifs supposed to look How the bug looks


Here's what happens when we Here's what happens when we
run it and enter the numbers enter 2,2,2 .
1,2,3.4,5,6 . Lookin' good.

Aco~plete galMe I.,teractlon Adifferent galtle Interact/o.,


(your mileage may vary) (yikes)

Fllo Ed~ Window He Felnl

~ j a va SimpleDotComGame
enter a number 2
hit
enter a number 2
hit
enter a number 2
kill
You took 3 guesses

hi the CUffltlt verslotl. otlce


you geta hit, you catl shttplv
repeat that hittwo tMore
tlllles for the kill!

126 cha pter 6


get to know the Java API

So what happetted?

public String checkYourself (String stringGuess) (

int guess'" Int:8ger.pa.rselnt{stringGue8S); (-- fon\l~ the Sh-ill~


1;Q all lilt.
Strinq reBUlt '" ''miss''; ( - A1ake cl va~jable t.D hold the reswi: 'II
rttwhl p.,.e II " we
(' . ...iss i\'\ as the detault
I. e. lIIe as.s""'e 8 u... iss''),

for (int cell loeationCells)

Here's where It
goes wrong. We
counted a hit every ~
time the user
guessed a cell
location. even If
that location had
already been hit!

We need a wayto
II end foz:
know that when
a user makes
if (numOfHits = locationCells . length)
a hit, he hasn't
previously hit that result::: "kill";
cell. If he has, then
we don't want to II end if
count It as a hit.
System . out.println (result) j ~ Di1fla'f the res"l! k()lr the lI.1Cr
return result;
(..... i~", ",,1e1S it waJ i.hcl,,~ed to "hit" CW' "1cill U ) .
r-, R~ the "mit baLk to
II e n d me t h od the talli~ "'«hod.

you are here. 127


fixing the bug

How do we fix it?


We need a way to know whether Q cell has already been hit. Let's run
through some possibilities, but first, we'll look at what we know so for...

We have a virtual row of 7 celts, and a DotCom will occupy three


consecutive cells somewhere in that row. This virtual row shows a
DotCom placed at eel/locations 4,5 and 6.

The DotCom has an instance variable-an int array-that holds that


DotCom object's cell locations .

locatlonCells
(instance variable of
the DotCom)

• OptlO" o"e
We could make a second array, and each time the user makes a hit, we
store that hit in the second array. and then check that array each time
we get a hit. to see if that cel/ has been hit before.

kltCells arra~
(this would be 0
new boolean array
instance variable of
the DotCom)

128 chapter 6
get to know the Java API

Option one is too clunky


Option one seems like more work than you'd expect. It means that each
time the user makes a hit, you have to change the state of the second
array (the 'hitCells' array), oh -~ but first you have to CHECK the 'hitCeJls'
array to see jf that cell has already been hit anyway. It would work, but
there's got to be something better...

• OpfloHtwo
We could just keep the one original array, but change the value of any hit
cells to -1. That way, we only have ONE array to check and manipulate

locQtlonCells
(instance var iable of
the DotCom)

Option two is a little better, but


still pretty clu"ky
Option two is a little less clunky than option one, but it's not very efficient. You'd
still have to loop through all three slots (index positions) in the array, even jf
one or more are already invalid because they've been 'hit' (and have a -1 value).
There has to be something better...

you are here I 129


prep code
prep code

Optlo., three
We delete each cell location as it gets hit, and then modify the array to
be smaller. Except arrays can't change their size, so we have to make a
new array and copy the remaining cells from the old array into the new
smaller array.

locatlonCells array
BEFORE any cells
have be.en hit

locatlonCells array
AFTER cell '5', which
was at inde.x 1 in the.
array, has been hit

Optlo., three would be 'Much better Ifthearray could shrlttlc, so that we would.,'t have
to ",ake a .,ew ''Maller array, copy there",altt'"(1 values ht, attd reasslQ" thereferettce.

fhe orlal"81 prepcode for partof the Life would be good 'f otdy we could
checkYourselfU 'Method: chattae Itto:
REPEAT with each of the location cells in the int array . ~. -REP EAT with each of the remaining locat ion cells
1/COMPARE the user guess to the location cell /1 COMPARE the user guess to the location cell
I F the user guess matches IF the user guess matches
INCREMENT the number of hits ~ REMOVE this cell from the array
/1 FIND OUTif it was the last location cell: 1/ FIND OUTif it was the last location cell:
IF number of hits is 3. RETURN "kill" ~ 'IF the array is now empty, RETURN "ki ll"

ELSE it was not a kill, so RETURN"hit" ELSE it was not a kill. so RETURN"hit"
END IF END IF
ELSE user guess did not match, 50 RETURN "miss" ELSE user guess did not match, so RETURN "miss"
END IF END IF
END REPEAT END REPEAT

130 chapter 6
get to know the Java API
when arrays aren't enough

Wake up at1d stMell the library

As if by magic, there really Is such a thing.

But it's not an array, it's an ArrayLisf.

A class in the core Java library (the API).

The java Standard Edition (which is what you have unless you're work-
ing on the Micro Edition for small devices and believe me, you'd know)
ships with hundreds of pre-built classes. Just like our Ready-Bake code
except that these built-in classes are already compiled.

That means no typing.

Just use 'em.


ArrayUS t

dd{Ob}ed e\en") aram eter to the \\st .


a Adds the object P
et er.
Ont. of a 5az..illiol\ t1asst.$ in eUnt Index) h \nde)( paralTl
t.ht. Ja~a libvavy. ren"o" he object at t e
Removes t
Yo... tan lASt. it itl 'fOlJ.V cede {Ob}ed elel1\) t' 'I' the AnayLlst).
as i+ yOlJ. IIIrOU if 'f0.. ~I.f. rel1\o"e thIs object (If I s
RelTl oves
) arameter
. {Object e\en" h for the object P
,o"ta,n s , 'If there'S a mate
Returns trUe
II . \em entS
\sEI1\PtV . If the list has no e
RetUrns true ,
, ) eter, or '
\"dellOf{Obiec~ ~:~de)( of the object paralTl
RetUrns elthe
currently In the list
s\zell h number of elements
RetUrns t e
(NoU; tht add(ObjttA:. ele...) ...tthod aram et er
att..ally look.s a li-i:.Be sh-a"1& ~a .. -tht ge tt\nt Indell)
the obleet eur r ently at the.l.n.de.'Il.p .
Returns
OY\e ..,e'~t shOWtl h,~e ... ..,,'11 ~tt to -the
..tal Qrle lai& i .. tht book. FOfr ""'''', jlA1t
think of it as a.. aodO ...tihod that
take.! the objett yo<. ",ant to addJ

132 chapter 6
get to know the Java API

Some thhtgs you ca., do with ~rrayLisr


~
a~\e-h--6t.ket ~"jI,
D '~wt:IrT'f a~ this ",ew': -.T. , l o.f c, ol:!' eth"·
'"' .~. t I\S U....akt IS a \In. "j~ ~
• Make one ? . . i~~t "ow; I jW Mea _ .

ArrayList<Egg> myList = new ArrayList<Egg> () ; ~-a'1l,ist objet~ \ 'We


/'I ~ (\P tnt \leaf' \~ 5 ,
tvea~ci ,~ ...w,

• Put something in it
Egg s = new Egg() i
\)eLi~ no' CW'Y "I

myList.add(s)i

• Put another thing in it


Egg b = new Egg();

myList.add(b);

• Find out how many things are in it


int theSize = myList.size();

Find out if it contains something The A'rt"a'1L.i.st. Dol:S tC/tItail'l the ~~


I / " .... ,.__ I.e! ku '5', so tC/tItail\SO retWY\S ~
, tltd
boolean is10 = myList.contains(s)i ~ ~~.~~ ~1

" D 0 (... eal\S ~irtt. ;Yllie~ is 0)


Find out where something is (l.e. its index) ~ Atta'1Ust 15 ~ Last ,. _ . 0 D'f '0' ..,os the
int idx = myList .indexOf(bl i
d '."te the Objet.. vt-tc;·~t
01'1 51 l"
I
' l.\. \.--1. i\'lO~'W .... eboVl\S_
sUO\'IO ..hl"~ lY\ 'We In"

Find out if it's empty it's deo.fil'li+.tly NOT bftpty, so isE"'rtyO


boolean empty = myList. isEmpty (); C- r~PIS £ili.e
• Remove something from it
myList.remove(s);

you are here. 133


when arrays aren't enough

~ your penCil Fill In the rest of the table below by looking at the ArrayList code
on the left and putting in what you think the code might be if it
were using a regular array Instead. We don't expect you to get all
of them exactly right, so Just make your best guess.

ArrayList regular array


hrrayList<String> myList = new
~h-i"9 0 "'yList ::.. "ew Sh-il'l~ClJj
hrrayList<String>();

String a = new String("whoohoo H ) ;


Sb-il'l'l a =- ~ Sb-i~("whoohool)j
myList.add(a);

String b = new String("Frog H )


~iri,,~ \> ::. """ ~ir;I'I~C'n-~»)j
;

myList. add (b) ;

int theSize = myList.s izeO:

Object 0 = myList.get( l);

myList.remove(l);

boolean isIn = myList.contains(b);

134 chapter 6
get to know the Java API
;\.

Java'&pos~
R..,: So Arl1lyListIs cool, but This week's Interview:
ArrayList. on arrays
how would I know It exists?
HeadFirst So, ArrayLists are like arrays, right?
!A.: The question is really, ArrayLlst In their dreams! I am an objec: thank you very much.
-How do I know what's In the
HeadFirst If I'm not mistaken, arrays are objects too. They live on the heap right
API?" and that's the key to your
success as a Java programmer. there with all the other objects.
Not to mention your key to ArrayList Sure arrays go on the heap, duh, but an array is still a wanna-be
being as lazy as possible while ArrayList. A poser. Objects have state and behavior, right? We're clear on that. But
still managing to build software. have you actually tried calling a method on an array?
You might be amazed at how
much time you can save when HeadFirst Now that you mention it, can't say I have. But what method would I
somebody else has already done call, anyway? I only care about calling methods on the stuff I put in the array, not
most of the heavy lifting, and the array itself. And I can use array syntax when I want to put things in and take
all you have to do is step in and things out of the array.
create the fun part.
ArrayUst Is that so? You mean to tell me you actually remooed something from an
But we digress... the short
array? (Sheesh, where do they train. you guys? Mljava's?)
answer Is that you spend some
time learning what's In the core HeadFirst Of &OlITSe I take something out of the array. I say Dog d = dogArray[l)
API. The long answer is at the and J get the Dog object at index lout of the array.
end of this chapter, where you'll
learn how to do that. ArrayList Allright, I'll tty to speak slowly so you can follow along. You were 1UJ1,
I repeat TUI~ removing that Dog from the array. All you did was make a copy of the
rifmnce to tht Dog and assign it to another Dog variable.
R: But that's a pretty big
Issue. Not only do I need to
HeadFirst Oh, I see what you're saying. No I didn't actually remove the Dog
know that the Java library object from the array. It's still there. But I can just set its reference to null, I guess.
comes with ArrayLlst, but more ArrayLlst: But I'm a first-class object, so I have methods and I can actually, you
Importantly I have to know know, M things like remove the Dog's reference from myself, not just set it to null.
that ArrayList Is the thing that And I can change my size, dynami£al£y (look it up). Just tty to get an ami)' to do that!
can do what Iwantl So how
110 I go from a need-to-do- HeadArst Gee, hate to bring this up, but the rumor is that you're nothing more
something to a-way-to-do-It than a glorified but less-efficient array. That in fact you're just a wrapper for an
using the API? array, adding extra methods for things like resizing that I would have had to write
myself. And while we're at it,J'OU can't even haM primiJiDes! Isn't that a big limitation?

!A..:Now you're really at the ArrayList I can't believe you buy into that urban legend. No, I am not just a less-
efficient array. I will admit that there are a few extmne{y rare situations where an
heart of It . By the time you've
finished this book, you'll have array might be just a tad, I repeat, tad bit faster for certain things. But is it worth the
agood grasp of the language, miniscule performance gain to give up all this poWa'. Still, look at all tlllsflexihiliry. And
and the rest of your learning as for the primitives, of 'dum you can put a prirntive in an ArrayList, as long as it's
curve really Is about knowlnq wrapped in a primitive wrapper class (you'll see a lot more on that in chapter 10).
now to get from a problem to And as ofJava 5.0, that wrapping (and unwrapping when you take the primitive out
a solution, with you writing the again) happens automatically. And allright, I'll Q£krwwledge that yes, if you're using an
least amount of code. If you can
ArrayList of primitives, it probably is faster with an array, because of all the wrapping
be patient for a few more pages,
and unwrapping, but still... who really uses primitives Uu.se days?
we start talking about it at the
!nd of this chapter. Oh, look at the rime! I'm llJujor Pilaus: We'll have to do this again sometime.

you are here ~ 135


difference between ArrayList and array

CotMparhtg ArrayList to a regular array

ArrayList regular array


ArrayList<String> myList = new String [] myList = new String[2J;
ArrayList<String>();

String a = new String("whoohoo"); String a = new String("whoohoo");


myList.add(a) ; myList[O) = a;

String b = new String ("Frog") ; String b = new String("Frog");


myList.add(b); myList{l) = b;

int theSize = myList.size(); int theSize = myList.length; ~ ,


\ \\eY~ s ..,'ncYt
= myList.get(l); rl;s tp \oo\t.
\ ~a\\'t d'~~eYO\t...: t
Object 0 String 0 = myList(l];

myList.remove(lj; myList(l] = null; ..,..

boolean isIn = myList.contains(b); boolean isIn = false;

for (String item : myList) (

if (b. equals (item)) {

isIn = true;

break;

Notice how with ArrayList, you're working With an arra)', you use special array syntax (like
with an object of type ArrayList, so you're just myList[O] = foo) that you won't use anywhere
invoking regular old methods on a regular old else except with arrays. Even though an
object, using the regular old dot operator. array is an object, it lives in its own special
world and you can't invoke any methods on
it, although you can access its one and only
instance variable, length.

136 chapter 6
get to know the Java API

CotMparit1g ArrayList to a regular array

• A plain old array has to know its


size at the time it's created.
But for Arrayl.ist, you just make an object of
type Arrayl.ist, Every time. It never needs to
Arrays use array syntax that's not
used anywhere else in Java.
But ArrayLists are plain old Java objects, so
they have no special syntax.
know how big it should be , because it grows
myList[l]
and shrinks as objects are added or removed.
~ ~ .\
n ew Str ing[2] Needs 0 siu· The ott0'l Lo\"otkets [ J o\"e sfet,o
s'll'lta~ l,ISed 01'1\'1 kO't' attd'ls.
new ArrayList<String>( )

No siu \"e,"'i\"eo (olthOl,\~h YOl,\ tan


~ive it 0 siu i~ yo", wont to).

• To put an object in a regular array,


you must assign it to a specific
location.
• ArrayLists in Java 5.0 are
parameterized.
We just said that unlike arrays, Arrayl.ists
have no special syntax. But they do use
(An index from 0 to one less than the length of
something special that was added to Java 5.0
the array.)
Tiger-paramet:erized types.
myList[l] = b;
Ar rayList <String>
~
Needs oYl il'lde~.

If that index is outside the boundaries of the


'"
The <St\"il'l~> in ol'l~le b\"otlcets is 0 "-t'ife
fo\"offtete\"". A\"\"oyList<St\"il'lg> ffteal'lS Sifftf1y "0
array (like, the array was declared with a size of list ~ Stril'lgs", oS offosed to AttoyList<Dog>
2, and now you're trying to assign something whith ""eons, "0 list ~ Dogs".
to index 3), it blows up at runtime. Prior to Java 5.0, there was no way to declare
With ArrayIist, you can specify an index us- the type of things that would go in the
ing the add(anlnt, anObject) method, or you ArrayList, so to the compiler, all ArrayIists
can just keep saying add(anObject) and the were simply heterogenous collections of
ArrayList will keep growing to make room for objects. But now, using the <typeGoesHere>
the new thing. syntax, we can declare and create an
myList.add(b) ; ArrayIist that knows (and restricts) the
-, types of objects it can hold. We'll look at the
details of parameterized types in ArrayLists
No il'ldex. in the Collections chapter, so for now, don't
think too much about the angle bracket <>
syntax you see when we use Arrayl.ists, Just
know that it's a way to force the compiler to
allow only a specific type of object (the type in
angle brackets) in the ArrayList.

" _" ........_ L.. ...


the buggy DotCom code

Letl fix the t'otCOItt code.

int(] locationCells;
int nurnOfHits = OJ

publ ic void setLocationCells(int[] locs) (


locationCells = locs;

public String checkYourself(String stringGuess)


int guess = Integer.parselnt(stringGuess);
String result "miss ";

fo r (i nt ce ll locat i onCe l l s )

break;
}
I I ou t o f: t he l oop

if (numOfHits == l oc a t i o nCe l l s . l e ng t h )
result. = " ki l l " ;

System.out .println(resul t);


return result;
/ / c l os e me t h od
I I c l ose cl a s s

138 chapter S
get to know the Java API

prep code ID~~

New and hMproved PotCOtM class

import

publ ic class DocCom I

p r Lva t e ArrayList<Strinq> locationCells ;


/ / pri v at e i n c nurnOf<Ji t ~ ~-a L.irt. that. ho\ds Shin~S -
// don ' t n e ed t.ha c now C Lhe Shinl1 a"r.,.a~ to an f\n ~
ha"ljl", .(;)

publi c vo id se t Locat ionCe lls (ArrayList<String> Loc) ! l'll "al'l'l-


locat ionCe lls = loc; _ .,.-o'ItO a'(~l>J"t
~t'tI a"d ""r-

public String checkYours e lf (String user Inputl


/'"
(
"t \I.SC'f"~!>S
f ind out, tne - ~orr ib inde~
is i" t.he

~
An-a~L.-'st... b ~l~skll~1) t.hen i,..oe-d)tO
I~r ",l.'s
l '" 1St.
String result = " mi s s" ; '"
_A
.-'"
",I'll

y~'n\S a -l-
int index = locationCells.indexOf(userlnput):
if (index >= 0) {

if (locationCells.isEmpty(»
result "kill";
else I
result c: "h it";
I I c l os e if

II c l os e ou e r if

return r esult;
) II c lose method
I I cl os e c l a s s

you are here. -1 3 9


making the OotComBust

Let's build the REAL galtte:


HSi"k a Pot COItt M

We've been working on the 'simple' version, but now


let's build the real one. Instead of a single row, we'll You're going to build the
use a grid. And instead of one DotCOID,we'll use Sink a Dot Com game, with
three . a 7 x 7 grid and three
Goal: Sink all of the computer's Dot Corns in the Dot Cams. Each Dot Com
fewest number of guesses. You're given a rating level takes up three cells.
based on how well you perform.
Setup: When the game program is launched, the
computer places three Dot Corns, randomly. on the
virtual. 7:x. 7 grid . When that's complete, the game
asks for your first guess .
partof a gattte I.,teractlo.,
How you play: We haven't learned to build a GUI
yet, so this version works at the command-line. The 't j ava DotComBust
computer will prompt you to enter a guess (a cell), Enter a guess A3
which you'll type at the command-line (as "A3n, WCS\
etc.) , In response to your guess, you'll see a result at miss
the command-line, either "hit", "miss", or "You sunk Enter a guess 82
Pets.com" (or whatever the lucky Dot Com of the day miss
is) . When you've sent all three Dot Corns to that big
404 in the sky, the game ends by printing out your Enter a guess C4
rating. miss
Enter a guess 02
7 )<. 7 ~__id
hit

A k V Enter a guess D3
hit
B
E Enter a guess 04
( q Ouch! You sunk Pets.com
N

o i ....p L;~ kill


I· .~ .,.~~,~c f~~~~
Enter a guess B4
E
miss
F Enter a guess G3
hit
G
RS.IrMe~c ~m
I. '. Enter a guess G4
o 1 2 345 6
hit
\ start.s at ZbO, like Java ar'ra'f~ Enter a guess G5
Ouch! You sunk AskMe .com

140 chapter 6
get to know the Java API

What tteeds to chattge? DotComBust class continued.••


We have three classes that need to change: the o Put the DotComs on a grid rather than
DotCom class (which is now called DotCom instead of just a single row, and do it for all three
SimpleDotCom), the game class (DotComBust) and the DotComs.
game helper class (which we won't worry about now). This step is now way more complex than
o DotCom class
before, ifwe're going to place the DotComs
randomly. Since we're not here to mess
o Add a name variable with the math, we put the algorithm for
to hold the name of the DotCom giving the DotComs a location into the
("Pets.com", uGo2.com~, etc.) so each Dot- GameHelper (Ready-bake) class.
Com can print its name when it's killed (see
the output screen on the opposite page). @ Check each user guess with all three

o DotComBust class (the game)


DotComs, instead of just one.
@ Keep playing the game (i.e accepting
o Create three DotComs instead of one. user guesses and checking them with the
remaining DotComs) until there are no nwre
o Give each of the three DotComs a name. live DotComs.
Call a setter method on each DotCom
instance, so that the DotCom can assign the o Get out of main. We kept the simple one in
name to its name instance variable. main just to... keep it simple. But that's not
what we want for the real game.

3 Classes:
DotcomBlItt DotCom Gam.Helper

The game class. The actual The helper class


Makes DolComs, DotCom objects. (Ready-Bake).
gels user Input, DolComs know their It knows how to
plays until all001· name. location, and accept user com-
Corns are dead how 10 check a user mand-llne input,
gu6SS for a match. and malle DOICom
locations.

Plus 4
ArrayLists: 1 for
the DotComBust
5 Objects: and 1 for each
of the 3 DotCom
objects.

DotComBust GameHelper

you are here ~ 141


detailed structure of the game

Who does what it' the PofColMJust gatMe


(at'd whetd

DotCom8u" The mainO method

o The game
class.
instantiates in the DotComBust
class instantiates the
DotComBust object that
does all the game stuff.
DotComBust
object

The DotComBust (game)


object instantiates an
instance of GameHelper.
the object that will help
DotComBust the game do its work
object

The DotComBust object


instantiates an ArrayList
that will hold the 3 DotCom
objects.

ArrayList object (to


hold DotCom objects)

142 chapter 6
get to know the Java API

e The DotComBust object


creates three DotCom
objects (and puts them in
the ArrayList)

ArrayList object to
DotCom
hold DotCom objects
objects

The DotComBust object asks the The DotComBust object gives each of the Dot-
he/per object for a location for a Com objects a location (which the DotComBust
DotCom (does this 3 times, one for got from the helper object) like - A2 u • -B2-.
each DotCom) etc . Each DotCom object puts his own three
location cells in an ArrayList

ArrayList object
(to hold DotCom
cell locations)

Ar ray List
object

ArrayList
object

The DotComBust object asks the helper The DotComBust object loops through the list
object for a user guess (the helper of DotComs. and asks each one to check the user
prompts the user and gets input from guess for a match . The DotCom checks its locations
the command-line) ArrayList and returns a result ("hW. "miss", erc .)

ArrayList object
(to hold DotCom
cell lccctioas)

ArrayList
1If:Jl~91o bj ec t

And so the game continues ... get- ArrayList


ting user input. asking each DotCom object
to check for a match, and continuing
until 011 DotComs are dead
you are here ~ 143
the OotComBust class (the game)

prep code

DalComBUJt

GameHelper helper
ArrayUsl dolComsLlsl
Inlnurn OfGUB.'lS6S
-
Prep code for the real PotCOIM'ust class
The DotComBust class has three main jobs: set up the game, play the game
until the DotComs are dead, and end the game. Although we could map
those three jobs directly into three methods, we split the middle job (play the
selUpGameO
game) into two methods, to keep the granularity smaller. Smaller methods
slarIPlayingO (meaning smaller chunks of functionality) help us test, debug. and modify
checkUserGuessO the code more easily.
fin~GameO

DECLARE and instantiate the GomeHelper instance variable, named helper.


DECLARE and instantiate an ArrayUst to hold the list of DotComs (initially three) Call it
Variable dotComsLJst
DECLARE an int variable to hold the number of user guesses (so that we can give the user a
Declarations score at the end of the game). Name it numOfGuesses and set it to O.

DECLARE a setUpGameO method to create and initialize the DotCom objects with names
and locations. Display brief instructions to the user.
DECLARE a 5tortPlayingO method that asks the player for guesses and calls the
Method
checkUserGuessO method until all the DotCom objects are removed from play.
Declarations DECLARE a ched<UserGuessO method that loops through all remaining DotCom objects and
calls each DotCom object's checkYourselfO method.
DECLARE a ~nlshGomeO method that prints a message about the user's performance, based
on how many guesses it took to sink all of the DotCom objects.

METHOD: voId JetUpGGmeO


II make three DotCom objects andnome them
CREATE three DotCom objects.
Method
SET a name for each DotCom,
Implementations ADD the DotComs to the dotComsLJst ( the ArrayList).
REPEAT with each of the DotCom objects in the dotComsUst array
CALL the placeDotComO method on the helper object, to get a randomly-selected
location for this DotCom (three cells, vertically or horizontally aligned, on a 7 X 7 grid).
SET the location for each DotCom based on the result of the placeDotComO call,
END REPEAT
END METHOD

142
get to know the Java API

Method httpleltt8MtatioMS COMttMUad:


METHOD: void startPlaylng()
REPEAT while any DotComs exist
GET user input by calling the helper getUserinputQ method
EVALUATE the user's guess by checkUreI'GuessO method
END REPEAT
END METHOD

METHOD: void checkUserGuess(SCrlng userGuess)


/I find out if there's a hit (and kill) on any DotCom
INCREMENT the number of user guesses in the numOfGuesses variable
SET the local resul! variable (a String) to "miss", assuming that the user's guess will be a miss.
REPEAT with each of the DotObjeC1S in the dotComsUst array
EVALUATE the user's guess by calling the DotCom object's checkYourseJf() method
SET the result variable to "hit" or "kill" if appropriate
IF the result is "kill", REMOVE the DotCom from the dotComsUst
END REPEAT
DISPLAY the resul! value to the user
END METHOD

METHOD: void fJnlshGameO


DISPLAY a generic "game over" message,then:
IF number of user guesses is small,
DISPLAY a congratulations message
ELSE
DISPLAY an insulting one
END IF
END METHOD

rpen yoor p e n C i l - - - - - - - - - - - - - - - - - - ,
How should we go from prep code to the methods, And which method do you test
final code? First we start with test code. and and write first? See If you can work out some
then test and build up our methods bit by prep code for a set of tests. Prep code or
bit. We won't keep showing you test code even bullet points are good enough for this
In thIs book, so now It's up to you to think exercise,but If you want to try to write the
about what you'd need to know to test these rea/test code (In Java), knock yourself out,

you are here. 145


the DotComBust code (the game)

import java.util . *;
public c lass DotComBust
Annotat. the code
yourself.
Pr i va t e GameHelper helper new GameHelper() ;
Match the
~ private ArrayList<DotCom> dotComsList
f private int numOfGuesses
private void setUpGame () (
= 0;
= new AIrayList<DotCom>();
annotations 8t the
bottom of each
with the numbe...
...

II first make some dot corns and give them locations In the code. Writ.
the number In the
DotCom one = new DotCom();
slot In front of the
one .setName(-Pets.com"); eorr..pondlns


DotCom two = new DotCom(); annoldon.
two.setName("eToys.com H ) ;
DotCom three = new DotCom(); You'll u_ each
three .setName{ "Go2.com"); annotation Just once,
and you'll n.....11 of
dotComsList ,add {one);
the .nnotatlon•.
dotComsList,add(two);
dotComsList .add(three);
System.out.println("Your goal i s to sink three dot corns.");
System.out,println("Pets .com, eToys.com, Go2.com");
System.out,pr intln("Try to sink them all in the fewest number of guesses "):

for (DotCom dotComToSet : dotComsList) ( •


ArrayList<Str ing> newLocation = helper .placeDotCom(3); ~
dotComToSet .setLocationcellS(neWLocatiOn); ...
I I I c lose for loop
I I c los e s ec UpGame method

pr i va te void startPlayinq () (
while(!dotComsList,isEmpty() ( •
String userGuess = helper.getUserInput("Enter a guess"); ~
checkUserGuess(userGuess); •
I I I c l ose wh il e
linishGame () ; •
I I c lose sta rcPlay ing met hod

146 chapter 6
get to know the Java API

Whatever you do,


DON'T turn the
pagel
private void checkUserGuess (String u serGuess) {

numOfGuesses++; 4ID Not until you've


finished this
String r esult = " miss" ; ~ exercise.
for (DotCom d otComToTest : dotComsList) { ~ Our version is on
result = dotComToTest.checkYourself(u serGuess); ~
the next page.
if (result.equals("hit"» {
~
break; •
)


if (result.equals("kill"»
dotComsList.remove(dotComToTest);
b reak;

) I I c l os e fo r
System. out.println(result); •
II c lose method

private v oid finishGame ()


System.out.pri ntln("All Dot Corns are dead! Your stock i s now worth less.");
if (numOfGuesses <= 18) {
System.out.println(" It only took y ou" + numOfGues ses + " guesses.") ;
System.out.println(" You got out before you r op ti o n s sank.");
el se {
System.out.println("Took you long enough. " + numOfGuesses + " guesse s .");
System.out.println("Fish are dancing with your o p tio n s . " ) ;
}
I I close method

public s t a t i c void DUlin (S tring[] args) {


DotComBust game = new DotCOmBust();.
game . setUpGame () ; •
game. startPlaying () ; •
II close method

_ Pt'il'l't the
~es~lt to\'"
the ~et'
_ull the ~a",e objett
to set ~f the ~a...e

you are here ~ 147


the DotComBust code (the game)

import java.util.*;
pub Li,c class DotComBust

private GameHelper he l pe r "' new GameHelper () ; ~, ~


private ArrayLis t<DotCom> dotComsList = new ArrayLlst<DotCom> (); Ma\(( a" An-att atn
private int nurnOfGuesses = 0; DotCo'" ~jC:L .L'" 'II h~d
lis a l,st. Vla~ "'"
ONL.~ Dot:COf'I ~jctb,
private void setUpGame () ( ' w{: as pot£.or..() ...,oJd
/1 fust make some dot corns and give them locations J",tdll ..~II a"/ ok DotcOfl"
DotCom one = new DotCom(): o\>jtt.W.
one .setName("Pe ts.com") ;
DotCom two = new DotCom();
two .setName("eToys.com");
DotCom three ~ new DotCom();
three.setName("Go2.com");
dotComsList.add(one);
dotComsLis t.add(two) ;
dotComsList.add(three); Pyi\'lt b\-ie~

~
ir.st,n..l tions .foor \O.KY.
System,out.println("¥our goal is to sink three dot coms .");
System.out.println("Pets .com, eToys.com, Go2.com") ;
System .out.println("Try to sink them all in the fewest number of guesses");

f o r (DotCom dotComToSet : dotComsList) { ~Reytdt 'WoIith tdth DO'l:.COftI i" t~t list.
Ask t},c helt'e\' t.... a
ArrayList<String> newLocation = helper.placeDotCom(3); ~ D~ loUBOY\ ~a:.~
~a'1Lisi .J Sh,,,,..·..
dotComToSet. setLocationCells (newLocation) : ( - C<111 ih
DotCA...e ~~t" "'~
to . 't
.1, .
0" UlIJ
I / / c l.ose f o r loop j~ ~ot .(t"o1'V~j the 10t4i:ioh y04J.
I I close se t Upq ame, method ~ helpa-.

private void startPlayinq ()

while( !dotComsLi9t.is~mpty())

String userGuess = helper .getUserlnput ("E:nter a guess"); k""' ~et \O.KY i\'lflo+"
checkUserGuess(userGuess);~
C<111 ~ OWJI lhtl~1A L.
II cl o s e whi le
set'qlotU "'et.hod.
finis hGame(); ~ C<111 010"" 0""" +i"ish~a"'e ...tihod.
I J c l ose s C3rt Pl ay il1g method

148 chapter 6
get to know the Java API

private void checkUserGuess (String userGuess) {

numOfGuesses++;

String result \\miss"; t--asslA",e it's a '",iss', IAl'liess told oth«wise


for (DotCom dotComToTest dotComsList) { ~ \"eyeat with all DotCO\'I'IS il'l the list

result = dotComT oTest .checkYourself (userGuess); ~ ask the DotCO\'I'I to thet.k the Wie\"
~IAeSS, lookil'l~ ~O\" a hit (0\" kill)
if (result .equals(\\hit"» (

break; ~ ,ei ~~ o.f the loop ea\"ly, 1'10 poil'lt


<; 11'1 USt;II'I~ the others
)
if (result.equals("kill"» (

dotComsList.remove(dotComToTest);
break;

I I c l o s e for

System. out.println (result); ~ PY'il'lt the reslAlt +0\" the Wi«


II c l o s e met hod PY'il'lt a l'IIessa~e tellil'l~ the
lASe.. . how he did il'l the ~l'IIe

private void finishGame ()


System.out.println(\\All Dot Corns are dead! Your stock is now worthless .");
f
if (numOfGuess es <= 1 8) (
System.out.println(\\It only took you \\ + numOfGues s e s + \\ guesses.") ;
System.out.println(\\ You got out before your options sank.");
else (
System . out.println(\\Took you long enough. \\+ numOfGuesses + \\ guesses.");
System .out.println( \\Fish are dancing with your options");
)
I I close met hod

public static void main


DotComBust game = new
game.setUpGame();
game.startPlaying();
II clo s e me t hod

yo u are here • 149


the DotCom code

The final version of the


PotCOtlt class
import java .util.*;

DotCOM'5 iWlStaWlte "iav-ia'oles:


public class DotCom
_ ah Arra'fl-ist cJ tell loeatiOWlS
private ArrayList<String> locationcells;'S
_ the DotCOM'5 ~Me
private String name; )

public void setLocationCells(ArrayList<String> loc) {


locationCells = loc;

public vo id setName (String n) ~ 'lOll-V- basit seHe\" Method


name = n;

pUblic String checkYourself(String userlnput) {


Str ing result = ~miss";

int index = locationCells .indexOf(userlnput);


if (index >= 0) (
l ocationCells.remove(index);~
1___ (,(Sih~
L._
(lrrayl-ist'
5 \"eMo"ie
() il
Me~od 1R
L_.J
aeIe1;C:
L_ L
an en,,\,,'!,

if (locationCells. isEmpty ()) { (-----~'-.. (,(sin~ the iS~Mft'l( ) Method to see i~ all
re sult = ~kill";
cJ the loeatoWlS ha"ie been ~~sed
System.out.println(~Ouch! You sunk ~ + name + ~ ( ~);

else {
result = ~hit ";
<,
Tell the lASe\" wnen h Lr»
' a Vo"U., has bten 51Ahk.
} II close i f OM
II cl ose i f
return result;
O_i....... ( . ,
1\1:1;- n, -...5S ..... 'h'i' ,
..... '" or kill'.
} I I close method
I I close class

150 chapter 6
get to know the Java API

Super Powerful 'oolea" [xpressio"s


So far, when we've used boolean expressions for our loopsor Not equals (!= and ! )
i f tests, they'vebeen pretty simple. We will be using more
powerful boolean expressions in some of the Ready-Bake code Let's say that you have a logiclike,"ofthe ten available
you're aboutto see, andeven though we knowyou wouldn't camera models, a certain thing is true forall butone,"
peek, wethought this would bea good time to discuss howto if (model 1= 2000) {
energize yourexpressions. II do non-model 2000 stuff
}
'And' and 'Or' Operators (&&, II )
or for comparing objects likestrings...
Let's say you'rewriting a chooseCamera( ) method, with lotsof rules
aboutwhich camera to select. Maybe you can choose cameras if (lbrand.equals("X"» {
ranging from $50 to $1000, but in some cases youwantto limit the II do non-brand X stuff
price range more precisely. You wantto say something like: }

'If the price range isbetween $300 and $400 then choose x: Short Circuit Operators (&&, II )
The operators we've looked at sofar, && and II, are
if (price >= 300 && price < 400) { known as shortcircuit operators. Inthe case of &&,
the expression will betrue onlyif both sides ofthe &&
camera =
"X"i
are true. So jf theJVM sees that the left side of a &&
} expression isfalse, it stops right there! Doesn't even
botherto lookat the right side.
Let's say that of the ten camera brands available,you have some Similarly, with II, the expression will betrue if either side is
logicthat applies to onlya few of the list: true, soif the JVM sees that the left side istrue,it declares
the entire statement to betrue and doesn't botherto
check the right side.
if (brand.equals("A") II brand.equals("B") ) {
Why isthis great? Let's say that youhave a reference
II do stuff for only brand A or brand B variable and you're not sure whether it's been assigned
} to anobject. If youtry to call a method using this null
reference variable (l.e, no objecthas been assigned), you'll
get a NullPointerException. So, try this:
Boolean expressions can get really big and complicated:

if «zoomType.equals("optical") && if (refVar 1= null &&


(zoomDegree >= 3 && zoomDegree <= 8» II refVar.isvalidType() ) {
(zoomType.equals("digital") && II do 'got a valid type' stuff
}
(zoomDegree >= 5 && zoomDegree <= 12») {
II do appropriate zoom stuff Non Short Circuit Operators (&, I)
} When used in boolean expressions, the & and Ioperators
If youwantto get really technical, you might wonder aboutthe act liketheir && and II counterparts, except that
precedence of these operators. Instead of becoming anexpert they force theJVM to always check both sides of the
in the arcane world of precedence, we recommend that you use expression. Typically, & and Iare used in another context,
for manipulating bits.
parentheses to make yourcode clear.

you are here ~ 151


Ready-bake: GameHelper

Th is is the helper class for the game. Besides the. user input method
(that prompts the user and reads input from the commend -line), the
helper's Big Service is to create the cell locat ions for the DotComs.
If we were you, we'd just back away slowly from this code, except
to type it in and compile it. We tried to keep it fairly small to you
wouldn't hove to type so much, but that means it isn't the most
import java.io.*i readable code. And remember, you won', be able to compile the
import java.util.·: DotComBust game class until you have this class.

pUblic class GamaBelper

private static final Str ing alphabet "abcdefg";


NoU: F~ elttta ,,,e,M, '101# ",\~h-l:
private int gridLength = 7: b-)' '1<rI-'o...... c:"ti,,~' tht
private int gridSize = 49; S)'lu....Ollt.fri..HI,,)'s i.. t.he
pr ivate int () grid = new int[gridSize); fl.lteDoiCo...( ) ... dhod, j\l.1t.
private int comCount = 0; to w<iUh it work! These ?,"i"t
u
1~te-e"u will Id Y0l# "',heai
public String ge tUserlnput(String prompt)
String inpu tLine = null; by ~ivi,,~ 'f..... tile lold·tioll o-f the
System.out.print(prompt +" ")i Dot.ColN, bl#t it. will hell' 'fOIl ust it..
try (
BufferedReader is = new BufferedReader(
new InputStreamReader(System.in»);
inputLine = is.readLine();
if (inpu tLine.length() == 0) return null;
catch (IOExcept ion e) (
System.out.println("IOException : " + eli
I
return inputLine .toLowerCase();

public ArrayList<Stxing> placeDotCom(int comSi ze) (


ArrayList<String> alphaCells = new ArrayList<String>();
String [1 a1phacoords = new String (comSizel: II holds 'f6' type coords
String temp = null; II temporary String for concat
int II coords = new intlcomSize); II current candidate coords
int attempts = 0; II current attempts counter
boolean success = false; II flag = found a good location?
int location = 0; II current starting location
comCount++; II nth dot com to place
int incr = 1; II set horizontal increment
i f «cornCount % 2) == 1) ( II if odd dot com (place vertically)
i nc x = gridLength; II set vertical increment

while ( ! s uc c e s s & attempts++ < 200 ) ( II main search loop (32)


location = (int) (Math.random() .. gridSize); II get random starting point
I/S y s t em. o uc . p ri n t ( " t ry" + locat ion);
i n t x == Oi II nth position in dotcom to place
success = true; II assume success
while (success && x < comSizel II look for adjacent unused spots
i f (grid(locacion) =-= 0) { II if not already used

152 chapter 6
get to know the J ava API

tallteHelper class code cot1tlt1ued...

c o ords[x++] = location; II s a v e l ocati on


l o cation += incr; II tr y 'nex t' adjacent
if (location >= gridSize){ II out of b ounds - 'bottom'
success = false; II fa ilu re
}
if (x> O && (location % g ridLength 0» { II o u t o f b ounds - ri g ht edg e
success = false; II failure
}
else ( II f ound already used l o c a t i on
I I System . o ut .pr i nt ( " used" + l oc ati on);
succes s = f al se; II failure

I I e nd while

int x = 0; II turn l ocation into alpha coo r d s


int r ow = 0;
int c olumn = 0;
II Sy s tem . o u t . p ri n tl n ( "\ n " ) ;
whil e (x < c omSiz e) {
grid[coords[x]] = 1; II mark master g r id p t s . a s 'u s ed'
r ow = (int) (c o o rds[x] I gridLength); II get row value
c olumn = coords[x] % gridLength; I I g et numeric co l umn va lue
t emp = String.va lueOf(alphabet.charAt(column); I I c o nv e r t to alpha

alphaCell s.add(temp.concat(Integer.toString(row»); ttnat


x++; n' is tnC stateVOlC" t nC
II System .ou t . p r i n t ( n co or d " +x +" = n + a l p h aCe ll s . get(x - l) ); <;-,, 1 ~s olJ.c"14t.H'i'f/nCVOC
te s'f . \-'atCO.
1)otCOVOI IS ""
I I Sys t em . o u t .pr i ntln r " \ n " ) ;

r e t u r n alphaCells;

you are here ~ 153


API packages

Usittg the Library (the Java API)


You made it all the way through the DotComBust game,
thanks to the help of ArrayList. And now, as promised,
it's time to learn how to fool around in theJava library.

In the .Java API. classes


are grouped into packages.

To use a class in the API. you


have to know which package
the class Is in.
Every class in theJava library belongs to a package .
The package has a name, like javax.swlng (a
package that holds some of the Swing CUI classes
you'll learn about soon). ArrayList is in the package
called java.utll, which surprise surprise, holds a
pile of utility classes. You'll learn a lot more about
packages in chapter 16, including how to put your
own classes into your own packages. For now though,
we're just looking to usesome of the classes that come
with Java.
Using a class from the API, in your own code, is
simple. You just treat the class as though you wrote
it yourself... as though you compiled it, and there it
sits. waiting for you to use it. With one big difference:
somewhere in your code you have to indicate the full
name of the library class you want to use, and that
means package name + class name.
Even if you didn't know it, you've already been using
cJassesfrom a ptu:kage. System (System.out.println),
String, and Math (Math.random 0), all belong to the
java.lang package.

154 chapter 6
get to know the Java API

You have to know the full name*


of the class you want to use in
- :tberet&rH?
Dumo ~uest19ns

your code. Q.: Why does there have to


be a full name? Is that the only
purpose of a package?
ArrayList is not the full name of ArrayList, just as 'Kathy'
isn't a full name (unless it's like Madonna or Cher, but we
won't go there). The full name of ArrayList is actually: A: Packagesare import ant
for three main reasons. First, they
java.util.ArrayList help the overall organization of a
~ ~ project or library. Rather than just
/ '\ having one horrendously large
patka~e l'lc11l1e e.\ass ~"'c pile of classes, they're all grouped
into packages for specific kinds
of functionality (like GUI,or data
structures, or database stuff, etc.)
You have to tell Java which ArrayList you Second, packages give you a name-
want to use. You have two options: scoping, to help prevent collisions
if you and 12 other programmers
in your company all decide to
make a class with the same name.
IMPORT If you have a class named Set and
Put an import statement at the top of your source code file: someone else (including the Java
import java.util.ArrayList; API) has a class named Set,you
need some way to tell the JVM
public class MyClass { ... } which Set class you're trying to use.

OR Third, packages provide a level of


security, because you can restrict
the code you write so that only

o
other classesin the same package
can accessit. You'll learn all about
TYPE that in chapter 16.
Type the full name everywhere in your code. Each time
you use it. Anywhere you use it. n .
~: OK, back to the name
. .. collision thing. How does a full
When you declare and/or instantlate It: name really help? What's to
java.util.ArrayList<Doq> list = new java .util.ArrayList<Dog>0 ; prevent two people from giving a
class the same package name?

When you use it as an argument type:


A:Java has a naming convention
public void go(java.util .Arraytist<Dog> list) { } that usually prevents this from
happening, as long as developers
adhere to it. We'll get into that in
When you use it as a return type: more detail in chapter 16.

public java.util.Arraytist<Doq> fooO { .. . }

"Unless the class is in the java.lang package.

you are here. 155


when arrays aren't enough

.-----_ BUUD POINIS-


• ArrayList isa class inthe Java API.
Where'd that 'x' come from?
• To put something into an ArrayUst. use addD,
(or, what does it mean when
a package starts with Javax?) • To remove something from an ArrayUst use
r&moveD·
In the first and second versions of Java (1.02
and 1.1), all classes that shIpped with Java (In • To find outwhere something is (and If it is) in an
other words, the standard library)were In packages ArrayUst, use indexOfO.
that began wlthJava.There was alwaysjllva.lang, of course
- the one you don't have to import. And th ere was jlllla.netl • To find outif an ArrayUst is empty, use
jOl/a,/o,java.util (although there was no such thing as ArrayList IsEmpfyQ.
way back then), and a few others, Including the ja va.aWl
package that held GUI-related classes. • To get the size (number ofelements) in an
ArrayUst. use the sizeD method.
Looming on the horizon, though, were other packages not
Included in the standard library.These classes were known as • To get !he length (number of elements) ina
extensions, and came in two maInflavors: standard, and not regular old array. remember, you use the length
standard. Standard extensions were those that Sun considered variable.
official,as opposed to experimental, early access, or beta
packages that might or mIght not ever see the light of day. • An Arraylist res1z&s dynamically to what-
Standard extensIons, by convention, all began with an 'x' ever size is needed. It grows when objects
appended to the regular java package starter. The mother of all are added, and it shrinks when objects are
standard extensions was the Swing library. It Included several removed.
packages, all of which began with jallax.swlng.
• You declare the type of the array using a type
But standard extensions can get promoted to first-class,shlps-
parameter, which is a type name in angle
wIth-Java,standard-out-of-the-box library packages. And that's
what happened to Swing,beginning with version 1.2 (which brackets. Example: ArrayList<8utton> means
eventually became the first version dubbed 'Java 2') . the ArrayUst will be able to hold only objects of
type Button (or subclasses ofButton asyou'll
MCool: everyone thought (Including us).~Now everyone who has
Java will have the SwIng classes, and we won't have to figure learn in !he next couple ofchapters).
out how to get those classes Installed with our end-users: • Although an ArrayUst holds objects and not
Trouble was lurking beneath the surface, however, because primitives, the compiler will automatically "wrap.
when packages get promoted, well of COURSE they have to (and ·unwrap· when you take It out) a primI-
start wlthjalla, notjavax. Everyone KNOWS that packages In tive into an Object, and place that object Inthe
the standard library don't have that "lC: and that only extensions ArrayUst Instead of the primitive. (More on this
have the "x~ So,Just (and we mean Just) befo re version 1.2
feature later in the book..)
went final, Sun changed the package names and deleted the
"x· (among other changes). Bookswere printed and In stores • Classes are grouped into packages.
featurIng SWing code with the new names. Naming conventIons
were intact. All was right with the Java world. • Aclass has a full name, which isa combina-
Except the 20,000 or so screaming developers who realized tion of the package name and the class name.
that with that simple name change came dlsasterl All of their Class ArrayList is really java.utiIArrayUst.
Swing-using code had to be changedl The horrorl ThInk of all
• To use a class in a package other than java.
those Import statements that started wlthjavCDf...
lang, you must tell Java the full name of the
And In the flnal hour, desperate, as their hopes grew thin, the class.
developers convInced Sun to "screw the convention, save our
code" The rest Is history. So when you see a package In the • You use either an Import statement atthe top of
library that beglns with Javax, you know It started life as an your source code, oryou can type the full name
extension, and then got a promotion. every place you use the class in your code.

156 chapter 6
get to know the Java API

Q.: D06S import make my


class bigger? Does It actually
compile the imported class or
package Into my code7
N/ale~ if. oStit.1e
A: Perhaps you're a C pro-
grammer? An import is not the
Roses arered
apples areri;e.
same as an include. So the ifyou don't im;on
answer is no and no. Repeat after You 'lljust have t
c otYpe
rne.ran import statement saves
you from typing:That's really It. Youmust tell Java
you use, unle the full name of ev
You don 't have to worry about packag A s.s that class is in til ' ery class
your code becom ing bloated, or e. n lmport Sf e Java.lang
slower, from too many Imports. or packageat the to f atement for the class
An i mport is simply the way you easyway. OtherWise~~ ~our sourceCode is the
give Java the full name of a class. name of the class, e:e~h ave to type the fUll
. ere you use it!

Q: OK, how come I never had


to import the String class? Or
One more time, in the unlikely
System?
event that you don't already
have this down:
A: Remember, you get the
java.lang package sort of·pre-
Imported" for free. Because
the classes In [ava.lanq are so
fundamental, you don't have to
use the full name.There Is only
one java.lang.Strlng class,and one
[ava.tanq.System class,and Java
darn well knows where to find
them.

Q: Do I have to put my own


classes Into packages? How do I
do that? Can I do that?

A..: In the real world (which


you should try to avoid), yes, you
wl/l want to put your classes Into
packages. We'll get into that in
detail In chapter 16. For now, we
won 't put our code examples In a
package.

you a re he re . 157
getting to know the API

"Good to know there's an ArrayList in


the java.util package. But by myself, how
would 1 havefigured that out?"
- Julia, 31, hand model

How to play with the API


Two things you want to know:

o What classes are In the library?

e Once you find a class, how do


you know what It can do?

o Browse a Book

e Use the HTML API docs

. . . .1_..
I " ... 0 .

_USJl
&G!.~
e..
... . . ..
o..n-wo....zPIal. ... 51: l.O1
+ ~ ~t/Jlot&-Il.A (OMIIl 'ftl .',O/ _IJ ~1

~, ..-. .........
E'IlIiIIlIPocuoo C., UU JJlN ~ nIn tlAlD

Jav,,'" 2 P1IItlormStaodard Edlllon 51)


O ~·~Q.· '-

J"""'~
~U Hi
-
...... -¥~,., ;,,: i

-- . . - API SpedtblloD

- 1- IoAClM_ 'Nt - . . . Is'" API _ _ (00 "" b ... , Pbtl..... S<a\.ooIrod•.., 1,0

Ila<dIIJIoIl

JAVA --
Nnlr!cI".!ffIU
J8va 2 P18t1orm hcbgcs
N"1!rW1">"9'T"1 P'Jl.wtdca IIlc d ...~ 1lC'CD""' ~l nc. . . ~ .....
ANeJIChQ"""", C9ntr.i IIu.I.oPI<l c~u.~tan .,COl['IIamCC "lib b ~
","""l.

INANUTSHELL
6CID:!lraCr=
/IW..nJ
_ .et. . .
CmWM aDat Iht daun lar ClQlilt DID~ arid b
...-. JnliIIct1lOI 1m>;n.

... .
f«coInf ___•
......u.ab:
iIIlIIICUI
f'roo'Iotic" ~ ~ d:lUl:f for ttll:).ran.' .im t:w:r-tcII ~
~.
~ lnll>I",
Ii CX:sJdop Quick RI!jlf'l:llce

O'REillY'

158 ch ap ter 6
get to know the Java API

IJAVA
''?''!!!@I'
}twa ,utU,ClUnmcy

R,/JUJUId Bj~ IN.ltU1lleeImalFaT1lat#lCun8lctO.IM,te:l1-~malf~o.mncyO.


J-.l8ItN~eum:lley(I . O:JtnlllCY'~

Date

This d:I5:l represents dates and limes 2nd leu you ...·o rk with them in ~ ~em-ind~pen­
den! way , You C:1n create a D8l& by specityina the number of m1Diseconds (rom the
epoch (audf\is/11 GMT. J:>nw<y 181. 1970) or We year. month, date, and, oplional1)', th e
hour. m1nUle, llrld second. Yo,.. are 5p<'cilied as the number of fC"'lS since 1900, If you
call the Dale construClor wilh no "'BWDCfIlS. the OIIe ts ini riJn:z...d 10 the current time
J11d dJ'e. Tht Insunce runhods of the class .110"" you 10 get :lOd se t the \':l(iOll~ UJI"
and lim e fields, (0 compare mid "nd umes, and '0 convert da tes to 2nd from SIring
n:prcscnulio"" 11:> of J'V> 1.1, = ) ' or the dale metho<b bave been deprecated in
fa\ 'Or of th e me thods of the calendar cl.....

PiUc dass Oila iIIpltments ctonUblt. Coml*;tblt; Sedllriille I


II Mil; ~strucl:lrs
IUbllc Dm():
~leD~r. ct.lle):
, iiiIl1t o.tt(SlJireI);
, lIUbIlcD m..lIllye.v, lnlmonlft, IIIlct.l f!):
, PliIIlclllWCiI1ltw,lnlllll:'l ,liIl dlle. lnlhn,inl t*l;
, pUllIlc DItIl(lr>I ye¥, lnl /llMlII, lnlttaDl. lnllirs. Int mil, tnt sec):
II Piijiiifj~S{l(1rIer1t4df (tj ~ -J
~It Itr( e-t1llMl):
IdiIlt will MtTIIM(Ion&1tIIe):
7/ JljibJ; IiiSfiiiij MilIiOili
public boomn aftal\lmJJ1lLIl8:t . , ):
. II\iIllcbooIelI\hhlr-aM.UliLDiIl'-);
1.1publicInt c-..N1To11m.uDI.DJI'~Irllat,}:
ll lIiI1JDiif~~~
1.1putIIlc In! _PANTo(ObjtCl 0):
II JIlIbIi: j,jeth6ill ~0l;Id
1.1 pulIIlc 0lijtcI doN( I:
puliIic b09Iear! .q.II(OijIlc:l «II:
IdiI lcIIIl••1Ie.c1e():
PliIII~Sllitl(toStrlDiO; .
II ~ WPubic lIe~
, llWIlC irt 1I!tI!at1():
, ~ic Int,.0.,0:
, puliIic IIIptHoan/):
, puliIlc IntptMlllCIttI():
, ~~lnt ~d();
, pWlc Int,.S aMI(J:
, pUblic rt 1itI'IMIo..otfiit(1:
'~ltlnt"""l():
• liibIlclll~clq,.lM(S1(IrcJ);
, pJlllc'/Old utDat-r1fll dlIIlI):
, lIulill~ iOId iittIilIrI('llllllOurl);
, lQlillcvoIdMtMl~nlllllilwl8s):
, ~lc'lOliI ~ntllDllII);

you are here) 159


using the Java API documentation

e Use the HTML API docs


Java comes with a fabulous set of online docs The reference book, for example, tells you
called , strangely, the Java API. They're part of what the methods take, as arguments, and what
a larger set called the Java 5 Standard Edition they return. Look at ArrayList, for example.
Documentation (which, depending on what In the reference book. you'll find the method
day of the week you look, Sun may be refer- index Of'(}, that we used in the DotCom class,
ring to as "Java 2 Standard Edition 5.0"), and But if all you knew is that there is a method
you have to download the docs separately; called indexOf() that takes an object and re-
they don't come shrink-wrapped with the Java turns the index (an int) of that object, you still
5 download. If you have a high-speed internet need to know one crucial thing: what happens
connection, or tons of patience, you can also if the object is not in the ArrayList? Looking
browse them at java.sun.com, Trust us. you at the method signature alone won't tell you
probably want these on your hard drive. how that works, But the API docs will (most of
the time, anyway). The API docs tell you that
The API docs are the best reference for get- the indexOff) method returns a -1 if the object
ting more details about a class and its methods. parameter is not in the ArrayList. That's how
Let's say you were browsing through the refer- we knew we could use it both as a way to check
ence book and found a class called Calendar, if an object is even in the ArrayList, and to get
in java.util , The book tells you a little about it, its index at the same time , if the object was
enough to know that this is indeed what you there. But without the API docs, we might have
want to use, but you still need to know more thought that the indexOf() method would
about the methods . blow up if the object wasn't in the ArrayList.

boolNA .tdlM1.1(rp))eCt(PDcr .n...o.d.. c:' e)


Appilrod' >IJ of lbo C~1S In the <pcci1kd Col lccrlon 10 do: <lid 0( 1IIlJ!lSI. In
lIlc Olderdill. dley lite teI1lmCd by lIlc spcd{1ed CollccOOt>', ItcralQT.
tloOoQl. u .I44I.llf hot. .1..1:I4 •• 1 Co)) lOt iQa<) Qt._tlds P (III
1Jumj all r>ilIlc d<ma!1J in !be <pcd/ltd Collcctloo!n1O Ihi> hst, stuIing 4I1llC
<nccif1n1 nndrinn

160 chapter 6
get to know the Java API

Code Magnets a.remove(2); pri.ntAL (a) ;


Can you reconstruct the code snippets to make a
working Java program that produces the output
listed below7 NOTE: To do this exercise, you need a .add(O I " zero").
a _.....-oz-I one NEW piece of info-If you look in the API for
a.. add (1 " ,
ArrayList,you'll find a secondadd method that takes , one"),.
two arguments:
.';;;~.jiI:
"- lIdd(lnt Index. Object 0) public static void printAL (ArrayList<String> al) (
It lets you specify to the
Arrayl.lst where to put the object you're adding . if (a
. Contains ("brO"
&.add ( " 2 . 2 " ) ; » (
)

public static void main (String[]

System.out.print(eleme.nt +" ") ;


)
Syst.em.out.println(" ");

(a. contains ("three"»


a.add("fourn)i

public class ArrayListMagnet

if (a .indaxOf("four") !=
a.add(4, "4.2");

import java. ut i l.*;

printAL (a) ;

ArrayList<String> a = new ArrayL

for (String e1............-


~t:

3 "three") i
a.a dd( J

printAL(a) ;

you are here . 161


puzzle: crossword

JavaOr~ss t. O
How does this crossword puzzle help you learn
Java 7 Well,all of the words are Java related
(exceptone red herring).
HInt: When In doubt, remember ArrayUst.

Aaoss
1. I can't behave
6. Or, In the courtroom
7. Where It's at baby
9. A fork'sorigin Down
12. Grow an ArrayUst 2. Wherethe Java action Is.
13. Wholly massive 3. Addressable unit
14. Value copy 4. 2nd smallest
16. Not an object 5. Fractional default
17. An arrayon steroids 8. Ubrary'sgrandest
19, Extent 10. Must be low density
21. 19'scounterpart 11. He's In there somewhere
22, Spanish geek snacks (Note: This has 15. As if
nothing to do with Java)
16. dearth method
23. For lazyfingers
18. Whatshopping and arrays haveIn common
24. Wherepackages roam
20, Ubrary acronym
21. What goesaround

More Hints:
--1l6UI~IlWS.ill-l ·81 sJ~ladde 4SIUIldS' 1!hIl( l/1oqe ION 'U
lSn,(IlJJv l(U!ll..L '9 1 IUillXds•.(IlJJV' IZ
ilhll!W!!d '01 ~ 'to' ~w!Jd UOWWO) '91
lSn.<eJJy l(U!ll..L 'E ISn'<WY'lUI'lJ. 'L
lillqllP!JJahO S,lllllM ' Z 5a!liljJRh 8 ' I
uMO(J stoJ:lV

162 chapter 6
get to know the Java API

import java. uti!. * i I


public class ArrayListMagnet
( II
I public static void main (Strinq[] arqs) (I
I ArrayList<Strinq> a = new ArrayList<String>()i l
a.add(O,HzerOn)i
a.add(l,"one")i

a.add(2,"twO")i

a.add(3,"three")i
printAL (a) i

if (a.contains ("three"» (
a.add("four")j
)

a. remove (2) i Ie
printAL (a) i . .
..
if (a. indexO£ ("four") != 4) (
a .add(4, "'4.2")i
}

printAL (a) ; ..

if (a.contains("two"» {
a.add("2.2")i
}
printAL (a) ; ..

[r II'

I public static void printAL(ArrayList<String> a1) {r


for (Strinq element : al) (

System. out. print (element + " ") ;


)

ofll- System.out.println(" \\} ;

you are here ~ 163


puzzJe answers

JavaOrctSS
answers

~ your re::,~e you. OWN set of cluesl Lookat each word , and "y to
write your own clues. Try making them easier,or harder, or
Aaoss more technical than the ones we have.

I.
6. Down
7. 2
9. 3.
12. 4.
13. 5.
14. 8.
16. 10.
17. II.
19. 15.
21. 16.
22 18.
23. 20.
24. 21.

164 chapter 6
7 inheritance and polymorphism

We were underpaid,

Better Living in overworked coders 'fill we


tried the Polymorphism Plan. But

Objectville thanks to the Plan, our future is


bright. Yours can be tool

Plan your programs with the future in mind. If there were a way to write
Java code such that you could take more vacations, how much would It be worth to you? What
if you could write code that someone else could extend, easily? And if you could write code
that was flexible, for those pesky last-minute spec changes, would that be something you're
interested In?Then this is your lucky day. For Just three easy payments of 60 minutes time , you
can have all this. When you get on the Polymorphism Plan, you'll learn the 5 steps to better class
design, the 3 tricks to polymorphism, the 8 ways to make flexible code, and if you act now-a
bonus lesson on the 4 tips for exploiting inheritance. Don't delay, an offer this good will give
you the design freedom and programming flexlbll lty you deserve. It's quick. it's easy, and it's

available now. Start today, and we'll throw in an extra level of abstractionl

this is a new ch ap ter 16i


the power of inheritance

Chair Wars (evisited...


Remember way back in chapter 2, when Larry (procedural guy)
and Brad (00 guy) were vyingfor the Aeron chair? Let's look at
(J few pieces of that story to review the basics of~.

LARRY: You've got duplicated codel The rotate procedure


is in all four Shape things. It's a stupid design. You have [0
maintain four different rotate "methods". How can that
ever be good?
BRAD: Oh, I guess you didn't see the final design. Let me
show you how 00 inheritance works, Larry.

Square Amoeba
o
Ilooked at what all four
rotateQ
playSoundO
rotateO
playSoundQ
rotate()
playSoundO
classes have I" OOIMIIIO".
~

rhev're Shapes, and they all rotate and shape


plavSound. So IabstraGted out the rotateQ
COIMIMon features and put thelllinto a playSound()
ttew class called Shape. -:;, Shape
superclass rotale()
playSoondO

You can read this as, uSquare Inheritsfrom Shape".


"Circle Inheritsfrom Shape", and so on. I removed
(olale() and playSound() from the other shapes, so now
~here's only one copy to maintain.
Square Circle Triangle
Th&.~hape class Is called the luperciasl of the other four
classes. The other four are the lubelaues of Shape. The
SUbclasses Inherit the methods of the superclass. Inother
words. Ifthe Shape class has the (unci/anality, then the
subclasses automatically gatfhat same functionality.

166 chapter 7
inheritance and polymorphism

What about the AIMoeba rotate()?


LARRY: Wasn't that the whole problem here - that the amoeba shape
had a completely diffe rent rotate and playSound procedure?
How can amoeba do something different if it inherits irs
functionality from the Shape class?
BRAD: That's the last step. The Amoeba class overrides the
methods of the Shape class. Then at runtime, the JVM knows
exactly which rota/eO method to run when someone tells the
Amoeba to rotate.

superolau
"MOre autract)
~
Shape

rotateQ
playSoundO
o
lubclasses
"MOre speolflol

\ Square Circle Tilangle Amoeba

rotateO

'"
/I amoeba-specific
/I rotate code
playSoundO
!<" OverrldlnQ lMethods
II amoeba-speclfic
II sound code

How would you represent a house cat and a tiger. In an


inheritance structure. Is a domestic cat a specialized
version of a tiger? Which would be the subclass and
which would be the superclass? Or are they both
subclasses to some other class?
How would you design an Inheritance structure? What
methods would be overridden?
ThInk about It. Before you tu rn the page.

yo u are h er e ~ 167
I way inheritance works

Ut1derstat1dit1Q Inheritance
When you design with inheritance, you put common code in
a class and then tell other more specific classes that the
common (more abstract) class is their superclass. When one
class inherits from another, the subclass inherits frOID the
superclass.
InJava, we say that the subclass extends the superclass.
An inheritance relationship means that the subclass inherits
the lDelDbers of the superclass, When we say "members of
a class" we mean the instance variables and methods.
For example, if PantherMan is a subclass of SuperHero, the
PantherMan class automatically inherits the instance variables
and methods common to all superheroes including sui t,
tights, specialPower, useSpecialPower () and
so on. But the PantherMan subclass can add new
:methods and instance variables of its own, and it can
override the :methods it inherits fro:m the superc1ass
SuperHero.

superclasa SuperHero
(tHore abstract) sul1
I"sta"ce varIables
lights
~ spec/alPower (state. attributed
useSpecialPower() lMethods
putOnSull() (behavIor)
subclasses
(tHore speolfle) /~
~ FriadEggMan
PantherMan OverrldfttQ
if !Methods
. lJ,v4' useSpeclalPowerij
:;. t"
t( putOnSultO ~

FriedEggMan doesn't need any behavior that's unique,


so he doesn't override any methods. The methods and
instance variables in SuperHero are sufficient.
PanthenMan, though, has specific requirements for his suit
and special powers, so useSpecialPower () and
putOnSui t () are both overridden in the PantherMan
class.
Instance variables are not overridden because they
don't need to be. They don't define any special behavior, so a
subclass can give an inherited instance variable any value it
chooses. PantherMan can set his inherited tights (0
purple, while FriedEw\1an sets his to white.
~ chapter 7
inheritance and polymorphism

public class Doctor {

boolean worksAtHospita1i

void treatPatient() [
II perform a checkup

public class FamilyOoctor extends Doctor {

boolean makesHouseCallsi
void giveAdvice(} {
II give homespun advice

public class Surgeon extends Doctor(

void treatPatient () (
II perform surgery

void makeIncision() (
II make incision (yikes!)

superclass
your pencU
Doctor How many instance variables does
worksAlHosptlal OMe '"stattce variable Surgeon have7_ _

treatPatient 0 otte tMethod How many Inslance variables does


FamiryDoctor have7_ _

How many methods does Doctor have?_ _


subclasses How many methods does Surgeon have?_

How many methods does FamilyDoctor


Surgeon FamllyDoctor have7 _ _
Adds one new
Ovenides the Inherited makesHouseCal1s
Instance variable
lrealPaUenlQ method lreatPatlenl () Can e FamllyDoctor dolreatPatient()? _ _
glveAdvlce 0 Adds one new method
Adds one new method makelnclslonO Can a FamllyDoctor do rnakelneisloru)? _ _

you are here ~ 169


Let"s desig" the it1heritattce tree for
att Atti~al sitltulatiot1 progralM
Imagine you're asked to design a simulation program that
lets the user throw a bunch of different animals into an
environment to see what happens. We don't have to code the
thing now, we're mostly interested in the design.
We've been given a list of someof the animals that will be
in the program, but not all. We know that each animal will
be represented by an object, and that the objects will move
around in the environment, doing whatever it is that each
particular type is programmed to do .
And we want other programmers to be able to add new
kinds of animals to the program at any time.
First we have to figure out the common, abstract
characteristics that all animals have, and bu ild those
characteristics into a class that all animal classes can extend.

o Look for objects that have common


attributes and behaviors.
What do these six types have In
common? This helps you to abstract
out behaviors. (step 2)

How are the~ types related? This


helps you to define the Inheritance
tree relationships (step 4-5)

170 chapter 7
Inheritance and polymorphism

Usi.,g i.,herita.,ce to avoid


duplicatit1Q code it1 subclasses
We have five instance variables:
pidure- the file name representing theJPEG of this animal Design a class that represents
food - the type offood this animal eats, Right now, there the common state and behavior.
can be only 1:\'10 values : meat or grass.
The~ objects are all animals, so
hunger- an int representing the hunger level of the animal. we'll make a common super-class
It changes depending on when (and how much) the called Animal .
animal eats. We'll put In methods and instance
boundaries - values representing the height and width of variables that all animals might
the 'space' (for example, 640 x 480) that the animals will need.
roam around in.
location> the X and Y coordinates for where the animal is Animal
in the space.
picture
We have four methods: food
hunger
makeNoUe 0 - behavior for when the animal is supposed to
boundaries
make noise. location
eatO- behavior for when the animal encounters its
preferred food SOUTee, meat or grass. makeNoiseO
eatO
skepO - behavior for when the animal is considered asleep. sleept)
roam() - behavior for when the animal is not eating or roamt)
sleeping (probably just wandering around waiting to bump
into a food source or a boundary) .

LIon

Wolf

HIppo
Dog

you are here ~ 171


designing for inheritance

Po all at1httals eat the saIMe way?


Assume that we all agree on one thing: the instance
variables will work for aUAnimal types. A lion will
have his own value for picture, food (we're thinking
meat), hunger, boundaries, and location. A hippo
will have different values for his instance variables,
but he'll still have the same variables that the other Decide if a subclass
Animal types have. Same with dog, tiger, and so on. needs behaviors (method
Butwhatabout~h~~ implementations) that are specific
to that particular subclass type.

Which 'Methods should we override? looking at th£ Animal class,


w£ decide that eatQ and
Does a lion make the same noise as a dog? Does makeNolseO should be overridden
a cat eat like a hippo? Maybe in youTversion, but by the Individual subclasses.
in ours, eating and making noise are Animal-type-
specific. We can't figure out how to code those
methods in such a way that they'd work for any
animal. OK, that's not true. We could write the
rnakeNoise() method, for example, so that all it does
is playa sound file defined in an instance variable
for that type, but that's not very specialized. Some In the dog
animals might make different noises community, barking is an
for different situations (like one important part of our cultural
for eating, and another when identity. We have a unique sound,
bumping into an enemy, etc.) and we want that diversity to
So just as with the Amoeba be recognized and respected.
overriding the Shape class rotateO
method, to get more amoeba-specific (in
other words, unique) behavior, we'll have
to do the same for our Animal subclasses.

Animal
picture
food
hunger
boundaries
location

sleepf)
roamO

172 chapter 7
Inheritance and polymorphism

Looklt1Q for more it1heritat1ce


opportut1itles
The class hierarchy is starting to shape up. We
e
Look for more opportunities to use
have each subclass override the makeNoise() and abstraction, by finding two or more
eat() methods, so that there's no mistaking a Dog subclasses that might need common
bark from a Cat meow (quite insulting to both behavior.
parties). And a Hippo won't eat like a Lion.
But perhaps there's more we can do. We have to
We look at our classes and see
that Wolf and Dog might have some
look at the subclasses of Animal, and see if CWo behavior In common, and the same goes
or more can be grouped together in some way, for Lion, Tiger, and Cat.
and given code that's common to only that new
group. Wolf and Dog have similarities. So do
Lion, Tiger, and Cat.

Animal
picture
food
hunger
boundaries
location

Lion

Wolf

Hippo
Dog
mekeNolseO
makeNoiseO eatO
eatO
·~IIIII!IIl"'_rlmakeNolseO
eatO

you are here) 173


designing for inheritance

Finish the class hierarchy


Since animals already have an organizational Animal
hierarchy (the whole kingdom, genus, phylum
thing), we can use the level that makes the most picture
sense for class design. We'll use the biological food
"families" to organize the animals by making a hunger
Feline class and a Canine class. boundaries
location
We decide that Canines could use a common
roomO method. because they tend to move In
packs. We also see that Felines could use a
common raamO method, because ther tend to sleept)
avoid others of their own kind. We'l let Hippo
continue to use Its Inherited roamO method-
the generic one It gds from Animal.
So we're done with the: deSign for now:
come back to It later In the chapter.

mem()

mamO

makeNolseO
6810

makeNolseO
eatO

Cat

TIger
makeNolseO
makeNolseO Wolf eatO
e.atO
makeNolseO
eat()
makeNolse()
eatO

174 chapter 7
inheritance and polymorphism

Which tttethod Is called?


The Wolf class has four methods. One
inherited from Animal, one inherited from
Canine (which is actually an overridden
version ofa method in class Animal), and
two overridden in the Wolf class. When
you create a Wolf object and assign it to
a variable, you can use the dot operator
on that reference variable to invoke all
Anima'
four methods. But which version of those
methods gets called? makeNolseO
eatO
sleepO
roarnr)
Wolf w = new Wolf () ;

tails t.he version in Wol.f w .makeNoise () ;

w. roam () i Canine

roamO
talls t.he v~ion in Wol.f w.eat();

talls -the version in Ani...al w. sleep () ;

When you call a method on an object


Wolf
reference, you're calling the most specific
version of the method for that object type.
In other words, the lowest one wins!
"Lowest" meaning lowest on the
inheritance tree. Canine is lower than
Animal, and Wolf is lower than Canine,
so invoking a method on a reference
to a Wolf object means the JVM starts
looking first in the Wolf class. If the JVM
doesn't find a version of the method in
the Wolf class, it starts walking back up
the inheritance hierarchy until it finds a
match.

you are here ~ 175


practice designing an inheritance tree

PeslgttiMQ aM InherltaMce free suparclass


hMore abstract) ~
~ L..:::..J
Class
Clothing
Boxers
Superclasses
--
Clothing
Subclasses
Boxers, Shirt subelaases
(lttore tpeolflol
I ~
'\.

Shirt Clothing ~ Box,," ~


Inherftance Table
Inheritance CIUlI Diagram

'-..:
~~
I l Sharpen your pencil Draw an inheritance diagram here.
Find the relationships that make sense. Fill In the last two columns

Chus Superclasses Subclasses


Musician
Rock Star
Fan
Bass Player
Concert Pianist

Hint: noteverythIng can beconnected to something else.


Hint: you're allowed to add to or change the cl8SSes listed.

therejltrer\l?
DUmb ~uesti9n.8

Q.: You said that the JVM starts


walking up the Inheritance tree,
A.: Good questionl But you don't
have to worry about that.The compiler
Where the inherited method Is defined
(In other words, In which superclass
starting at the class type you Invoked guarantees that a particular method It Is defined) makes no difference to
the method on (like the Wolf example Is callable for a specific reference type, the complier. But at runtIme, the JVM
on the previous pagel. But what but It doesn 't say (or care) from which will always pick the right one. And
happens If the JVM doesn't ever find class that method actually comes from the right one means, the most specific
ill match? at runtime. With the Wolf example, the version for that particular object.
compiler checks for a sleepf) method,
but doesn't care that sleepO Is actually
defined In (and Inherited from) class
Animal. Remember that If a class
Inherits a method, It has the method.

176 chapter 7
Inheritance and polymorphism

UsittQ IS...Aattd HAS-A


Remember that when one class
inherits from another, we say that the
subclass extends the superclass. When
you want to know if one thing should
extend another, apply the IS-A test,
Triangle IS-A Shape, yeah, that works. Does it make sense to
Cat IS-A Feline, that works too . say a Tub IS-A Bathroom? Or a
Surgeon IS-ADoctor, still good. Bathroom IS-A Tub? Well it doesn't to
Tub extends Bathroom, sounds me. The relationship between my Tub
reasonable. and my Bathroom is HAS-A. Bathroom
UntilyO'u apply 1M IS-A test. HAS-A Tub. That means Bathroom
To know if you've designed your types has Q Tub instance variable.
correctly, ask, "Does it make sense to
say type X IS-A type Y?" If it doesn't,
you know there's something wrong
with the design, so ifwe apply the IS-A
test, Tub IS-A Bathroom is definitely
false.
What if we reverse it to Bathroom
extends TUb? That still doesn't work.,
Bathroom IS-ATub doesn't work.
Tub and Bathroom are related, but
not through inheritance. Tub and
Bathroom are joined by a HAS-A
relationship. Does it make sense to
say "Bathroom HAS-ATUb"? If yes,
then it means that Bathroom has a
Tub instance variable. In other words,
Bathroom has a reference to a Tub, but
Bathroom does not extend1\lb and
vice-versa.

Tub
Inl size:
Bathroom Bubbles b:
Tub bathtub; Bubbles
Sink lheSink; inl radius:
Inl oolorAm~

Bathroom HAS-A Tub and Tub HAS-A Bubbles.


Bul nobody Inherits from (extends) anybody else.

you are here ~ 177


exploiting the power of objects

Jut wait! There"s 'More!


The IS-A test works anywhere in the inheritance tree. If your
inheritance tree is well-designed, the IS-A test should make
sense when you ask any subclass if it IS-A any of i IS su pertypes.

If class B extends class A, class B IS-A class A.


This is true anywhere in the inheritance tree. If
class C extends class B, class C passes the IS-A
test for both Band A.

Canine extends Animal Animal With an inheritance tree like the


one shown here, you're always
Wolf extends Canine makeNolseO allowed to say "Wolf extends
eatO Animal" or "Wolf IS-A Animal".
Wolf extends Animal sleepO
roamO It makes no difference if Animal
is the superc1ass of the superclass
of Wolf. In fact, as long as Animal
Canine IS-A Animal is somewhere in the inheritance
hierarchy above Wolf, Wolf IS-A
Wolf IS-A CanIne
Animal will always be true.
Canine
Wolf IS-A Animal The structure of the Animal
inheritance tree says to the world:
roarnt)
"Wolf IS-A Canine. so Wolf can do
anything a Canine can do. And
Wolf IS-AAnimal, so Wolf can do
anything an Animal can do."
It makes no difference if Wolf
overrides some of the methods
Wolf in Animal or Canine. As far as
the world (of other code) is
makeNolseO concerned, a Wolf can do those
eal() four methods. H(JlJ) he does them,
or in which class they 1'e overridden
makes no difference. A Wolf can
makeNoise O. ea to, sleep (), and
roamO because a Wolf extends
from class Animal.

178 chapter 7
Inheritance and polymorphism

I lets are blUe. . 't true.


Roses are red, v 0 the reverse lsn
""a is-aShape,
SqU- d r
d laletS are ell. beer.
Roses are re vI t 01/ drinks are
How do you k"ow if yotfve got Beer is-a Dr,
Ink but no e-
'" t shOWS the on 'f
M Ke one t"a . Remember. \
QI(, your turr\e~S_A relatiOnshlP~ense,
your htherita"ce right? way.nesS of ~ 'S.A'( must maKe
There's obviously more to it than what we've '/.. extend_s_'(I_ ------".......... --~"........-
covered so far, but we'll look at a lot more 00
issues in the next chapter (where we eventually
refine and improve on some of the design work
we did in this chapter) .
For now. though, a good guideline is to use the
Sharpen your pencil------,
IS-A test, U "X IS-AY" makes sense, both classes
(X and Y) should probably live in the same Put a check next to the relationships that
inheritance hierarchy. Chances are, they have make sense.
the same or overlapping behaviors.
Keep in mind that the o Oven extends KItchen
inheritance IS-A relationship o Guitar extends Instrument
works in only one directionl o Person extends Employee
Triangle IS-A Shape makes sense, so you can
have Triangle extend Shape.
o Ferrari extends EngIne
But the reverse-Shape IS-ATriangle-does o FriedEgg extends Food
not make sense, so Shape should not extend
Triangle. Remember that the IS·A relationship
o Beagle extends Pet
implies that if X IS-A y. then X can do anything o Container extends Jar
a Y can do (and possibly more).
o Metal extends Titanium
o GratefulDead extends Band
o Blonde extends Smart
o Beverage extends Martini

Hint apply the IS-A test

you are here ~ 179


who inherits what

therelllreAl~
Dum D "<.,uesD9ns
Q: SO we see how a subclass gets
Q: In a subclass, what if I want to
to In herlt a superclass method, but You can design your superclass
use BOTH the superclass version and
what If the su perclass wants to use methods in such a way that they
my overriding subclass version of a
the subclass version of the method1 contain method implementat ions
method? In other words, I don't want
that will work for any subclass, even
to completely rep/Dee the superclass
A.: A superclass won't necessarily
know about any of its subclasses .
version, I Just want to add more stuff
to It.
though the subclasses may still need
to 'append' more code . In your subclass
overriding method, you can call th e
You might write a class and much superclass version using the keyword
later someone else comes along and super. It's like saying,"first go run the
A:vou can do this! And It's an superclass version. then come back and
extends it. But even Ifthe superclass
important design feature .Thinkof the finish with my own code ..,"
creator does know about (and wants
word "extends" as meaning,"1 want
to use) a subclass version of a method,
to extend the functionality of the
there's no sort of reverse or backwards
su perclass"
inheritance. Think about it, children
public void roamC)
Inherit from parents, not the other way
super. roam C) ;
around.
/ / my own roam

Who gets the Porsche, who gets the porcelah,? Access levels control who sees what, and are crucial
(how to kt'ow whata subclass cat' to having well-designed, robust Java cod e. For now we'll
Itt"erlt frolM Its superelassJ focus just on public and private. The rules are simple for
thos e two:
A subclass inherits members of the
superclass. Members include instance
variables and methods, although later in
--
public members are Inherited
private members are ~ Inherited

this book we'Dlook at other inherited members. A


superclass can choose whether or not it wants a When a subclass inherits a member, it is as if the
subclass to inherit a particular member by the level of subclass defined the -member itself. In the Shape
access the particular member is given. example, Square inherit ed the rotate () and
playSound () methods and to the outside world (othe r
There are four access levels that we'D cover in this book. code) the Square class simply has a rota te () and
Moving from most restrictive to least , the four access playSound () method .
levels are: The members of a class include the vari ables and
private default protected public methods defined in the class plu s anything inherited
from a superclass.

No-«: get ..O\"C ddails about dc+alAlt and fl"ot.et.ud in 'h4y-W-


Ib (dcrl0't"cnV and .li'fcNli'J< B.
180 chap ter 7
Inheritance and polymorphism

When designing with inheritance,


are you usit1g or abusi"g?
Although some of the reasons behind these rules won't be
revealed until later in this book, for now, simply knowing a
few rules will help you build a better inheritance design.

DO use inheritance when one class is a more specific type


ofa superclass. Example: WIllow is a more specific type of
Tree, so Willow extends Tree makes sense.

DO consider inheritance when you have behavior


(implemented code) that should be shared among • A subclass extends a superclass.
multiple classes of the same general type. Example:
Square, Circle, and Triangle all need to rotate and play • A subclass Inherits all public Instance
sound, so putting that functionality in a superclass Shape variables and methods ofthe superclass, but
might make sense, and makes for easier maintenance and does not Inherit the private Instance variables
extensibility. Be aware, however, that while inheritance is and methods ofthe superdass,
one of the key features of object-oriented programming,
• Inherited methods can be overridden; instance
it's not necessarily the best way to achieve behavior reuse.
vartables cannot be overridden (although they
It'll get you started, and often it's the right design choice, can be redefined in the subclass, but that's
but design panerns will help you see other more subtle not the same thing, and there's almost never a
and flexible options. !fyou don't know about design
need todo it)
patterns, a good follow-on to this book would be HeadFirst
Design Patterns. • Use the IS-A test to verify thaiyour
inheritance hierarchy is valid. If X extends Y,
then X IS-A Ymust make sense.
DO NOT use inheritance just so that you can reuse
code from another class, if the relationship between the • The rS-A relationship works In only one
superclass and subclass violate either of the above two direction. A Hippo is an Animal. but not all
rules. For example, imagine you wrote special printing Animals are Hippos.
code in the Alarm class and now you need printing code • When a method isoverridden ina subclass,
in the Piano class, so you have Piano extend Alarm so that and that method isInvoked on an instance of
Piano inherits the printing code. That makes no sense! A the subclass, the overridden version of the
Piano is rwt a more specific type of Alarm. (So the printing method is called. (The lowest one wins.)
code should be in a Printer class, that all printable objects
can take advantage of via a HAS-A relationship.) • Ifclass B extends A, and C extends B, class
B IS-A class A, and class C IS-A class e, and
class C also IS-A class A.
DO NOT use inheritance if the subclass and superclass
do not pass the IS-A test, Always ask yourself if the subclass
IS-A more specific type of the superclass. Example: Tea IS-
A Beverage makes sense. Beverage IS-ATea does not.

you are here) 181


exploiting the power of objects

So what does all this


h1herita"ce really buy you?
You get a lot of 00 mileage by designing
with inheritance. You can get rid of duplicate
code by abstracting out the behavior common
to a group of classes, and sticking that code
in a superclass. That way, when you need to (i) You avoid duplicate
modify it, you have only one place to update, code.
and the change is magically reflected in all the Put common code in one place, and let
classes that inherit that behavior. Well, there's the subclasses inherit that code from a
no magic involved, but it is pretty simple:
superclass . When you want to change that
make the change and compile the class
again. That's it. You don't have to touch the behavior, you have to modify it in only
subclasses I one place, and everybody else (i.e, all the
subclasses) see the change.
Jmt deliver the newly-ehanged superclass, and
all classes that extend it will automatically use
the new version.
• You define a common
AJava program is nothing but a pile of classes, protocol for a group of
so the subclasses don't have to be recompiled
in order to use the new version of the
classes.
superclass, As long as the superclass doesn't
break anything for the subclass, everything's
fine. (We'll discuss what the word 'break'
means in this context, later in the book. For
now, think of it as modifying something in
the superclass that the subclass is depending
on, like a particular method's arguments or
return type, or method name, etc.)

182 chapter 7
Inheritance and polymorphism

lt1heritat1ce lets you guarat1tee that


all classes grouped ut1der a certaht
supertype have all the Ittethods that
the supertype has:
I., other words. you defl"~ a oOttUMO" protocol for a And I care because•••
set ofclasses related through I"herita"ce,
Because you get to take advantage of
When you define methods in a superclass, that can be polymorphism.
inherited by subclasses, you're announcing a kind of
protocol to other code that says, "All my subtypes (i.e,
subclasses) can do these things, with these methods Which matters to me
that look like this .;" because•••
In other words, you establish a contract: Because you get to refer to a subclass
Class Animal establishes a common protocol for all object using a reference declared as the
Animal subtypes: supertype.

Anlm.1
And that means to me•••
makeNolse() You get to write really flexible code.
eatO
sleepO
Code that's cleaner (more efficient,
roamO simpler). Code that's not just easier to
develop, but also much, much easier to
extend, in ways you never imagined at
the time you originally wrote your code.
And remember, when we say any AlIima~ we mean
Animal and any classthat extendsfrom Animal Which That means you can take that tropical
again means, any class tha: has Animal SO"TTIeWhere aboue it vacation while your co-workers update
in the inheritance hierarchy, the program, and your co-workers might
But we're not even at the really cool part yet, because not even need your source code.
we saved the best--polymarphism--for last
You'll see how it works on the next page,
When you define a supertype for a group of classes,
We don't know about you, but
any subclass 0/that supmype can besubstituted where the
supertype is expected. personally, we find the whole
tropical vacation thing
Say, what?
particu Iarly motivating.
Don 't worry. we're nowhere near done explaining it
Two pages from now, you'll be an expert

"When wesay "all the methods' we mean "alilhe Inheritable methods', which
fornow actually means, "all the public methods', although later we'll refine that
defini\Jon a bitmore.
you are here. 183
the way polymorphism works

The 3 steps of object


declaration and assignment

1 2
To see how polymorphism ~3~
works, we have to step back Dog myDog = new Dog();
and look at the way we
normally declare a reference
and create an object...
O Declare a reference
variable
Dog myDoq = new Dog () ;
Tells the JVM to allocate space for a
reference variable. The reference variable
Is, forever, of type Dog. In other words,
a remote control that has buttons to
control a Dog, but not a Cat or a Button
or a Socket. Dog

G Create an object
Dog myDoq = new Dog () ;
Tells the JVM to allocate space for
a new Dog object on the garbage
collectible heap .

Dog object

~ Link the object


~ and the reference
Dog myDog = new Dog () ;
Assigns the new Dog to the refer-
ence variable myDog.ln other words,
program the remote control.

Dog object

Dog

184 chapter 7
inheritance and polymorphism

The important point is that the


reference type AND the object
type are the same.
In this example, both are Dog.

But with polymorphism, the


reference and the object can
be different.

Animal myDog - new ~ () ;

~/'
twonest: .i~e NOT the sd",e t)'Pe. ne
re-ftyel'lu I/ariable t)'Pt is detlarta as APli...aI,
b~t tht objtt+' is tytaud as Pltw D~O.

you are here ~ 185


polymorphism In action

With polymorphism, the reference


type can be a superclass of the
actual object type.
When you declare a reference variable,
any object that passes the IS-Atest for the
declared type of the reference variable
can be assigned to that reference. In
other words , anything that extends the
declared reference variable type can
be assigned to the reference
variable. This lets you do
thing! like make polyrruwphic
arrays.

animals [0] = new Dog();

animals [1] = new cat 0 ; Blot. look ",hdt. 'fOU ~d. to do... ~O" Un fvl:. ANY
animals [2) = new Wolf() ; <- s"bclass of A"i...al i.. tnt A..i1'fl41 a.......a'f!
animals [3) = new Hippo () ;

186 chapter 7
Inheritance and polymorphism

But wait! There's more!


You can have polymorphic
arguments and retu!!, types.
If you can declare a reference variable
of a superrype, say,Animal, and assign a
subclass object to it, say, Dog, think of how
that might work when the reference is an
argument to a method...

class Vet {

public void qiveShot(Animal a)

II do horrible things to the Animal at

/ / the other end of the 'a' parameter

a.ma.keNoise();
}

class Petowner

public void start ()

Vet v = new VetO;

Dog d = new Dog()i ~


Hippo h = new Hippo(); ~
v. giveShot (d) ; ~ D'1's "",ktNoiUO--1Ai\S

v . giveShot (h) ; ( Itippo's Or\dkeNoiseO l"1AN;

you are here) 187


exploiting the power of polymorphism

NOW I get itl If I write


my code using polymorphic arguments,
where. r declare the method parameter as a
super-class type,r CM pass in any subclass object at
runtime. Cool. Because that also means r can write my
code, go on vacation, and someone else can add new
subclass types to the program and my methods will
still work ... (the only downside is rm just making life
easier for that idiot Jim).

WIth polytttorphlSttt, you caM write code that doutt't


have to chattge whe.. you 'tttroduce ..ew subclass
types I..to the progratlt.
Remember that Vet class? If you write that Vet class using
arguments declared as type Animal; your code can handle any
Animal subclass. That means if others want to take advantage of
your Vet class. all they have to do is make sure their new Animal
types extend class Animal. The Vet methods will still work, even
though the Vet class was written without any knowledge of the
new Animal subtypes the Vet will be working on.

Why is polymorphism guaranteed to work this way? Why Is


it always safe to assume that any subclass type will have the
methods you think you're calling on the suoerclass type (the
superclass reference type you're using the dot operator on)?

18a chapter 7
inheritance and polymorphism

:therel arH ?
Diimo ~uesti9n8
0

Q: Are there any practical limits Q: Can you extend any class? Or Q: Why would you ever want to
on the levels of subclassing? How is it like class members where if the make a final class? What advantage
deep can you go? class is private you can't inherit it... would there be in preventing a class
from being subclassed?
A.: If you look in the Java API,
A.:
you 'll see that most inheritance
hierarchies are wide but not deep.
There's no such thing as a
private class,except in a very special
case called an innerclass,that we
A: Typically, you won 't make your
classes final. But if you need security
Most are no more than one or two
haven't looked at yet. But there are - the security of knowing that the
levels deep, although there are
three things that can prevent a class methods will always work the way
exceptions (especially in the GUI
from being subclassed. that you wrote them (because they
classes) .You'll come to realize that
The first is accesscontrol. Even though can't be overridden), a final class
it usually makes more sense to keep
a class can't be marked pr i va t e, a will give you that. A lot of classes in
your inheritance trees shallow, but
class can be non-public (what you the Java API are final for that reason.
there isn't a hard limit (well, not one
get if you don 't declare the class as The String class,for example, is final
that you'd ever run into) .
pub l ic). A non-public class can be because, well , imagine the havoc if
subclassed only by classes in the somebody came along and changed
Q: Hey,Ijust thought of same package as the class.Classes in the way Strings behave!
something... if you don't have a different package won't be able to
Kcess to the source code for a class,
but you want to change the way a
subclass (or even use, for that matter)
the non-public class.
Q: Can you make a method final,
without making the whole class
method of that class works, could The second thing that stops a class final?
JOu use subclassing to do that? To from being subclassed is the keyword
extend the"bad" class andoverride
the method with your own better
code?
modifier final. A final class means
that it's the end of the inheritance
line. Nobody, ever, can extend a final
A.: If you want to protect a specific
method from being overridden, mark
class. the method with the fin almodifier.

A.: Yep.That's one cool feature


of 00, and sometimes it savesyou
The third issue is that if a class has
only p r i va te constructors (we'll
Mark the whole class as final if you
want to guarantee that none of the
methods in that class will ever be
look at constructors in chapter 9), it
from having to rewrite the class overridden .
can't be subclassed.
from scratch, or track down the
programmer who hid the source code.

you are here r 189


Keepl.,g the co"tract: rules for overriding
When you override a method from a supercIass, you 're agreeing to
fulfill the contract. The contract that says. for example, ~I take no
arguments and I return a boolean ." In other words, the arguments Appliance
and return types of your overriding method must look to the outside
world exactly like the overridden method in the superclass. boolean bJmOnO
The methods are the contract. boolean bJmOffO
If polymorphism is going to work. the Toaster's version of the
overridden method from Appliance has to work at runtime.
Remember. the compiler looks at the reference type to decide
whether you can call a particular method on that reference. Wilh
an Appliance reference to a Toaster, the compiler cares only if class
Appliance has the method you 're invoking on an Appliance reference . Toaster
But at runtime, thejVM looks not at the reference type (Appliance) but
at the actual Toaster object on the heap. So if the compiler has already ~ boolean tumOn(~lleveD
approved the method call, the only way it can work is if the overriding "This \~ 1'./01 6"
method has the same arguments and return types. Otherwise. '1t:Y""'\dt~
someone with an Appliance reference will call turn On 0 as a no- o. h6 e \)Ie
arg method, even though there's a version in Toaster that takes an ta" \:. t. b~" 61\
int. Which one is called at runtime? The one in Appliance. In other ~\WI'.~~ .... e-t.n06.I .
words, the turnOn{int level) m.etJwd in Toaster is not an override.' O~~I ThIs j! .t,i:.ua/ly .a Je5d1
overLOAD b· i .L
olle"rRIDE. I ""l; "()l:. an
Arguments must be the same, and return
types must be compatible.
The contract of superclass defines how other code can use a method.
Whatever the superclass takes as an argument. the subclass over-
riding the method must use that same argument. And whatever the
superclass declares as a retum type. the overriding method must de- Appliance
clare either the same type. or a subclass type . Remember, a subclass
object is guaranteed to be able to do anything its superclass declares. pUblic boolean tumOnO
so iI's safe to retum a subclass where the superclass Is expected.
public boolean tumOnO

• The method can't be less accessible.


That means the access level must be the same, or friendlier. That
means you can't, for example, override a public method and make
It private. What a shock that would be to the code invoking what It
thinks (at compile time) is a public method. If suddenly at runtime
the JVM slammed the door shut because the overriding version Toaster
called at runtime Is prlvatel
So far we've leamed about two access levels : private and public . privata boolean bJmOnO
The other two are In the deployment chapter (Release your Code) \
and appendix B. There's also another rule about overriding related
to exception handling , but we'll walt until the chapter on exceptions
(Risky Behavior) to cover thaI.

190 chapter 7
inheritance and polymorphism

Overloading a tttethod
~

Method overloading is nothing more than having


two methods with the same name but different
argument lists. Period. There's no polymorphism
involved with overloaded methods!
An overloaded method is
Overloading lets you make multiple versions
of a method, with different argument lists, for just a dii±erent method that
convenience to the callers. For example, if you
have a method that takes only an int, the calling
happens to have the sane
code has to convert, say, a double into an int method name, It has nothing
before calling your method. But if you overloaded
the method with another version that takes a
to do with inheritance and
double, then you've made things easier for the pol)'Illorphism. An overloaded
caller. You'll see more of this when we look into
constructors in the object lifecyc1e chapter. method is NoT the sane as
Since an overloading method isn't trying to an overridden method.
fulfill the polymorphism contract defined by its
superc1ass, overloaded methods have much more
flexibility.

• The return types can be Legal examples of method


different. overloading:
You're free to change the return types in public class Overloads
overloaded methods, as long as the argument lists
are different. String uniqueID;

• You can't change ONLY the public int addNums(int a, int b) (


return a + b;
return type.
If only the return type is different, it's not a
valid overload-the compiler will assume public double addNums(double a, double b) (
you're trying to override the method. And even return a + b;
that won 't be legal unless the return type is
a subtype of the return type declared in the
superclass. To overload a method, you MUST public void setUniqueID(String theID) (
change the argument list, although you can II lots of validation code, and then:
change the return type to anything. uniqueID = theID;

• You can vary the access public void setUniqueID(int ssNumber)


levels in any direction. String numString = " " + ssNumber;
setUniqueID{numString);
You're free to overload a method with a method
that's more restrictive. It doesn't matter, since the
new method isn't obligated to fulfill the contract of
the overloaded method.

you are here ~ 191


exercise: Mixed Messages
A short Java program is listed below . One block of
Mix~d the program is missing! Your challenge is to match
MessagES the candidate block of code (on the left), with the
output that YOU'd see if the block were Inserted.
Not all the lines of output wIll be used, and some of
a ~ 6i~56 the lines of output might be used more than once .
b ~ Si 11 Draw lines connecting the candidate blocks of
a ~ 5i 65
code with their matching command-line output.
the prograttt:
class A { class C extends B {
int ivar ;; 7; void m3() {
void ml() ( system.out.print(UC's nU, "+(ivar + 6»;
System.out.print("A'S mIt ");
}
void m2 () {
System.out.print("A'S m2, "); public class Mixed2 {
} public static void main(String [I args) {
void m3() ( A a "" new A();
System.out.print("A's m3, U); B b ;; new B();
C c = new e();
A a2 = new C ( ) ; cattdldate code
~ goes here
class B extends A {
void ml (I (
(three IIttes)
System.out.print(UB'S ml, U); '----------I
} }
}

code b.ml (); output:


candidates: c.m2();
a.m3 (); } A's ml, A's m2, C's m3, 6

B's ml, A's m2, A's m3,


c .ml ( );
c.m2();
c.m3();
} A's ml, B's rn2, A's m3,

B's ml, A's m2, C's m3, 13


a.ml()i
b.rn2();
c.m3();
} B's ml, C's m2 t A's m3,

B's m1, A's rn2, C's m3, 6

a2.ml(); } A's m1, A's rn2, C's mJ, 13


a2 .m2 ( ) i
a2 .m3 ( ) ;

192 chapter 7
inheritance and polymorphism

BE the Ct»mriler
"Which ofthe A-B pai.rS ofmethods listed on the right, if
inserted into the classes on the left. would compile and
produce the output shown? (The AltIethod inSerted into
class Monster, the B JIlethod inserted into class VlUtlpil'e.)
public class MonsterTestDrive {
boolean frighten(int d) {
public static void maio(String (I args) { 1
System.out.println("arrrgh U);
Monster (J rna = new Monster(3J: e return true;
ma[OI new Vampire(); }
marl) new Dragon(): boolean frighten(int x)
ma[2J new Monster(): System.out.println("& bite?");
for(iot x = 0: x < 3; X++) { return false;
ma[xJ.frighten(x); }

}
boolean frighten(int x) {
} 2
} e System.out.println(Uarrrgh");
return true;
}
class Monster { iot frighten(int f) {
4) System.out.println(U a bite?");
return 1:
} }

boolean frighten(int x) {
class Vampire extends Monster ( 3 System.out.println("arrrgh"):
e return false;
}
}
boolean scare(int x) {
System.out.println("a bite?"):
class Dragon extends Monster { return true;
boolean frighten(int degree) }
System. out. pr intln ("breath fire");
return true; boolean frighten(int z) {
4
}
e System.out.println("arrrgh")i
return true;
}
boolean frighten(byte b) {
o System.out.println("a bite?H);
return true;

you are here ~ 193


puzzle: Pool Puzzle

Pool Puzzle
Your Job is to take code snippets from the pool and place them into
the blank lines In the code .You may use the same snippet more
than once, and you might not need to use all the snippets.Your
goal Is to make a set of classes that will compile and run together
as a program. Don't be fooled - this one's harder than It looks.

public class Rowboat { public class TestBoats {


public rowTheBoat() { _ _ _ __ _ _ _ _ main(String( I args){
Syatem.out.print(nstroke natashaW)i ______ bI = new Boat();
Sailboat b2 = new ();
}
Rowboat _ new Rowboat ( ) ;
public class b2.setLength(32);
private int _ bl. ()i
____ void __ ) { b3. ()i
length:: len; _ _ _ .move();
}
}
public int getLength() {
public class Boat {
} public () {
public move() { System. out. print ( u ") ;

System. ou t . print (" H ) ; }


}
}
}
OUTPUT: drift drift hoist sail

194 chapte r 7
inheritance and polymorphism

Set 1 will work.

Set 2 will not compile becauseof Vampire's retum


type (Int).
The Vampire's frightenO method (B) is not a legal
override OR overload of Monster'sfrightenO method.
Changing ONLYthe retum type Is not enough
to make a valid overload, and since an int is not
compatible with a boolean. the method is not a valid
override. (Remember, If you change ONLY the retum
type, it must be to a retum type that Is compatible
with the superclass version's retum type, and then ifs
an override.
Sets 3 and 4 will compile, but produce:
arrrqh
breath fire
arrrgh
Remember, class Vampire did not override class
Monster's frightenO method. (The frightenO method
in Vampire's set 4 takes a byte, not an lnr.)

code
catldldates:
A's m2, C's m3, 6

mz , A'9 m3,
Mixed A's

MessagES B'B m2, A's m3,

A's mz , C's nU, 13

B's ml, C's m2, A's m3,

B's ml, A's 11\2, C's m3, 6

A'8 ml, A'S m2, e's m3, 13

you are he re ~ 195


puzzle answers


pUblic class Rowboat extends Boat
public void rowTheBoat() {
System.out.print("stroke natasha")1

public class Boat {


private int length
public void setLength ( int len ) {
length = lenl

public int getLength()


return length 1

pub.l.Lc void move ( )


System. out. print ( "drift") 1

public class TestBoats {


public static void main(String[ l args) {
Boat bl = new Boat()l
Sailboat b2 = new Sailboat ( ) 1
Rowboat b3 = new Rowboat()1
b2.setLength(32)1
bl.mOVe() 1
b3.mOVe() 1
b2 .move() 1

pubLi.c class Sailboat extends Boat {


public void mover i {
System.out.print( "hoist sail •• ) 1

OUTPUT: drift drift hoist sail

196 chapter 7
8 interfaces and abstract classes

Serious Polymorphism

Inheritance is just the beginning. 4OEXPLOITPOLYMORPHISM WENEEDINTERFACES


ANDNOTTHE'5)KIND 7ENEEDTOGOBEYONDSIMPLEINHERITANCETOALEVELOFFLEXIBILITYAND
EXTENSIBILITYYOUCANGETONLYBYDESIGNINGANDCODINGTOINTERFACESPECIFICATIONS3OMEOFTHE
COOLESTPARTSOF*AVAWOULDNTEVENBEPOSSIBLEWITHOUTINTERFACES SOEVENIFYOUDONTDESIGN
WITHTHEMYOURSELF YOUSTILLHAVETOUSETHEM"UTYOULLWANTTODESIGNWITHTHEM9OULLNEED
TODESIGNWITHTHEM9OULLWONDERHOWYOUEVERLIVEDWITHOUTTHEM7HATSANINTERFACE)TS
AABSTRACTCLASS7HATSANABSTRACTCLASS)TSACLASSTHATCANTBEINSTANTIATED7HATSTHAT
GOODFOR9OULLSEEINJUSTAFEWMOMENTS"UTIFYOUTHINKABOUTTHEENDOFTHELASTCHAPTER
ANDHOWWEUSEDPOLYMORPHICARGUMENTSSOTHATASINGLE6ETMETHODCOULDTAKE!NIMAL
SUBCLASSESOFALLTYPES WELL THATWASJUSTSCRATCHINGTHESURFACE)NTERFACESARETHEPOLYIN
POLYMORPHISM4HEABINABSTRACT4HECAFFEINEIN*AVA

this is a new chapter 197


designing with inheritance

Did we forget about something


when we designed this? Animal
4HECLASSSTRUCTUREISNTTOOBAD7EVEDESIGNED
picture
ITSOTHATDUPLICATECODEISKEPTTOAMINIMUM
food
ANDWEVEOVERRIDDENTHEMETHODSTHATWETHINK hunger
SHOULDHAVESUBCLASS SPECIlCIMPLEMENTATIONS boundaries
7EVEMADEITNICEANDmEXIBLEFROMA location
POLYMORPHICPERSPECTIVE BECAUSEWECANDESIGN
!NIMAL USINGPROGRAMSWITH!NIMALARGUMENTS makeNoise()
ANDARRAYDECLARATIONS SOTHATANY!NIMAL eat()
SUBTYPEˆINCLUDINGTHOSEWENEVERIMAGINEDATTHE sleep()
TIMEWEWROTEOURCODEˆCANBEPASSEDINANDUSED roam()
ATRUNTIME7EVEPUTTHECOMMONPROTOCOLFOR
ALL!NIMALSTHEFOURMETHODSTHATWEWANTTHE
WORLDTOKNOWALL!NIMALSHAVE INTHE!NIMAL
SUPERCLASS ANDWEREREADYTOSTARTMAKINGNEW
,IONSAND4IGERSAND(IPPOS
Feline

Canine

roam()
Hippo
roam()
size
picture
food
makeNoise()
prey
eat()

Lion
size
picture
food
makeNoise()
prey
eat()

Dog

Cat size
picture
size food
Tiger makeNoise()
picture Wolf prey
size food eat()
makeNoise()
picture prey size
eat() picture
food
makeNoise()
prey food
makeNoise()
eat()
prey
eat()

198 chapter 8
interfaces and polymorphism

We know we can say:


Wolf aWolf = new Wolf();

aWolf
W
A Wolf reference to a olf object
Wolf object. Wolf

These two are the same type.

And we know we can say:


Animal aHippo = new Hippo();

aHippo
Animal reference to Hi t
ppo
a Hippo object. objec
Animal

These two are NOT the same type.

But here’s where it gets weird:


Animal anim = new Animal();

Animal reference to anim


?
An
an Animal object. imal bject
o
Animal

These two are the same type, but...


what the heck does an Animal object look like?

you are here4 199


when objects go bad

What does a new Animal() object


look like?

scary objects

What are the instance variable values?

Some classes just should not be


instantiated!

)TMAKESSENSETOCREATEA7OLFOBJECTORA(IPPO 9OUCANSTILLUSETHATABSTRACTTYPEASAREFERENCETYPE
OBJECTORA4IGEROBJECT BUTWHATEXACTLYISAN )NFACT THATSABIGPARTOFWHYYOUHAVETHATABSTRACT
!NIMALOBJECT7HATSHAPEISIT7HATCOLOR SIZE CLASSINTHElRSTPLACETOUSEITASAPOLYMORPHIC
NUMBEROFLEGS ARGUMENTORRETURNTYPE ORTOMAKEAPOLYMORPHIC
4RYINGTOCREATEANOBJECTOFTYPE!NIMALISLIKEA ARRAY 
NIGHTMARE3TAR4REK©TRANSPORTERACCIDENT4HE 7HENYOUREDESIGNINGYOURCLASSINHERITANCE
ONEWHERESOMEWHEREINTHEBEAM ME UPPROCESS STRUCTURE YOUHAVETODECIDEWHICHCLASSESARE
SOMETHINGBADHAPPENEDTOTHEBUFFER ABSTRACTANDWHICHARECONCRETE#ONCRETECLASSESARE
"UTHOWDOWEDEALWITHTHIS7ENEEDAN!NIMAL THOSETHATARESPECIlCENOUGHTOBEINSTANTIATED!
CLASS FORINHERITANCEANDPOLYMORPHISM"UTWE CONCRETECLASSJUSTMEANSTHATITS/+TOMAKEOBJECTS
WANTPROGRAMMERSTOINSTANTIATEONLYTHELESS OFTHATTYPE
ABSTRACTSUBCLASSESOFCLASS!NIMAL NOT!NIMALITSELF -AKINGACLASSABSTRACTISEASYˆPUTTHEKEYWORD
7EWANT4IGEROBJECTSAND,IONOBJECTS NOT!NIMAL abstractBEFORETHECLASSDECLARATION
OBJECTS
&ORTUNATELY THERESASIMPLEWAYTOPREVENTACLASS abstract class Canine extends Animal {
FROMEVERBEINGINSTANTIATED)NOTHERWORDS TOSTOP
ANYONEFROMSAYINGhnewvONTHATTYPE"YMARKING public void roam() { }
THECLASSASabstract THECOMPILERWILLSTOPANY }
CODE ANYWHERE FROMEVERCREATINGANINSTANCEOF
THATTYPE

200 chapter 8
interfaces and polymorphism

The compiler won’t let you instantiate


an abstract class
!NABSTRACTCLASSMEANSTHATNOBODYCANEVERMAKEANEW
INSTANCEOFTHATCLASS9OUCANSTILLUSETHATABSTRACTCLASSASA
DECLAREDREFERENCETYPE FORTHEPURPOSEOFPOLYMORPHISM BUT
YOUDONTHAVETOWORRYABOUTSOMEBODYMAKINGOBJECTSOFTHAT
TYPE4HECOMPILERGUARANTEESIT

abstract public class Canine extends Animal


{
public void roam() { }
}

lways assign ce,


public class MakeCanine {
y o u c a n a
because eferen
public void go() {
This is OK, bject to a superclass r.
Canine c; a subclass o superclass is abstract
c = new Dog(); even if the
c = new Canine();
class Canine
c.roam(); so the comp is marked abstract,
iler will NOT
} let you do t
his.
}
File Edit Window Help BeamMeUp

% javac MakeCanine.java
MakeCanine.java:5: Canine is abstract;
cannot be instantiated
c = new Canine();
^
1 error

An abstract class has virtually* no use, no value, no


purpose in life, unless it is extended.

With an abstract class, the guys doing the work at runtime


are instances of a subclass of your abstract class.

*There is an exception to this—an abstract class can


have static members (see chapter 10).
you are here4 201
abstract and concrete classes

Abstract vs. Concrete abstract


!CLASSTHATSNOTABSTRACTISCALLED Animal
ACONCRETECLASS)NTHE!NIMAL
INHERITANCETREE IFWEMAKE
!NIMAL #ANINE AND&ELINE
ABSTRACT THATLEAVES(IPPO 7OLF
$OG 4IGER ,ION AND#ATASTHE
abstract
CONCRETESUBCLASSES Canine
concrete
&LIPTHROUGHTHE*AVA!0)AND Hippo
YOULLlNDALOTOFABSTRACTCLASSES abstract
ESPECIALLYINTHE'5)LIBRARY7HAT Feline
DOESA'5)#OMPONENTLOOK concrete
LIKE4HE#OMPONENTCLASSISTHE Dog
SUPERCLASSOF'5) RELATEDCLASSES
FORTHINGSLIKEBUTTONS TEXTAREAS concrete
SCROLLBARS DIALOGBOXES YOUNAME concrete
Cat
IT9OUDONTMAKEANINSTANCEOF Wolf
AGENERIC#OMPONENTANDPUTITON concrete concrete
THESCREEN YOUMAKEA*"UTTON)N Lion
OTHERWORDS YOUINSTANTIATEONLYA Tiger
CONCRETESUBCLASSOF#OMPONENT BUT
NEVER#OMPONENTITSELF

YiX`e
gfn\i abstract or concrete?
(OWDOYOUKNOWWHENACLASSSHOULDBE
ABSTRACT7INEISPROBABLYABSTRACT"UTWHAT
Hmmmm... do I Hmmmm... the Camelot ABOUT2EDAND7HITE!GAINPROBABLYABSTRACT
feel like red or Vineyards 1997 Pinot
white tonight? Noir was a pretty
FORSOMEOFUS ANYWAY "UTATWHATPOINTINTHE
decent year... HIERARCHYDOTHINGSBECOMECONCRETE

$OYOUMAKE0INOT.OIRCONCRETE ORISITABSTRACT
TOO)TLOOKSLIKETHE#AMELOT6INEYARDS
0INOT.OIRISPROBABLYCONCRETENOMATTERWHAT
"UTHOWDOYOUKNOWFORSURE

,OOKATTHE!NIMALINHERITANCETREEABOVE$OTHE
CHOICESWEVEMADEFORWHICHCLASSESAREABSTRACT
ANDWHICHARECONCRETESEEMAPPROPRIATE
7OULDYOUCHANGEANYTHINGABOUTTHE!NIMAL
INHERITANCETREEOTHERTHANADDINGMORE!NIMALS
OFCOURSE 

202 chapter 8
interfaces and polymorphism

Abstract methods
"ESIDESCLASSES YOUCANMARKMETHODSABSTRACT TOO!NABSTRACT
CLASSMEANSTHECLASSMUSTBEEXTENDEDANABSTRACTMETHODMEANS
THEMETHODMUSTBEOVERRIDDEN9OUMIGHTDECIDETHATSOMEORALL It really sucks to
BEHAVIORSINANABSTRACTCLASSDONTMAKEANYSENSEUNLESSTHEYRE
be an abstract method.
IMPLEMENTEDBYAMORESPECIlCSUBCLASS)NOTHERWORDS YOUCANT
THINKOFANYGENERICMETHODIMPLEMENTATIONTHATCOULDPOSSIBLYBE You don’t have a body.
USEFULFORSUBCLASSES7HATWOULDAGENERICEAT METHODLOOKLIKE
An abstract method has no body!
"ECAUSEYOUVEALREADYDECIDEDTHEREISNTANYCODETHATWOULDMAKE
SENSEINTHEABSTRACTMETHOD YOUWONTPUTINAMETHODBODY3ONO
CURLYBRACESˆJUSTENDTHEDECLARATIONWITHASEMICOLON

public abstract void eat();

!
No method boadsey micolon.
End it with

If you declare an abstract method, you MUST


mark the class abstract as well. You can’t have
an abstract method in a non-abstract class.

)FYOUPUTEVENASINGLEABSTRACTMETHODINACLASS YOUHAVETO
MAKETHECLASSABSTRACT"UTYOUCANMIXBOTHABSTRACTANDNON
ABSTRACTMETHODSINTHEABSTRACTCLASS

there are no
Dumb Questions
Q: 7HATISTHEPOINTOFANABSTRACTMETHOD)THOUGHT
THEWHOLEPOINTOFANABSTRACTCLASSWASTOHAVECOMMON
Q: 7HICHISGOODBECAUSE

CODETHATCOULDBEINHERITEDBYSUBCLASSES
A: 0OLYMORPHISM2EMEMBER WHATYOUWANTISTHE

A: )NHERITABLEMETHODIMPLEMENTATIONSINOTHERWORDS
METHODSWITHACTUALBODIES ARE!'OOD4HINGTOPUTINA
ABILITYTOUSEASUPERCLASSTYPEOFTENABSTRACT ASAMETHOD
ARGUMENT RETURNTYPE ORARRAYTYPE4HATWAY YOUGETTO
ADDNEWSUBTYPESLIKEANEW!NIMALSUBCLASS TOYOUR
SUPERCLASS7HENITMAKESSENSE!NDINANABSTRACTCLASS IT PROGRAMWITHOUTHAVINGTOREWRITEORADD NEWMETHODS
OFTENDOESNTMAKESENSE BECAUSEYOUCANTCOMEUPWITH TODEALWITHTHOSENEWTYPES)MAGINEHOWYOUDHAVETO
ANYGENERICCODETHATSUBCLASSESWOULDFINDUSEFUL4HE CHANGETHE6ETCLASS IFITDIDNTUSE!NIMALASITSARGUMENT
POINTOFANABSTRACTMETHODISTHATEVENTHOUGHYOUHAVENT TYPEFORMETHODS9OUDHAVETOHAVEASEPARATEMETHOD
PUTINANYACTUALMETHODCODE YOUVESTILLDEFINEDPARTOF FOREVERYSINGLE!NIMALSUBCLASS/NETHATTAKESA,ION ONE
THEPROTOCOLFORAGROUPOFSUBTYPESSUBCLASSES  THATTAKESA7OLF ONETHATTAKESAYOUGETTHEIDEA3OWITH
ANABSTRACTMETHOD YOURESAYING h!LLSUBTYPESOFTHISTYPE
HAVE4()3METHODvFORTHEBENEFITOFPOLYMORPHISM

you are here4 203


you must implement abstract methods

You MUST implement all abstract methods

I have wonderful news,


mother. Joe finally implemented
all his abstract methods! Now
everything is working just the
way we planned...

Implementing an abstract
method is just like
overriding a method.

!BSTRACTMETHODSDONTHAVEABODYTHEYEXISTSOLELYFORPOLYMORPHISM4HAT
MEANSTHElRSTCONCRETECLASSINTHEINHERITANCETREEMUSTIMPLEMENTALLABSTRACT
METHODS
9OUCAN HOWEVER PASSTHEBUCKBYBEINGABSTRACTYOURSELF)FBOTH!NIMALAND
#ANINEAREABSTRACT FOREXAMPLE ANDBOTHHAVEABSTRACTMETHODS CLASS#ANINE
DOESNOTHAVETOIMPLEMENTTHEABSTRACTMETHODSFROM!NIMAL"UTASSOONASWE
GETTOTHElRSTCONCRETESUBCLASS LIKE$OG THATSUBCLASSMUSTIMPLEMENTALLOFTHE
ABSTRACTMETHODSFROMBOTH!NIMALAND#ANINE
"UTREMEMBERTHATANABSTRACTCLASSCANHAVEBOTHABSTRACTANDNON ABSTRACT
METHODS SO#ANINE FOREXAMPLE COULDIMPLEMENTANABSTRACTMETHODFROM
!NIMAL SOTHAT$OGDIDNTHAVETO"UTIF#ANINESAYSNOTHINGABOUTTHEABSTRACT
METHODSFROM!NIMAL $OGHASTOIMPLEMENTALLOF!NIMALSABSTRACTMETHODS
7HENWESAYhYOUMUSTIMPLEMENTTHEABSTRACTMETHODv THATMEANSYOUMUST
PROVIDEABODY4HATMEANSYOUMUSTCREATEANON ABSTRACTMETHODINYOURCLASS
WITHTHESAMEMETHODSIGNATURENAMEANDARGUMENTS ANDARETURNTYPETHATIS
COMPATIBLEWITHTHEDECLAREDRETURNTYPEOFTHEABSTRACTMETHOD7HATYOUPUTIN
THATMETHODISUPTOYOU!LL*AVACARESABOUTISTHATTHEMETHODISTHERE INYOUR
CONCRETESUBCLASS

204 chapter 8
interfaces and polymorphism

Sharpen your pencil !BSTRACTVS#ONCRETE#LASSES


,ETSPUTALLTHISABSTRACTRHETORICINTOSOMECONCRETEUSE)NTHEMIDDLE
COLUMNWEVELISTEDSOMECLASSES9OURJOBISTOIMAGINEAPPLICATIONS
WHERETHELISTEDCLASSMIGHTBECONCRETE ANDAPPLICATIONSWHERETHELISTED
CLASSMIGHTBEABSTRACT7ETOOKASHOTATTHElRSTFEWTOGETYOUGOING
&OREXAMPLE CLASS4REEWOULDBEABSTRACTINATREENURSERYPROGRAM WHERE
DIFFERENCESBETWEENAN/AKANDAN!SPENMATTER"UTINAGOLFSIMULATION
PROGRAM 4REEMIGHTBEACONCRETECLASSPERHAPSASUBCLASSOF/BSTACLE
BECAUSETHEPROGRAMDOESNTCAREABOUTORDISTINGUISHBETWEENDIFFERENT
TYPESOFTREES4HERESNOONERIGHTANSWERITDEPENDSONYOURDESIGN

#ONCRETE 3AMPLECLASS !BSTRACT

golf course simulation 4REE tree nursery application

???????????????????? (OUSE architect application

satellite photo application 4OWN ?????????????????????

???????????????????? &OOTBALL0LAYER coaching application

???????????????????? #HAIR ?????????????????????

???????????????????? #USTOMER ?????????????????????

???????????????????? 3ALES/RDER ?????????????????????

???????????????????? "OOK ?????????????????????

???????????????????? 3TORE ?????????????????????

???????????????????? 3UPPLIER ?????????????????????

???????????????????? 'OLF#LUB ?????????????????????

???????????????????? #ARBURETOR ?????????????????????

???????????????????? /VEN ?????????????????????

you are here4 205


polymorphism examples

Polymorphism in action
,ETSSAYTHATWEWANTTOWRITEOUROWNKINDOFLISTCLASS ONETHATWILLHOLD
$OGOBJECTS BUTPRETENDFORAMOMENTTHATWEDONTKNOWABOUTTHE
!RRAY,ISTCLASS&ORTHElRSTPASS WELLGIVEITJUSTANADD METHOD7ELLUSE
ASIMPLE$OGARRAY$OG;= TOKEEPTHEADDED$OGOBJECTS ANDGIVEITA
LENGTHOF7HENWEREACHTHELIMITOF$OGOBJECTS YOUCANSTILLCALLTHE
ADD METHODBUTITWONTDOANYTHING)FWERENOTATTHELIMIT THEADD
METHODPUTSTHE$OGINTHEARRAYATTHENEXTAVAILABLEINDEXPOSITION THEN
INCREMENTSTHATNEXTAVAILABLEINDEXNEXT)NDEX 

Building our own Dog-specific list


(Perhaps the world’s worst attempt at making our
own ArrayList kind of class, from scratch.)

E RSI O Dog array


Use a plain oscldenes.
N
V

1 public class MyDogList {


private Dog [] dogs = new Dog[5];
behind the
MyDogList

Dog[] dogs
private int nextIndex = 0; We’ll increment this eadechd.
int nextIndex time a new Dog is ad
add(Dog d) public void add(Dog d) {
the limit
If we’re not alreadyadatd the Dog
if (nextIndex < dogs.length) {
of the dogs array,
dogs[nextIndex] = d; and print a message.
System.out.println(“Dog added at “ + nextIndex);

nextIndex++;
increment,
} next index tto give us the
o use
}
}

206 chapter 8
interfaces and polymorphism

Uh-oh, now we need to keep Cats, too.


7EHAVEAFEWOPTIONSHERE
 -AKEASEPARATECLASS -Y#AT,IST TOHOLD#ATOBJECTS0RETTYCLUNKY
 -AKEASINGLECLASS $OG!ND#AT,IST THATKEEPSTWODIFFERENTARRAYSASINSTANCE
VARIABLESANDHASTWODIFFERENTADD METHODSADD#AT#ATC ANDADD$OG$OG
D !NOTHERCLUNKYSOLUTION
 -AKEHETEROGENEOUS!NIMAL,ISTCLASS THATTAKESANYKINDOF!NIMALSUBCLASS
SINCEWEKNOWTHATIFTHESPECCHANGEDTOADD#ATS SOONERORLATERWELLHAVE
SOMEOTHERKINDOFANIMALADDEDASWELL 7ELIKETHISOPTIONBEST SOLETSCHANGE
OURCLASSTOMAKEITMOREGENERIC TOTAKE!NIMALSINSTEADOFJUST$OGS7EVE
HIGHLIGHTEDTHEKEYCHANGESTHELOGICISTHESAME OFCOURSE BUTTHETYPEHAS
CHANGEDFROM$OGTO!NIMALEVERYWHEREINTHECODE

Building our own Animal-specific list ga


o n ’t p a n ic . W e’re not makinaking a
D ject; we’re m
public class MyAnimalList {
new Animal obbject, of type Animal.
E RSI O
new array o you cannot make a new
N
V

private Animal[] animals = new Animal[5];


2
private int nextIndex = 0; (Remember, an abstract type, but
MyAnimalList instance of ake an array object
public void add(Animal a) { you CAN m HOLD that type.)
Animal[] animals
if (nextIndex < animals.length) {
animals[nextIndex] = a;
declared to
int nextIndex
System.out.println(“Animal added at “ + nextIndex);
add(Animal a) nextIndex++;

}
}
}

public class AnimalTestDrive{


public static void main (String[] args) {
MyAnimalList list = new MyAnimalList();
Dog a = new Dog();
Cat c = new Cat();
list.add(a);
list.add(c);
}
}
File Edit Window Help Harm

% java AnimalTestDrive
Animal added at 0
Animal added at 1

you are here4 207


the ultimate superclass: Object

What about non-Animals? Why not make


a class generic enough to take anything?
9OUKNOWWHERETHISISHEADING7EWANTTOCHANGETHE a few of the
(These are just ayList...there
TYPEOFTHEARRAY ALONGWITHTHEADD METHODARGUMENT TO E RSI O
methods in Arr )

N
V
SOMETHINGABOVE!NIMAL3OMETHINGEVENMOREGENERIC MORE 3
are many more.
ABSTRACTTHAN!NIMAL"UTHOWCANWEDOIT7EDONTHAVEA
SUPERCLASSFOR!NIMAL
4HENAGAIN MAYBEWEDO
!RRAY,IST
2EMEMBERTHOSEMETHODSOF!RRAY,IST
,OOKHOWTHEREMOVE CONTAINS AND
INDEX/FMETHODALLUSEANOBJECTOFTYPE LEM
R E M OVE/BJECTE 2ETURNS
/BJECT BO O LE A N
A T TH E IN D EXPARAMETER
JECTOB
2EMOVESTHE ELIST
IF T H E EL EM ENTWASINTH
Every class in Java extends @TRUE
TELEM
class Object. TAINS/BJEC JECTPARAMET
ER
BOOLEANCON AT CHFORTHEOB
IFTHERESAM
#LASS/BJECTISTHEMOTHEROFALLCLASSESITS 2ETURNS@TRUE
THESUPERCLASSOFEVERYTHING MPTY
BOOLEANIS% NOELEMENTS

IFTHELISTHAS
%VENIFYOUTAKEADVANTAGEOFPOLYMORPHISM 2ETURNS@TRUE

YOUSTILLHAVETOCREATEACLASSWITHMETHODS
/BJECTELEM AMETER OR 

THATTAKEANDRETURNYOURPOLYMORPHICTYPE INTINDEX/F ERTHEINDEXOFTHEOBJECTPAR
7ITHOUTACOMMONSUPERCLASSFOREVERYTHING 2ETURNSEITH
TINDEX
/BJECTGETIN
IN*AVA THEREDBENOWAYFORTHEDEVELOPERS THELIST
HISPOSITIONIN
OF*AVATOCREATECLASSESWITHMETHODSTHAT ELEMENTATT
2ETURNSTHE
COULDTAKEYOURCUSTOMTYPESTYPESTHEYNEVER
/BJECTELEM
KNEWABOUTWHENTHEYWROTETHE!RRAY,ISTCLASS BOOLEANADD LISTRETURN S@TRUE 
!DDSTHEEL EMENTTOTHE
3OYOUWEREMAKINGSUBCLASSESOFCLASS/BJECT
FROMTHEVERYBEGINNINGANDYOUDIDNTEVEN MORE
KNOWIT%VERYCLASSYOUWRITEEXTENDS/BJECT
WITHOUTYOUREVERHAVINGTOSAYIT"UTYOUCAN
THINKOFITASTHOUGHACLASSYOUWRITELOOKSLIKE
of th e A rr ay L is t methods use the
THIS Many ic type, Object. Sinc
e
public class Dog extends Object { } ultimate polymorph is a subclass of Object,
"UTWAITAMINUTE $OGALREADYEXTENDSSOMETHING #ANINE
every class in Java ethods can take anything !
4HATS/+4HECOMPILERWILLMAKE#ANINEEXTEND/BJECT these ArrayList m d()
0, the get() and ad
INSTEAD%XCEPT#ANINEEXTENDS!NIMAL.OPROBLEM THENTHE (Note: as of Java 5.ok a little different
COMPILERWILLJUSTMAKE!NIMALEXTEND/BJECT
methods actually lon here, but for now this
Any class that doesn’t explicitly extend another than the ones show about it. We’ll get into
class, implicitly extends Object. is the way to thinktle later.)
3O SINCE$OGEXTENDS#ANINE ITDOESNTDIRECTLYEXTEND/BJECT the full story a lit
ALTHOUGHITDOESEXTENDITINDIRECTLY ANDTHESAMEISTRUE
FOR#ANINE BUT!NIMALDOESDIRECTLYEXTEND/BJECT
208 chapter 8
interfaces and polymorphism

So what’s in this ultra-super-megaclass Object?


)FYOUWERE*AVA WHATBEHAVIORWOULDYOUWANTEVERY
OBJECTTOHAVE(MMMMLETSSEEHOWABOUTA Object
METHODTHATLETSYOUlNDOUTIFONEOBJECTISEQUAL
TOANOTHEROBJECT7HATABOUTAMETHODTHATCAN boolean equals()
TELLYOUTHEACTUALCLASSTYPEOFTHATOBJECT-AYBEA Class getClass() the methods
METHODTHATGIVESYOUAHASHCODEFORTHEOBJECT SO int hashCode() Just SOME of .
YOUCANUSETHEOBJECTINHASHTABLESWELLTALKABOUT String toString() of class Object
*AVASHASHTABLESINCHAPTERANDAPPENDIX" 
/H HERESAGOODONEˆAMETHODTHATPRINTSOUTA
3TRINGMESSAGEFORTHATOBJECT
YourClassHere Every class you write inherits all the
!NDWHATDOYOUKNOW!SIFBYMAGIC CLASS/BJECT methods of class Object. The classes
DOESINDEEDHAVEMETHODSFORTHOSEFOURTHINGS
4HATSNOTALL THOUGH BUTTHESEARETHEONESWE
you’ve written inherited methods you
REALLYCAREABOUT didn’t even know you had.

1 equals(Object o)
3 hashCode()
Dog a = new Dog();
Cat c = new Cat(); Cat c = new Cat();
System.out.println(c.hashCode());
if (a.equals(c)) { File Edit Window Help Drop
shcode
Prints out a ha (for
System.out.println(“true”);
} else { % java TestObject
System.out.println(“false”); for the object as a
} 8202111
now, think of it
File Edit Window Help Stop unique ID).
e
% java TestObject
Tells you if two objects ar
false considered ‘equal’ (we’ll talk
about what ‘equal’ really 4 toString()
means in appendix B). Cat c = new Cat();
System.out.println(c.toString());
File Edit Window Help LapseIntoComa

% java TestObject
2 getClass()
Cat c = new Cat(); Cat@7d277f
System.out.println(c.getClass());
ring message
Prints out a Stof the class
File Edit Window Help Faint

% java TestObject Gives you back the with the name number we
class that object was and some other ut.
class Cat
instantiated from. rarely care abo

you are here4 209


Object and abstract classes

there are no
Dumb Questions Q: /+ BACKTOCLASS/BJECT Q: )FITSSOGOODTOUSE

Q: )SCLASS/BJECTABSTRACT
BEINGNON ABSTRACTSO)GUESS
THATMEANSITSCONCRETE (/7
CANYOULETSOMEBODYMAKEAN
POLYMORPHICTYPES WHY
DONTYOUJUSTMAKE!,,YOUR
METHODSTAKEANDRETURNTYPE
A: .O7ELL NOTINTHEFORMAL
*AVASENSEANYWAY/BJECTISA
/BJECTOBJECT)SNTTHATJUST
ASWEIRDASMAKINGAN!NIMAL
/BJECT

NON ABSTRACTCLASSBECAUSEITS
GOTMETHODIMPLEMENTATION
OBJECT
A: !HHHHTHINKABOUTWHAT
WOULDHAPPEN&ORONETHING
CODETHATALLCLASSESCANINHERIT
ANDUSEOUT OF THE BOX WITHOUT
A: 'OODQUESTION7HYIS
ITACCEPTABLETOMAKEANEW
YOUWOULDDEFEATTHEWHOLE
POINTOF@TYPE SAFETY ONE
HAVINGTOOVERRIDETHEMETHODS /BJECTINSTANCE"ECAUSE OF*AVASGREATESTPROTECTION
SOMETIMESYOUJUSTWANTA MECHANISMSFORYOURCODE7ITH
TYPE SAFETY *AVAGUARANTEESTHAT
Q: 4HENCANYOUOVERRIDE
GENERICOBJECTTOUSEAS WELL AS
ANOBJECT!LIGHTWEIGHTOBJECT
"YFAR THEMOSTCOMMONUSEOF
YOUWONTASKTHEWRONGOBJECT
TODOSOMETHINGYOUMEANTTO
THEMETHODSIN/BJECT
ANINSTANCEOFTYPE/BJECTISFOR ASKOFANOTHEROBJECTTYPE,IKE

A: 3OMEOFTHEM"UTSOMEOF
THEMAREMARKEDfinal WHICH
THREADSYNCHRONIZATIONWHICH
YOULLLEARNABOUTINCHAPTER 
ASKA&ERRARIWHICHYOUTHINKISA
4OASTER TOCOOKITSELF
"UTTHETRUTHIS YOUDONTHAVE
&ORNOW JUSTSTICKTHATONTHE
MEANSYOUCANTOVERRIDETHEM BACKBURNERANDASSUMETHAT TOWORRYABOUTTHATFIERY&ERRARI
9OUREENCOURAGEDSTRONGLY TO YOUWILLRARELYMAKEOBJECTSOF SCENARIO EVENIFYOUDOUSE
OVERRIDEHASH#ODE EQUALS TYPE/BJECT EVENTHOUGHYOU /BJECTREFERENCESFOREVERYTHING
ANDTO3TRING INYOUROWN CAN "ECAUSEWHENOBJECTSARE
CLASSES ANDYOULLLEARNHOWTO REFERREDTOBYAN/BJECT
DOTHATALITTLELATERINTHEBOOK
"UTSOMEOFTHEMETHODS LIKE Q: 3OISITFAIRTOSAYTHATTHE
REFERENCETYPE *AVATHINKSITS
REFERRINGTOANINSTANCEOFTYPE
GET#LASS DOTHINGSTHATMUST MAINPURPOSEFORTYPE/BJECT /BJECT!NDTHATMEANSTHE
WORKINASPECIFIC GUARANTEED ISSOTHATYOUCANUSEITFORA ONLYMETHODSYOUREALLOWEDTO
WAY POLYMORPHICARGUMENTAND CALLONTHATOBJECTARETHEONES
RETURNTYPE,IKEIN!RRAY,IST DECLAREDINCLASS/BJECT3OIF
Q: )F!RRAY,ISTMETHODSARE
GENERICENOUGHTOUSE/BJECT A: 4HE/BJECTCLASSSERVES
YOUWERETOSAY

Object o = new Ferrari();


THENWHATDOESITMEANTOSAY TWOMAINPURPOSESTOACTASA o.goFast(); //Not legal!
!RRAY,IST$OT#OM)THOUGHT POLYMORPHICTYPEFORMETHODS
)WASRESTRICTINGTHE!RRAY,ISTTO THATNEEDTOWORKONANYCLASS 9OUWOULDNTEVENMAKEITPAST
HOLDONLY$OT#OMOBJECTS THATYOUORANYONEELSEMAKES THECOMPILER
ANDTOPROVIDEREALMETHODCODE

A: 9OUWERERESTRICTINGIT
0RIORTO*AVA !RRAY,ISTS
THATALLOBJECTSIN*AVANEEDAT
RUNTIMEANDPUTTINGTHEMIN
"ECAUSE*AVAISASTRONGLY TYPED
LANGUAGE THECOMPILERCHECKS
CLASS/BJECTMEANSALLOTHER TOMAKESURETHATYOURECALLING
COULDNTBERESTRICTED4HEY CLASSESINHERITTHEM 3OMEOF AMETHODONANOBJECTTHATS
WEREALLESSENTIALLYWHATYOU THEMOSTIMPORTANTMETHODSIN ACTUALLYCAPABLEOFRESPONDING
GETIN*AVATODAYIFYOUWRITE /BJECTARERELATEDTOTHREADS )NOTHERWORDS YOUCANCALLA
!RRAY,IST/BJECT)NOTHER ANDWELLSEETHOSELATERINTHE METHODONANOBJECTREFERENCE
WORDS AN!RRAY,ISTRESTRICTED BOOK ONLYIFTHECLASSOFTHEREFERENCE
TOANYTHINGTHATSAN/BJECT
TYPEACTUALLYHASTHEMETHOD
WHICHMEANSANYOBJECTIN*AVA
7ELLCOVERTHISINMUCHGREATER
INSTANTIATEDFROMANYCLASSTYPE
DETAILALITTLELATER SODONTWORRY
7ELLCOVERTHEDETAILSOFTHISNEW
IFTHEPICTUREISNTCRYSTALCLEAR
TYPESYNTAXLATERINTHEBOOK

210 chapter 8
interfaces and polymorphism

Using polymorphic references of type Object has a price...


"EFOREYOURUNOFFANDSTARTUSINGTYPE/BJECTFORALLYOURULTRA mEXIBLEARGUMENTANDRETURN
TYPES YOUNEEDTOCONSIDERALITTLEISSUEOFUSINGTYPE/BJECTASAREFERENCE!NDKEEPINMIND
THATWERENOTTALKINGABOUTMAKINGINSTANCESOFTYPE/BJECTWERETALKINGABOUTMAKING
INSTANCESOFSOMEOTHERTYPE BUTUSINGAREFERENCEOFTYPE/BJECT
7HENYOUPUTANOBJECTINTOAN!RRAY,IST$OG ITGOESINASA$OG ANDCOMESOUTASA$OG

Make an ArrayList declared


ArrayList<Dog> myDogArrayList = new ArrayList<Dog>();
to hold Dog objects.
Dog aDog = new Dog(); Make a Dog.
myDogArrayList.add(aDog); Add the Dog to the list. e list
iable.
to a new Dog reference varreturn
As sig n th e Do g fr om th g
get() method declares a Do
Dog d = myDogArrayList.get(0);
(Think of it as though the List<Dog>.)
type because you used Array
"UTWHATHAPPENSWHENYOUDECLAREITAS!RRAY,IST/BJECT)FYOUWANTTOMAKEAN!RRAY,IST
THATWILLLITERALLYTAKEANYKINDOF/BJECT YOUDECLAREITLIKETHIS

ArrayList<Object> myDogArrayList = new ArrayList<Object>();


Make an ArrayList declared
to hold any type of Object.
Dog aDog = new Dog(); Make a Dog. (These two steps are the same.)
myDogArrayList.add(aDog); Add the Dog to the list.
"UTWHATHAPPENSWHENYOUTRYTOGETTHE$OGOBJECTANDASSIGNITTOA$OGREFERENCE

myD
m
Dog d = myDogArrayList.get(0); NO!! Won’t compile!! When you use ArrayList<Object>, the get() method
returns type Object. The Compiler knows only that the object inherits from
Object (somewhere in its inheritance tree) but it doesn’t know it’s a Dog !!
%VERYTHINGCOMESOUTOFAN!RRAY,IST/BJECTASAREFERENCEOFTYPE/BJECT REGARDLESSOFWHATTHE
ACTUALOBJECTIS ORWHATTHEREFERENCETYPEWASWHENYOUADDEDTHEOBJECTTOTHELIST

The objects go IN
as SoccerBall, Objects come out of
Fish, Guitar, and an ArrayList<Object>
Car. acting like they’re
generic instances
of class Object. The
ArrayList<Object> Compiler cannot
assume the object
But they come that comes out is of
OUT as though any type other than
they were of type Object.
Object. Object Object Object Object

you are here4 211


When a Dog loses its Dogness

When a Dog won’t act like a Dog I don’t know what you’re
talking about. Sit? Stay?
4HEPROBLEMWITHHAVINGEVERYTHINGTREATED bark? Hmmmm... I don’t
POLYMORPHICALLYASAN/BJECTISTHATTHEOBJECTS recall knowing those.
APPEARTOLOSEBUTNOTPERMANENTLY THEIR
TRUEESSENCE4HE$OGAPPEARSTOLOSEITSDOGNESS
,ETSSEEWHATHAPPENSWHENWEPASSA$OGTO
AMETHODTHATRETURNSAREFERENCETOTHESAME
$OGOBJECT BUTDECLARESTHERETURNTYPEASTYPE
/BJECTRATHERTHAN$OG

n t h o u g h t he methodthe
ve og
public void go() {
n’t work! E ery same D
Dog aDog = new Dog(); This line wao reference to the evturn type Object rned
BAD g = getObject(aDog);
Dog sameDog g returned referred to, the r you assign the retu
L } argument compiler won’t let bject.
means the to anything but O
reference
public Object getObject(Object o) {
a
return o;
re tu rn ing a re fe re nc e to the same Dog, but asNote:
} We’re This part is perfectly leg
al.
return type of Object. e get() method works when you have
this is similar to how th ther than an ArrayList<Dog>.
an ArrayList<Object> ra
File Edit Window Help Remember

DogPolyTest.java:10: incompatible types


The compiler doesn’t know that the
found : java.lang.Object
thing returned from the method is
actually a Dog, so it won’t let you
required: Dog
assign it to a Dog reference. (You’ll
Dog sameDog = takeObjects(aDog);
see why on the next page.)
1 error ^

public void go() { This works (although it may not be very


Dog aDog = new Dog(); useful, as you’ll see in a moment) because you
GOOD Object sameDog = getObject(aDog); can assign ANYTHING to a reference of type
J } Object, since every class passes the IS-A test
for Object. Every object in Java is an instance
public Object getObject(Object o) { of type Object, because every class in Java has
return o; Object at the top of its inheritance tree.
}
212 chapter 8
interfaces and polymorphism

Objects don’t bark.


3ONOWWEKNOWTHATWHENANOBJECTIS
REFERENCEDBYAVARIABLEDECLAREDASTYPE
/BJECT ITCANTBEASSIGNEDTOAVARIABLE
o
DECLAREDWITHTHEACTUALOBJECTSTYPE
D og t
!NDWEKNOWTHATTHISCANHAPPENWHEN objec
Object
ARETURNTYPEORARGUMENTISDECLARED
ASTYPE/BJECT ASWOULDBETHECASE
FOREXAMPLE WHENTHEOBJECTISPUT When you get an object reference from
INTOAN!RRAY,ISTOFTYPE/BJECTUSING
!RRAY,IST/BJECT"UTWHATARETHE
an ArrayList<Object> (or any method
IMPLICATIONSOFTHIS)SITAPROBLEMTO that declares Object as the return type),
HAVETOUSEAN/BJECTREFERENCEVARIABLE it comes back as a polymorphic reference
TOREFERTOA$OGOBJECT,ETSTRYTOCALL type of Object. So you have an Object
$OGMETHODSONOUR$OG 4HAT #OMPILER reference to (in this case) a Dog instance.
4HINKS )S !N /BJECT
sa
Object o = al.get(index); e . C la s s Object ha an call
c
This is fin() method, so you t in Java.
int i = o.hashCode(); hashCode hod on ANY objec
that met
o.bark();
o.b
o.ba
Won’t compile! Can’t do this!! The Object class has no idea what
it means to bark(). Even though YOU know it’s
really a Dog at that index, the compiler doesn’t..

hashCod
e( )
The compiler decides whether
you can call a method based
on the reference type, not the
actual object type. o
D og t
objec
%VENIFYOUKNOWTHEOBJECTISCAPABLE Object
hBUTITREALLYISA$OG HONESTv THE
COMPILERSEESITONLYASAGENERIC/BJECT Object
The method you’re calling on a
&ORALLTHECOMPILERKNOWS YOUPUTA equals() reference MUST be in the class of
"UTTONOBJECTOUTTHERE/RA-ICROWAVE getClass() that reference type. Doesn’t matter
OBJECT/RSOMEOTHERTHINGTHATREALLY hashCode() what the actual object is.
DOESNTKNOWHOWTOBARK toString()
4HECOMPILERCHECKSTHECLASSOFTHE
REFERENCETYPEˆNOTTHEOBJECTTYPEˆTO o.hashCode();
SEEIFYOUCANCALLAMETHODUSINGTHAT
REFERENCE
The “o” reference was declared as type
Object, so you can call methods only if
those methods are in class Object..
you are here4 213
objects are Objects

He treats me like an
Object. But I can do so
much more...if only he’d see
me for what I really am.

Get in touch with your inner Object.


!NOBJECTCONTAINSEVERYTHINGITINHERITSFROMEACHOFITS
SUPERCLASSES4HATMEANSEVERYOBJECTˆREGARDLESSOFITS
ACTUALCLASSTYPEˆISALSOANINSTANCEOFCLASS/BJECT4HAT
MEANSANYOBJECTIN*AVACANBETREATEDNOTJUSTASA$OG
"UTTON OR3NOWBOARD BUTALSOASAN/BJECT7HENYOU
SAYnew Snowboard() YOUGETASINGLEOBJECTONTHE
HEAPˆA3NOWBOARDOBJECTˆBUTTHAT3NOWBOARDWRAPS
ITSELFAROUNDANINNERCOREREPRESENTINGTHE/BJECT
CAPITALh/v PORTIONOFITSELF

Object

equals() A single object


getClass() on the heap.
hashCode()
)
toString() d( turn
()
re

has
sh

g () h
rin
Co
t
t oS

de(

Object
)
equ

Snowboard Snowboard inherits methods


()

s(
al

equals() from superclass Object, and s


)
()
get

la
s

getC
rol

getClass() adds four more.


Ai

nt

() o
r

hashCode()
loseC
toString()
Snowboard
turn()
Sn
ow b je ct
shred()
oard ob
getAir()
loseControl()

There is only ONE object on the heap here. A Snowboard


object. But it contains both the Snowboard class parts of
itself and the Object class parts of itself.
214 chapter 8
interfaces and polymorphism

‘Polymorphism’ means When you put


‘many forms’. an object in an
You can treat a Snowboard as a ArrayList<Object>, you
Snowboard or as an Object. can treat it only as an
)FAREFERENCEISLIKEAREMOTECONTROL THE
Object, regardless of
REMOTECONTROLTAKESONMOREANDMOREBUTTONS the type it was when
ASYOUMOVEDOWNTHEINHERITANCETREE! you put it in.
REMOTECONTROLREFERENCE OFTYPE/BJECTHAS
ONLYAFEWBUTTONSˆTHEBUTTONSFORTHEEXPOSED When you get a
METHODSOFCLASS/BJECT"UTAREMOTECONTROL reference from an
OFTYPE3NOWBOARDINCLUDESALLTHEBUTTONSFROM ArrayList<Object>, the
CLASS/BJECT PLUSANYNEWBUTTONSFORNEW reference is always of
METHODS OFCLASS3NOWBOARD4HEMORESPECIlC
type Object.
THECLASS THEMOREBUTTONSITMAYHAVE
/FCOURSETHATSNOTALWAYSTRUEASUBCLASSMIGHT That means you get an
NOTADDANYNEWMETHODS BUTSIMPLYOVERRIDE Object remote control.
THEMETHODSOFITSSUPERCLASS4HEKEYPOINTIS
THATEVENIFTHEOBJECTISOFTYPE3NOWBOARD AN
/BJECTREFERENCETOTHE3NOWBOARDOBJECTCANTSEE
THE3NOWBOARD SPECIlCMETHODS

)
Snowboard s = new Snowboard(); d( turn
()
re

has
sh

g () h
Object o = s; rin
Co
t
t oS

de(

Object
)
equ

()

s(
al

s
)
()
ge

la
s

getC
rol
tA

nt

()
ir

o
loseC
s

Snowboard
The Snowboard remote control Sn
ow b je ct
(reference) has more buttons than fewer methods here... oard ob
an Object remote control. The o
Snowboard remote can see the full
Snowboardness of the Snowboard The Object reference can see only the
object. It can access all the methods Object parts of the Snowboard object.
in Snowboard, including both the It can access only the methods of class
inherited Object methods and the Object. It has fewer buttons than the
methods from class Snowboard. Snowboard remote control.
you are here4 215
casting objects

Wait a minute... what good


is a Dog if it comes out of an
ArrayList<Object> and it can’t do Casting an object reference
any Dog things? There’s gotta be a back to its real type.
way to get the Dog back to a state
of Dogness...

o
D og t
objec
Object
I hope it doesn’t hurt.
)TSREALLYSTILLA$OGOBJECT BUTIFYOUWANTTOCALL
And what’s so wrong with
staying an Object? OK, I can’t
$OG SPECIlCMETHODS YOUNEEDAREFERENCEDECLARED
fetch, sure, but I can give you
ASTYPE$OG)FYOURESURE
THEOBJECTISREALLYA
a real nice hashcode.
$OG YOUCANMAKEANEW$OGREFERENCETOITBY
COPYINGTHE/BJECTREFERENCE ANDFORCINGTHAT
COPYTOGOINTOA$OGREFERENCEVARIABLE USINGA
CAST$OG 9OUCANUSETHENEW$OGREFERENCETO
CALL$OGMETHODS

Object o = al.get(index);
ct back to
Dog d = (Dog) o; cast the Okbnjeow is there.
d.roam(); a Dog we

o
D og t
objec
Object

Cast the so-called ‘Object’ (but


we know he’s actually a Dog) to d
type Dog, so that you can treat
Dog
him like the Dog he really is.

)FYOURENOTSUREITSA$OG YOUCANUSETHE
instanceofOPERATORTOCHECK"ECAUSEIF
YOUREWRONGWHENYOUDOTHECAST YOULLGETA
#LASS#AST%XCEPTIONATRUNTIMEANDCOMETOA
GRINDINGHALT
if (o instanceof Dog) {
Dog d = (Dog) o;
}

216 chapter 8
interfaces and polymorphism

So now you’ve seen how much Java


cares about the methods in the
class of the reference variable.
You can call a method on an object only if
the class of the reference variable has that
method.
Think of the public methods in your class as
your contract, your promise to the outside
world about the things you can do.

7HENYOUWRITEACLASS YOUALMOSTALWAYSEXPOSESOME
OFTHEMETHODSTOCODEOUTSIDETHECLASS4OEXPOSEA
METHODMEANSYOUMAKEAMETHODACCESSIBLE USUALLYBY
MARKINGITPUBLIC
)MAGINETHISSCENARIOYOUREWRITINGCODEFORASMALL
BUSINESSACCOUNTINGPROGRAM!CUSTOMAPPLICATION
FORh3IMONS3URF3HOPv4HEGOODRE
Account
USERTHATYOUARE YOUFOUNDAN!CCOUNT
CLASSTHATAPPEARSTOMEETYOURNEEDS debit(double amt)
PERFECTLY ACCORDINGTOITSDOCUMENTATION
ANYWAY%ACHACCOUNTINSTANCEREPRESENTS credit(double amt)
ANINDIVIDUALCUSTOMERSACCOUNTWITHTHE
double getBalance()
STORE3OTHEREYOUAREMINDINGYOUROWN
BUSINESSINVOKINGTHECREDIT ANDDEBIT
METHODSONANACCOUNTOBJECTWHENYOUREALIZEYOU
NEEDTOGETABALANCEONANACCOUNT.OPROBLEMˆ
THERESAGET"ALANCE METHODTHATSHOULDDONICELY
%XCEPTWHENYOUINVOKETHEGET"ALANCE METHOD
THEWHOLETHINGBLOWSUPATRUNTIME&ORGETTHE
DOCUMENTATION THECLASSDOESNOTHAVETHATMETHOD
9IKES
"UTTHATWONTHAPPENTOYOU BECAUSEEVERYTIMEYOU
USETHEDOTOPERATORONAREFERENCEADO3TUFF THE
COMPILERLOOKSATTHEREFERENCETYPETHETYPE@AWAS
DECLAREDTOBE ANDCHECKSTHATCLASSTOGUARANTEETHE
CLASSHASTHEMETHOD ANDTHATTHEMETHODDOESINDEED
TAKETHEARGUMENTYOUREPASSINGANDRETURNTHEKINDOF
VALUEYOUREEXPECTINGTOGETBACK
*USTREMEMBERTHATTHECOMPILERCHECKSTHECLASSOFTHE
REFERENCEVARIABLE NOTTHECLASSOFTHEACTUALOBJECTATTHE
OTHERENDOFTHEREFERENCE

you are here4 217


modifying a class tree

What if you need to change


the contract?
/+ PRETENDYOUREA$OG9OUR$OGCLASS
ISNTTHEONLYCONTRACTTHATDElNESWHOYOU
ARE2EMEMBER YOUINHERITACCESSIBLEWHICH
USUALLYMEANSPUBLIC METHODSFROMALLOF
YOURSUPERCLASSES
4RUE YOUR$OGCLASSDElNESACONTRACT
"UTNOTALLOFYOURCONTRACT YiX`e
%VERYTHINGINCLASS#ANINEISPARTOFYOUR gfn\i
CONTRACT
%VERYTHINGINCLASS!NIMALISPARTOFYOUR
CONTRACT Think about what YOU would do if YOU were
%VERYTHINGINCLASS/BJECTISPARTOFYOUR the Dog class programmer and needed to
CONTRACT modify the Dog so that it could do Pet things,
!CCORDINGTOTHE)3 !TEST YOUAREEACHOF too. We know that simply adding new Pet be-
THOSETHINGSˆ#ANINE !NIMAL AND/BJECT haviors (methods) to the Dog class will work,

"UTWHATIFTHEPERSONWHODESIGNEDYOUR and won’t break anyone else’s code.


CLASSHADINMINDTHE!NIMALSIMULATION But... this is a PetShop program. It has more
PROGRAM ANDNOWHEWANTSTOUSEYOUCLASS
than just Dogs! And what if someone wants
$OG FORA3CIENCE&AIR4UTORIALON!NIMAL
OBJECTS to use your Dog class for a program that has
wild Dogs? What do you think your options
4HATS/+ YOUREPROBABLYREUSABLEFORTHAT
might be, and without worrying about how
"UTWHATIFLATERHEWANTSTOUSEYOUFORA Java handles things, just try to imagine how
0ET3HOPPROGRAM9OUDONTHAVEANY0ET
you’d like to solve the problem of modifying
BEHAVIORS!0ETNEEDSMETHODSLIKEBE&RIENDLY
ANDPLAY  some of your Animal classes to include Pet
behaviors.
/+ NOWPRETENDYOURETHE$OGCLASS
PROGRAMMER.OPROBLEM RIGHT*USTADD Stop right now and think about it,
SOMEMOREMETHODSTOTHE$OGCLASS9OU before you look at the next page where we
WONTBEBREAKINGANYONEELSESCODEBY
begin to reveal everything.
ADDINGMETHODS SINCEYOUARENTTOUCHING
THEEXISTINGMETHODSTHATSOMEONEELSESCODE (thus rendering the whole exercise completely useless, robbing
MIGHTBECALLINGON$OGOBJECTS you of your One Big Chance to burn some brain calories)
#ANYOUSEEANYDRAWBACKSTOTHATAPPROACH
ADDING0ETMETHODSTOTHE$OGCLASS 

218 chapter 8
interfaces and polymorphism

Let’s explore some design options


for reusing some of our existing
classes in a PetShop program.
/NTHENEXTFEWPAGES WEREGOINGTOWALKTHROUGH
SOMEPOSSIBILITIES7ERENOTYETWORRIEDABOUT
WHETHER*AVACANACTUALLYDOWHATWECOMEUPWITH
7ELLCROSSTHATBRIDGEONCEWEHAVEAGOODIDEAOF
SOMEOFTHETRADEOFFS

1 Option one
We take the easy path, and put pet
methods in class Animal.
a l l t he pet p here
Pros: put d code u
All the Animals will instantly inherit metho heritance.
the pet behaviors. We won’t have to for in
touch the existing Animal subclasses
at all, and any Animal subclasses Animal
created in the future will also get to
take advantage of inheriting those
methods. That way, class Animal can
be used as the polymorphic type in
any program that wants to treat the
Animals as pets Canine

Cons: Hippo

So... when was the last time you


saw a Hippo at a pet shop? Lion? Feline
Wolf? Could be dangerous to give
non-pets pet methods. Dog

Also, we almost certainly WILL


have to touch the pet classes
Cat
like Dog and Cat, because (in Wolf
our house, anyway) Dogs
and Cats tend to imple- Lion
ment pet behaviors Tiger
VERY differently.

you are here4 219


modifying existing classes

2 Option t wo
We start with Option One, putting the pet methods
in class Animal, but we make the methods abstract,
forcing the Animal subclasses to override them.

Pros:
That would give us all the benefits of Option One, but with- ds
out the drawback of having non-pet Animals running around p e t metho
l th e hn o
with pet methods (like beFriendly()). All Animal classes put aelre, but wints. Make all
would have the method (because it’s in class Animal), but up h ementatio abstract.
because it’s abstract the non-pet Animal classes won’t impl methods
inherit any functionality. All classes MUST override the pet
methods, but they can make the methods “do-nothings”.

Animal
Cons:
Because the pet methods in the Animal class are all
abstract, the concrete Animal subclasses are forced to
implement all of them. (Remember, all abstract methods
MUST be implemented by the first concrete subclass
down the inheritance tree.) What a waste of time! Canine
You have to sit there and type in each and every
Hippo
pet method into each and every concrete non-
pet class, and all future subclasses as well.
And while this does solve the problem of Feline
non-pets actually DOING pet things
(as they would if they inherited pet Dog
functionality from class Animal), the
contract is bad. Every non-pet
class would be announcing to the
world that it, too, has those Cat
Wolf
pet methods, even though
the methods wouldn’t
actually DO anything Lion
when called. Tiger

This approach doesn’t


look good at all. It just Ask me to be friendly.
seems wrong to stuff No, seriously... ask me.
everything into class Animal I have the method.
that more than one Animal type
might need, UNLESS it applies to
ALL Animal subclasses.

220 chapter 8
interfaces and polymorphism

3 Option three
Put the pet methods ONLY in the
classes where they belong.

Pros:
No more worries about Hippos greeting you at the
door or licking your face. The methods are where
they belong, and ONLY where they belong. Dogs can
implement the methods and Cats can implement the
m e t h o d s O NLY in the
s,
methods, but nobody else has to know about them.
Put the plaesstes that can be pet
a l c
Anim of in Animal.
Cons: instead
Two Big Problems with this approach. First off, you’d
have to agree to a protocol, and all programmers of
pet Animal classes now and in the future would have
to KNOW about the protocol. By protocol, we mean Animal
the exact methods that we’ve decided all pets should
have. The pet contract without anything to back it up.
But what if one of the programmers gets it just a tiny
bit wrong? Like, a method takes a String when it was
supposed to take an int? Or they named it doFriendly()
instead of beFriendly()? Since it isn’t in a contract, Canine
the compiler has no way to check you to see if you’ve
Hippo
implemented the methods correctly. Someone
could easily come along to use the pet Animal
classes and find that not all of them work Feline
quite right.
Dog
And second, you don’t get to use
polymorphism for the pet methods.
Every class that needs to use
pet behaviors would have to Cat
Wolf
know about each and every
class! In other words,
Lion
you can’t use Animal
Tiger
as the polymorphic
type now, because the
compiler won’t let you call
a Pet method on an Animal
reference (even if it’s really a
Dog object) because class Animal
doesn’t have the method.

you are here4 221


multiple inheritance?

So what we REALLY need is:


Æ A way to have pet behavior in just the pet classes
Æ A way to guarantee that all pet classes have all of the same
methods defined (same name, same arguments, same return
types, no missing methods, etc.), without having to cross your
fingers and hope all the programmers get it right.
Æ A way to take advantage of polymorphism so that all pets can have
their pet methods called, without having to use arguments, return
types, and arrays for each and every pet class.

It looks like we need TWO


superclasses at the top

ct
n e w abstra and
ke a Pet,
We ma lass called t methods.
superc all the pe
give it Pet Animal

Canine

Hippo

Feline

Dog

Dog ex
Cat Lion Wolf Pet an tends both
d Anim
al
ends
Cat now ext nimal Tiger

from both A it gets


AND Pet, so of both.
the methods The non-pet Animals
don’t have any inherited
Pet stuff.

222 chapter 8
interfaces and polymorphism

There’s just one problem with the “two superclasses” approach...

It’s called “multiple inheritance”


and it can be a Really Bad Thing.
That is, if it were possible to do in Java.

But it isn’t, because multiple inheritance has a problem


known as The Deadly Diamond of Death.

Deadly Diamond of Death


DigitalRecorder
oth
r a n d D V DBurner b , int i
CDBurne m DigitalRecorder
inherit fro verride the burn()
burn()

and both ooth inherit the “i”


method. B riable. ce
instance va t t h e “ i” instan Burner
CDBurner DVDBurner ha D
Imagine tis used by both Cifferent
burn()
variable Burner, with d ComboDrive
and DVDhat happens if of “i”?
burn()

values. W use both values


needs to
ComboDrive
Problem with
Which burn() multiple inheritance.
call burn() o method runs when you
n the Combo
Drive?

!LANGUAGETHATALLOWSTHE$EADLY$IAMONDOF$EATHCANLEADTO
SOMEUGLYCOMPLEXITIES BECAUSEYOUHAVETOHAVESPECIALRULESTO
DEALWITHTHEPOTENTIALAMBIGUITIES!NDEXTRARULESMEANSEXTRA
WORKFORYOUBOTHINLEARNINGTHOSERULESANDWATCHINGOUTFOR
THOSEhSPECIALCASESv*AVAISSUPPOSEDTOBESIMPLE WITHCONSISTENT
RULESTHATDONTBLOWUPUNDERSOMESCENARIOS3O*AVAUNLIKE
# PROTECTSYOUFROMHAVINGTOTHINKABOUTTHE$EADLY$IA
MONDOF$EATH"UTTHATBRINGSUSBACKTOTHEORIGINALPROBLEM
(OWDOWEHANDLETHE!NIMAL0ETTHING

you are here4 223


interfaces

Interface to the rescue!


*AVAGIVESYOUASOLUTION!NINTERFACE.OTA'5)INTERFACE NOTTHEGENERIC
USEOFTHEWORDINTERFACEASIN h4HATSTHEPUBLICINTERFACEFORTHE"UTTON
CLASS!0) vBUTTHE*AVAKEYWORDinterface
!*AVAINTERFACESOLVESYOURMULTIPLEINHERITANCEPROBLEMBYGIVINGYOU
MUCHOFTHEPOLYMORPHICBENElTSOFMULTIPLEINHERITANCEWITHOUTTHEPAIN
ANDSUFFERINGFROMTHE$EADLY$IAMONDOF$EATH$$$ 
4HEWAYINWHICHINTERFACESSIDE STEPTHE$$$ISSURPRISINGLYSIMPLEMAKE
ALLTHEMETHODSABSTRACT4HATWAY THESUBCLASSMUSTIMPLEMENTTHEMETHODS
REMEMBER ABSTRACTMETHODSMUSTBEIMPLEMENTEDBYTHElRSTCONCRETE
SUBCLASS SOATRUNTIMETHE*6-ISNTCONFUSEDABOUTWHICHOFTHETWO
INHERITEDVERSIONSITSSUPPOSEDTOCALL

Pet A Java interface is like a


100% pure abstract class.
abstract void beFriendly();
d s in a n in t erface are
abstract void play(); All metho any class that IS-A
abstract, so implement (i.e. override)
Pet MUST of Pet.
the methods

To DEFINE an interface:
public interface Pet {...}

Use the ke
instead of yword “interface”
“class”

To IMPLEMENT an interface:
public class Dog extends Canine implements Pet {...}

ey w o r d “i m p le ments” followed
Use the k c e n a me. Note that ou
by th e in t er f a ce y
en y o u im p le m ent an interfa
w h
end a class
still get to ext
224 chapter 8
interfaces and polymorphism

Making and Implementing interface m


the Pet interface abstract, soettyhopids are implicitly publ
ic an
is optional (in fact in ‘public’ and ‘abstracdt’
ng
style’ to type , it ’s not considered
‘g
just to reinforcthe e words in, but we did heoored
u sa y ‘i n t e r face’ instead been slaves to fashit, and because we’ve never
Yo e ion...)
of ‘class’ her
t e r f a c e m e thods are in
All in end
public interface Pet {
b st r a c t , so they MUST y have
a emember, th e
public abstract void beFriendly(); semicolons. R
public abstract void play(); no body!
}

ements’
You say ‘implth
nimal me
Dog IS-AISA-A Pet followed by ace e.na
and Dog public class Dog extends Canine implements Pet { of th
e interf

public void beFriendly() {...}


You SAID
public void play() {..} implement tyhou are a Pet, so you M
contract. No e Pet methods. It’s y UST
instead of se tice the curly braces our
micolons.
public void roam() {...}

public void eat() {...} These are just


overriding methonodsrm
.
al
}

there are no
Dumb Questions
Q: 7AITAMINUTE INTERFACESDONT
TYPES YOUCANPASSANYTHINGTHAT
IMPLEMENTSTHATINTERFACE!NDTHINK
TOEXTEND9OUCOULDJUSTGIVETHEM
THEINTERFACEANDSAY h(ERE )DONT
REALLYGIVEYOUMULTIPLEINHERITANCE ABOUTITˆWITHANINTERFACE ACLASS CAREWHATKINDOFCLASSINHERITANCE
BECAUSEYOUCANTPUTANY DOESNTHAVETOCOMEFROMJUSTONE STRUCTUREYOUCOMEFROM JUST
IMPLEMENTATIONCODEINTHEM)FALL INHERITANCETREE!CLASSCANEXTEND IMPLEMENTTHISINTERFACEANDYOULLBE
THEMETHODSAREABSTRACT WHATDOES ONECLASS ANDIMPLEMENTANINTERFACE GOODTOGOv
ANINTERFACEREALLYBUYYOU "UTANOTHERCLASSMIGHTIMPLEMENT 4HEFACTTHATYOUCANTPUTIN
THESAMEINTERFACE YETCOMEFROMA IMPLEMENTATIONCODETURNSOUTNOTTO
COMPLETELYDIFFERENTINHERITANCETREE
A: 0OLYMORPHISM POLYMORPHISM
POLYMORPHISM)NTERFACESARETHE
3OYOUGETTOTREATANOBJECTBYTHE
ROLEITPLAYS RATHERTHANBYTHECLASS
BEAPROBLEMFORMOSTGOODDESIGNS
BECAUSEMOSTINTERFACEMETHODS
WOULDNTMAKESENSEIFIMPLEMENTED
ULTIMATEINFLEXIBILITY BECAUSEIFYOU TYPEFROMWHICHITWASINSTANTIATED INAGENERICWAY)NOTHERWORDS MOST
USEINTERFACESINSTEADOFCONCRETE )NFACT IFYOUWROTEYOURCODETOUSE INTERFACEMETHODSWOULDNEEDTO
SUBCLASSESOREVENABSTRACTSUPERCLASS INTERFACES YOUWOULDNTEVENHAVETO BEOVERRIDDENEVENIFTHEMETHODS
TYPES ASARGUMENTSANDRETURN GIVEANYONEASUPERCLASSTHATTHEYHAD WERENTFORCEDTOBEABSTRACT

you are here4 225


interface polymorphism

Classes from different inheritance trees


can implement the same interface.
Robot

Pet Animal

Agent
RoboDog
Canine

Class RoboD Hippo


come from thoge do
A
esn’t
inheritance tr ni mal
gets to be a Peeet, !but it still Feline

Dog

Cat Lion Wolf

Tiger

7HENYOUUSEACLASSASAPOLYMORPHICTYPELIKEAN THEIRMETHODSINASEPARATETHREADOFEXECUTION
ARRAYOFTYPE!NIMALORAMETHODTHATTAKESA#ANINE )MPLEMENT2UNNABLE9OUGETTHEIDEA9OULL
ARGUMENT THEOBJECTSYOUCANSTICKINTHATTYPE LEARNMOREABOUT3ERIALIZABLEAND2UNNABLEINLATER
MUSTBEFROMTHESAMEINHERITANCETREE"UTNOTJUST CHAPTERS BUTFORNOW REMEMBERTHATCLASSESFROM
ANYWHEREINTHEINHERITANCETREETHEOBJECTSMUSTBE ANYPLACEINTHEINHERITANCETREEMIGHTNEEDTO
FROMACLASSTHATISASUBCLASSOFTHEPOLYMORPHICTYPE IMPLEMENTTHOSEINTERFACES.EARLYANYCLASSMIGHT
!NARGUMENTOFTYPE#ANINECANACCEPTA7OLFANDA WANTTOBESAVEABLEORRUNNABLE
$OG BUTNOTA#ATORA(IPPO
Better still, a class can implement
"UTWHENYOUUSEANINTERFACEASAPOLYMORPHIC multiple interfaces!
TYPELIKEANARRAYOF0ETS THEOBJECTSCANBE
FROMANYWHEREINTHEINHERITANCETREE4HEONLY !$OGOBJECT)3 !#ANINE AND)3 !!NIMAL AND
REQUIREMENTISTHATTHEOBJECTSAREFROMACLASSTHAT )3 !/BJECT ALLTHROUGHINHERITANCE"UTA$OG)3 !
IMPLEMENTSTHEINTERFACE!LLOWINGCLASSESINDIFFERENT 0ETTHROUGHINTERFACEIMPLEMENTATION ANDTHE$OG
INHERITANCETREESTOIMPLEMENTACOMMONINTERFACE MIGHTIMPLEMENTOTHERINTERFACESASWELL9OUCOULD
ISCRUCIALINTHE*AVA!0)$OYOUWANTANOBJECT SAY
TOBEABLETOSAVEITSSTATETOAlLE)MPLEMENTTHE public class Dog extends Animal implements
3ERIALIZABLEINTERFACE$OYOUNEEDOBJECTSTORUN Pet, Saveable, Paintable { ... }

226 chapter 8
interfaces and polymorphism

tic k
Make it S
BLUE
E D V IO LETSARE TT WO
2OSESA
RER
B U T I M PLEMEN
E
ONLYON
%X TEND
VALUES
S I N O NFAMILY CANHA
VE
*AVAWE
IG H
 ! * A VACLASS TPARENT
ARENTS/
NLY DTHA
LASS AN MPLE
3INGLE0 ARENTSUPERC "UTYOUCANI CES
P 
ONLYO N E YOU A R E EIN R FA
T E
S D E FI N ESWHO C E S A NDTHOS
CLAS N TE R FA
ULTIPLEI 
MENTM SYOUCANPLAY
E R O LE
DEFIN

How do you know whether to make a


class, a subclass, an abstract class, or
an interface?

 Make a class that doesn’t extend anything


(other than Object) when your new class doesn’t
pass the IS-A test for any other type.

 Make a subclass (in other words, extend a class)


only when you need to make a more specific
version of a class and need to override or add
new behaviors.

 Use an abstract class when you want to define


a template for a group of subclasses, and you
have at least some implementation code that all
subclasses could use. Make the class abstract
when you want to guarantee that nobody can
make objects of that type.

 Use an interface when you want to define a role


that other classes can play, regardless of where
those classes are in the inheritance tree.

you are here4 227


using super

Invoking the superclass


c la s s v e r sion of thte stuff
version of a method supe r n
es importa
method dcolasses could use
Q: 7HATIFYOUMAKEACONCRETESUBCLASS abstract class Report {
void runReport() {
that sub
ANDYOUNEEDTOOVERRIDEAMETHOD BUTYOU
// set-up report
WANTTHEBEHAVIORINTHESUPERCLASSVERSIONOF
}
THEMETHOD)NOTHERWORDS WHATIFYOUDONT void printReport() {
NEEDTOREPLACETHEMETHODWITHANOVERRIDE // generic printing
BUTYOUJUSTWANTTOADDTOITWITHSOME }
ADDITIONALSPECIlCCODE }

A: !HHHTHINKABOUTTHEMEANINGOFTHE
class BuzzwordsReport extends Report {

ss version,
call supercelaback and
WORD@EXTENDS/NEAREAOFGOOD//DESIGNLOOKS void runReport() {
ATHOWTODESIGNCONCRETECODETHATSMEANTTO super.runReport();
BEOVERRIDDEN)NOTHERWORDS YOUWRITEMETHOD buzzwordCompliance(); then com bclass-
CODEIN SAY ANABSTRACTCLASS THATDOESWORK printReport(); do some su uff
THATSGENERICENOUGHTOSUPPORTTYPICALCONCRETE specific st
IMPLEMENTATIONS"UT THECONCRETECODEISNT }
ENOUGHTOHANDLEALLOFTHESUBCLASS SPECIFIC void buzzwordCompliance() {...}
WORK3OTHESUBCLASSOVERRIDESTHEMETHOD }
ANDEXTENDSITBYADDINGTHERESTOFTHECODE
4HEKEYWORDSUPERLETSYOUINVOKEASUPERCLASS
VERSIONOFANOVERRIDDENMETHOD FROMWITHINTHE
SUBCLASS
If method code inside a
BuzzwordReport subclass says: e t h o d ( o verrides
super.runReport();
subclass mrclass version)
the supe
the runReport() method inside runReport()
the superclass Report will run buzzwordCompliance() superclass methods dden
runReport()
(including the overri
printReport() runReport()
Report
super.runReport();
BuzzwordReport
A reference to the subclass object
(BuzzwordReport) will always call
the subclass version of an overridden
method. That’s polymorphism. The super keyword is really a reference
But the subclass code can call to the superclass portion of an object.
super.runReport() to invoke the When subclass code uses super, as in
superclass version. super.runReport(), the superclass version of
the method will run.

228 chapter 8
interfaces and polymorphism

BULLET POINTS Q: 4HERESSTILLSOMETHING


STRANGEHEREYOUNEVER
 When you don’t want a class to be instantiated (in other words, you don’t
want anyone to make a new object of that class type) mark the class with the
EXPLAINEDHOWITISTHAT
!RRAY,IST$OGGIVESBACK$OG
abstract keyword. REFERENCESTHATDONTNEEDTOBE
CAST YETTHE!RRAY,ISTCLASSUSES
 An abstract class can have both abstract and non-abstract methods. /BJECTINITSMETHODS NOT$OG
OR$OT#OMORANYTHINGELSE 
If a class has even one abstract method, the class must be marked abstract.
 7HATSTHESPECIALTRICKGOINGON
 An abstract method has no body, and the declaration ends with a semicolon (no
curly braces).
WHENYOUSAY!RRAY,IST$OG

 All abstract methods must be implemented in the first concrete subclass in the
inheritance tree.
A: 9OURERIGHTFORCALLINGITA
SPECIALTRICK)NFACTITISASPECIAL
TRICKTHAT!RRAY,IST$OGGIVES
 Every class in Java is either a direct or indirect subclass of class Object (java.lang.
Object).
BACK$OGSWITHOUTYOUHAVING
TODOANYCAST SINCEITLOOKSLIKE
!RRAY,ISTMETHODSDONTKNOW
 Methods can be declared with Object arguments and/or return types.
ANYTHINGABOUT$OGS ORANYTYPE
You can call methods on an object only if the methods are in the class (or interface)
 used as the reference variable type, regardless of the actual object type. So, a
BESIDES/BJECT
4HESHORTANSWERISTHATTHE
reference variable of type Object can be used only to call methods defined in class COMPILERPUTSINTHECASTFORYOU
Object, regardless of the type of the object to which the reference refers. 7HENYOUSAY!RRAY,IST$OG
THEREISNOSPECIALCLASSTHATHAS
 A reference variable of type Object can’t be assigned to any other reference type
without a cast. A cast can be used to assign a reference variable of one type to a
METHODSTOTAKEANDRETURN$OG
OBJECTS BUTINSTEADTHE$OG
reference variable of a subtype, but at runtime the cast will fail if the object on the ISASIGNALTOTHECOMPILERTHAT
heap is NOT of a type compatible with the cast. YOUWANTTHECOMPILERTOLET
Example: Dog d = (Dog) x.getObject(aDog); YOUPUT/.,9$OGOBJECTSIN
ANDTOSTOPYOUIFYOUTRYTOADD
 All objects come out of an ArrayList<Object> as type Object (meaning, they can be
referenced only by an Object reference variable, unless you use a cast).
ANYOTHERTYPETOTHELIST!ND
SINCETHECOMPILERSTOPSYOU
FROMADDINGANYTHINGBUT$OGS
 Multiple inheritance is not allowed in Java, because of the problems associated with
the “Deadly Diamond of Death”. That means you can extend only one class (i.e. you
TOTHE!RRAY,IST THECOMPILER
ALSOKNOWSTHATITSSAFETOCAST
can have only one immediate superclass). ANYTHINGTHATCOMESOUTOFTHAT
An interface is like a 100% pure abstract class. It defines only abstract methods. !RRAY,ISTDOA$OGREFERENCE)N
 OTHERWORDS USING!RRAY,IST$OG
 Create an interface using the interface keyword instead of the word class. SAVESYOUFROMHAVINGTOCAST
THE$OGYOUGETBACK"UTITS
 Implement an interface using the keyword implements
Example: Dog implements Pet
MUCHMOREIMPORTANTTHANTHAT
BECAUSEREMEMBER ACASTCAN
FAILATRUNTIME ANDWOULDNTYOU
 Your class can implement multiple interfaces.
RATHERHAVEYOURERRORSHAPPEN
A class that implements an interface must implement all the methods of the
 interface, since all interface methods are implicitly public and abstract.
ATCOMPILETIMERATHERTHAN SAY
WHENYOURCUSTOMERISUSINGITFOR
SOMETHINGCRITICAL
 To invoke the superclass version of a method from a subclass that’s overridden the
method, use the super keyword. Example: super.runReport();
"UTTHERESALOTMORETOTHISSTORY
ANDWELLGETINTOALLTHEDETAILSIN
THE#OLLECTIONSCHAPTER

you are here4 229


exercise: What’s the Picture?

(ERESYOURCHANCETODEMONSTRATEYOURARTISTICABILITIES/NTHELEFTYOULL
1dQ^OU_Q lNDSETSOFCLASSANDINTERFACEDECLARATIONS9OURJOBISTODRAWTHEASSOCIATED
CLASSDIAGRAMSONTHERIGHT7EDIDTHElRSTONEFORYOU5SEADASHEDLINEFOR
hIMPLEMENTSvANDASOLIDLINEFORhEXTENDSv
Given: What’s the Picture ?
(interface)
1) Foo
1) public interface Foo { }
public class Bar implements Foo { }

2)
2) public interface Vinn { }
public abstract class Vout implements Vinn { } Bar

3) public abstract class Muffie implements Whuffie { }


public class Fluffie extends Muffie { } 3)
public interface Whuffie { }

4) public class Zoop { } 4)


public class Boop extends Zoop { }
public class Goop extends Boop { }

5) public class Gamma extends Delta implements Epsilon { }


public interface Epsilon { }
public interface Beta { } 5)
public class Alpha extends Gamma implements Beta { }
public class Delta { }

230 chapter 8
interfaces and polymorphism

/NTHELEFTYOULLlNDSETSOFCLASSDIAGRAMS9OURJOBISTOTURN
1dQ^OU_Q
THESEINTOVALID*AVADECLARATIONS7EDIDNUMBERFORYOU
ANDITWASATOUGHONE 

What’s the Declaration ?


Given:
Click 1) public class Click { }
1
public class Clack extends Click { }
Top
2
2)
Clack

Tip
3)

Fee
3
4)
Foo
4
Fi

Bar 5)

Zeta
5
Baz

Beta
Alpha KEY
EXTENDS

IMPLEMENTS
Clack CLASS
Delta
Clack INTERFACE

Clack ABSTRACTCLASS

you are here4 231


puzzle: Pool Puzzle

9OURJOBISTOTAKECODESNIPPETSFROMTHEPOOLAND
Pool PLACETHEMINTOTHEBLANKLINESINTHECODEANDOUT
PUT9OUMAYUSETHESAMESNIPPETMORETHANONCE
Puzzle ANDYOUWONTNEEDTOUSEALLTHESNIPPETS9OUR
GOALISTOMAKEASETOFCLASSESTHATWILLCOMPILE
ANDRUNANDPRODUCETHEOUTPUTLISTED

____________ Nose {
public ___________ ________ extends Clowns {
________________________
} public static void main(String [] args) {
____________________________
abstract class Picasso implements ______{
i[0] = new __________
_________________________
i[1] = new __________
return 7;
} i[2] = new __________
} for(int x = 0; x < 3; x++) {
System.out.println(__________________
class _________ ________ __________ { } + “ “ + _______.getClass( ) );
}
class _________ ________ __________ { }
___________________________ } /UTPUT File Edit Window Help BeAfraid

return 5; %java ______________


} 5 class Acts
} 7 class Clowns
________Of76
.OTE%ACHSNIPPET
FROMTHEPOOLCANBE
USEDMORETHANONCE
CLASS
!CTS  EXTENDS I
.OSE  INTERFACE I
/F  IMPLEMENTS IX
#LOWNS  I;X= CLASS
0ICASSO  CLASS
CLASS !CTS
PUBLICINTI-ETHOD  PUBLICCLASS .OSE
/F;=INEW.OSE;= PUBLICINTI-ETHOD[] /F
/F;=I PUBLICINTI-ETHOD [ II-ETHODX #LOWNS
.OSE;=INEW.OSE  PUBLICINTI-ETHOD [] IX I-ETHOD;= 0ICASSO
.OSE;=INEW.OSE;= I;X=I-ETHOD
I;X=I-ETHOD;=

232 chapter 8
interfaces and polymorphism

%XERCISE3OLUTIONS

What’s the Picture ?

(interface)
2) Vinn
3) (interface)
Whuffie

Vout What’s the Declaration ?


Muffie

2) public abstract class Top { }


public class Tip extends Top { }
4) Zoop Fluffie

3) public abstract class Fee { }


public abstract class Fi extends Fee { }
Boop
public interface Foo { }
4)
public class Bar implements Foo { }
Goop public class Baz extends Bar { }

5) public interface Zeta { }


5) Delta
(interface)
Epsilon
public class Alpha implements Zeta { }
public interface Beta { }
(interface)
public class Delta extends Alpha implements Beta { }
Gamma Beta

Alpha

you are here4 233


puzzle solution

interface Nose { public class Of76 extends Clowns {


public int iMethod( ) ; public static void main(String [] args) {
} Nose [ ] i = new Nose [3] ;
abstract class Picasso implements Nose { i[0] = new Acts( ) ;
public int iMethod( ) { i[1] = new Clowns( ) ;
return 7;
i[2] = new Of76( ) ;
}
for(int x = 0; x < 3; x++) {
}
class Clowns extends Picasso { } System.out.println( i [x] . iMethod( )
+ “ “ + i [x].getClass( ) );
class Acts extends Picasso { }
public int iMethod( ) { }
return 5; }
}
}

/UTPUT File Edit Window Help KillTheMime

%java Of76
5 class Acts
7 class Clowns
7 class Of76

234 chapter 8
9 constructors and garbage collection

Life and Death ...then he said,


of an Object ~I
can't feel my legs!" and

... I said"Joel Stay with me J oel H

But it was... too late. The garbage


-~~ collector came and... he was gone.
-";<" '~_"\. Best object I ever had .

Objects are born and objects die. You're in charge of an object's IIfecycie.

You decide when and how to construct It .You decide when to destroy It. Except you don't
actually destroy the object yourself, you simply abandon it. But once it 's abandoned, the

heartless Garbage Collector {gel can vaporize it, reclaiming the memory that object was

using . If you're gonna write Java,you're gonna create objects. Sooner or later, you're gonna

have to let some of them go, or risk running out of RAM. In this chapter we look at how objects

are created, where they live while they're alive, and how to keep or abandon them efficiently.

That means we'll talk about the heap, the stack, scope, constructors, super constructors, null

references, and more. Warning: this chapter contains material about object death that some

may flnd disturbing. Best not to get too attached.

th is is a ne w chapter 235
the stack and the heap

fhe Stack at1d the Heap: where thit1gs live


Before we can understand what really happens when running. But usually you WO?I ', have anything to S2.y
you create an object, we have to step back a bit, We about it, And with good programming. you probably
need to learn more about where everything lives won't care (more on that a little later).
(and for how long) inJava. That means we need to We know that all objects live on the garbage-collectible
learn more about the Stack and the Heap. In java, we
heap. but we haven 't yet looked at where variables
(programmers) care about two areas of memory-the live. And where a variable lives depends on what kind
one where objects live (the heap), and the one of variable it is. And by "kind", we don't mean type
where method invocations and local variables live (i.e. primitive or object reference) . The two kinds of
(the stack). When aJVM starts up. it gets a chunk of variables whose lives we care about now are instance
memory from the underlying as, and uses it to run
variables and localvariables. Local variables are also
your Java program. How mucl, memory. and whether known as slack variables, which is a big clue for where
or not you can tweak it, is dependent on which they live.
version of the JVM (and on which platform) you're

fhe Stack fhe Heap


Where method Invocat ions Where ALL objects live
and local variables live

I nstance Variables Local Variables


Instance variables are declared Inside a claSJ but not Local variables are declared Inside a method, Including
Inside a method. They represent the "fields" that each method parameters, They're temporary, and live only as
Individual object has (which can be filled with different long as the method is on the stack (in other words, as long as
values for each Instance of the class). Instance variables the method has not reached the closing curly brace).
live InsIde the object they belong to.

public
int
}
}

236 chap te r 9
constructors and gc

Methods are stacked


When you call a method, the method lands on A call stack with two methods
the top of a call stack. That new thing that's
actually pushed onto the stack is the stack

~y~ ~,-i!!~~~
frame, and it holds the state of the method
including which line of code is executing, and ,UtI'-
the values of all local variables.
The method at the top of the slack is always
the currently-running method for that stack
?l.........
(for now, assume there's only one stack.but in boitor.. of -the statk
chapter 14 we'll add rnore.) A method stays on
the stack until the method hits its closing curly The method on the top of the
brace (which means the method's done). If stack is always the currently-
method foo() calls method bar(), method bast) is
executing method.
stacked on top of method foot).

public void doStuff() { Astack scenario


boolean b = true;
go(4); The code on the left is a snippet (we don't care what the rest of the
class looks like) with three methods. The first method (drot-u.ff(» calls
public void go (int x) the second method (go() , and the second method calls the third
int z = x + 24; (craz)'()). Each method declares one local variable within the body
crazy(); of the method, and method goO also declares a parameter variable
/ / imagine more coda here (which means goO has two local variables).

public void crazy()


char c = 'a';

• Code from another @ doStuffO calls goO, @goO cells crozyO, @crazy()completes,
class calls doStuffO, goO is pushed on crozyQ is now on the and its stack frame is
and doStuffO goes top of the stack. top of the stack, poppedoff the stack.
into a stack frame Variables 'x' and 'z' with variable 'e' in Execution goes back
at the top of the are in the goO stack the frame. to the goO method.
stack. The boolean frame. and picks up at the
variable named 'b' line following the caU
goes on the doStuffO to crazy().
stack frame.

you are here. 237


object references on the stack

What about local variables that are objects?


Remember, a non-primitive variable holds a reference to an
object, not the object itself. You already know where objects
live--on the heap. It doesn't matter where they're declared or
created. If the local variable is a reference to an object, only
the variable (the reference/remote control) goes on the stack. .,.t.....

The object itselfstill goes in the heap. 0 t\a'C'es a~ t'"t.a~ ~si~t. \t: s
'oa~O e lJay·'i"o\t. rt s a \ot.i\
t""IlIL~ ,"to~ tv"t.,.tl. e ",e\:.h00I
v 1 . ,.s\ot. .\)I ~t\L.
ot.i\ayt.o ' ov. ()YI -\:.'M
....
'l4ayl.." o\e 6,,0 ~

public class StackRef


~
public void foof()
barf();

public void barf() {


Duck d '" Dew Duck (24) ;

Q: Onl!!more time, WHY are we learning the


whole stack/heap thing? How does this help me?
~ Java has two areas of memory we care about
Do I really need to learn about It?
the Stack and the Heap.

A.: Knowl ng the fu ndamenta Is of the Java


Stack and Heapis crucial If you wa nt to understa nd
~ Instance variables are variables declared
insIde a class but outside any method.

variable scope, object creation Issues,memory ~ Local variables are variables declared inside a
management, threads, and exception handling. method ormethod parameter.
We cover threads and exception handling In later ~ All local variables live on the stack, In the
chapters but the others you'll leam In this one. You frame corresponding to the method where the
do not need to know anything about how the Stack
variables are declared.
and Heap are Implemented in any particular JVM
and/or platform. Everything you need to know ~ Object reference variables work. just like primi-
about the Stack and Heap Is on this page and the tive variables-if the reference isdeclared as a
previous one. If you nail these pages, all the other local variable, it goes on the stack.
topics that depend on your knowing this stuff will
go much, much, much easier. Once again, some day .. All objects live In the heap, regardless of
you will SO thank us for shoving Stacks and Heaps whether the reference isa local orInstance
down your throat. variable.
238 chapter 9
constructors and gc

If local variables live Ott the staek.


where do I"stattce
.. variables live?
When you say new Cellf'hone () ,Java has to make
space on the Heap for that CellPhone. But how much
space? Enough for the object, which means enough to
house all of the object'S instance variables. That's right,
instance variables live on the Heap, inside the object Objett wit.h two p-ri...itive iJ\St..l"te \/al'" iablcs.
they belong to. SpdU +~ the val'"iables lives i" the ~jed:,
Remember that the values of an object's instance
variables live inside the object. lithe instance variables
are all primitives, Java makes space for the instance
variables based on the primitive type . An int needs
32 bits, a long 64 bits, etc.java doesn't care about the
value inside primitive variables; the bit-size of an int
variable is the same (32 bits) whether the value of the
int is 32,000,000 or 32.
But what if the instance variables are objects? What if
CeliPhone HAS-AAntenna? In other words, CellPhone
has a reference variable of type Antenna. Objttt wit.h l»\t )lOtl-rv-i...itive ir.st..lrltt lIariable-
When the new object has instance variables that are
a I'"tttr-tlIte to d" A"b,."a objett., blot. "0 olthadl
object references rather than primitives, the real A"un'nd objtd~ This is \oIhat. yO'J. ~d, it YO4/.
question is: does the object need space for aU of detlal"'t t.he lIariable b...t. dOtl'i, initialiu it with
the objects it holds references to? The answer is, not a" ad:lodl Anta.na objett.
exQ.{;tly. No matter what,Java has to make space for the
public class CellPhone
instance variable values. But remember that a reference
private Antenna ant;
variable value is not the whole object, but merely a remote
control to the object. So if CellPhone has an instance
variable declared as the non-primitive type Antenna,
Java makes space within the CellPhone object only for
the Antenna's remote control (i.e. reference variable) but
not the Antenna object.
Well then when does the Antenna object get space on
the Heap? First we have to find out whim the Antenna
object itself is created. That depends on the instance
variable declaration. lithe instance variable is declared
but no object is assigned to it, then only the space for
the reference variable (the remote control) is created.
private Antenna ant; Objett. with Ol'le "or.-p-ri....i-lille iJ\Stal">tt lIariable,
and tht A"~,,a IIdr-iable is as.si~"ed a l\tw
No actual Antenna object is made on the heap unless A"u",."a objet+"
or until the reference variable is assigned a new
Antenna object. public class CellPhone (
private Antenna ant = new Antenna (l ;
private Antenna ant :: new Antenna () ;

you are here ~ 239


object creation

fhe tttiracle of object creatlott


Now that you know where variables and objects live, we can dive into
the mysterious world of object creation. Remember the three steps
of object declaration and assignment: declare a reference variable,
create an object, and assign the object to the reference.
But until now, step two--where a miracle occurs and the new object
is "boron-has remained a Big Mystery. Prepare to learn the facts of
object life. Hope you're not squeamish.

Review the 3 steps of object


declaration, creation and assignment:

Declare a reference
O variable
Duck myDuck = new Duck () :

e Create an object
. ~t.\t. ~ Duck myDuck = new Duck () ;
~ yV\\V' gI e
ot.t.v.V'~ "tv' .

e Link the object and


the reference
Duck myDuck @)new Duck () ; _ --rWL

Duck reference

240 chapter 9
constructors and gc

Are we calling a method named DuckO?


Because it sure looks like it.

Duck myDuck =

No.
We're calling the Duck constructor.

A constructor does look and feel a lot like a method, but it's not
a method. It's got the code that runs when you say new. In other
words, the code that runs when you instantiate an object.
The only way to invoke a constructor is with the keyword new
followed by the class name, ThejVM finds that class and invokes
the constructor in that class. (OK, technically this isn't the only
way to invoke a constructor, But it's the only way to do it from
outsidea constructor. You ca'n call a constructor from within
another constructor, with restrictions, but we'll get into all that
later in the chapter.)

But where Is the constructor?


If we didn't write It, who did?

You can write a constructor for your class (we're about to do


that), but if you don't, the compilerwrites one for you!
Here's what the compiler's default constructor looks like:

public Duck () {

Notice something missing? How Is this ~


different from a method? 1. e 'IS ~t sa",t as 1t~'-I
Iv I'd'" T\\at s ,..a"da\,Pl ,.
~ t.\ass y,d",t·

~Duck() (
~trejs the retllm t // constructor code goes here
I this Wtre a 1, ype? )
j rheOlod
you d heed d 'ret m t j

betweeh l'PlI.b/' ,, " yPe


llDlAlkO", It. arid

you are here. 241


constructing a new Duc k

CottStruct a Puck
The key feature of a constructor is that it runs
before the object can be assigned to a reference.
That means you get a chance to step in and
do things to get me object ready for use. In
other words, before anyone can use the remote
contra] for an object, the object has a chance to
help construct itself In our Duck constructor,
we're not doing anything useful, but it still
demonstrates the sequence of events.

public class Duck {

public Duck () {
System.out.println("Quack~) ;
The constructor gives
you a chance to step into
the middle of new.

~
public class UseADuck {
% java UseADuck
public static void main (String[] args) {
Quack
Duck d = new Duck() ;
f - - !h;s ~lJs in
}
D
(.orutr-lAl!or. t: lI.lk

o Increment a counter to track how many objects ofthis class type


have been made.
A constructor lets you Jump Into the middle
of the object creation step-into the middle
o Assign runtime-specific state (data about what's happening NOW).

of new. Can you imagine conditions where


o Assign values tothe object's important instance variables.

that would be useful? Which of these might


o Get and save a reference 10 Ihe object that's creating the new object.
be usefulin a Car classconstructor, if the Car
o Add the object to an ArrayList.
is part of a Racing Game?Check off the ones
o Create HAS-A objects.
that you came up with a scenario for.
o (your idea here)

242 chapter 9
constructors and gc

Initializing the state of a new Puck there]lU'H?


Dumo ~uest19ns
Most people use constructors to initialize the state of an object.
In other words, to make and assign values to the object's Q.: Why do you need to write
instance variables. a constructor if the compiler
writes one for you?
public Duck ( ) {

}
size = 34;
A: If you need code to help
initialize your object and get
That's all well and good when the Duck class developer knows it ready for use,you'll have to
how big the Duck object should be. But what if we want the write your own constructor. You
programmer who is using Duck to decide how big a particular might, for example, be depen-
Duck should be? dent on input from the user
before you can finish making
Imagine the Duck has a size instance variable, and you want the the object ready.There's another
programmer using your Duck class to set the size of the new reason you might have to write
Duck. How could you do it? a constructor, even if you don't
need any constructor code
Well, you could add a setSize() setter method to the class. But
yourself. It has to do with your
that leaves the Duck temporarily without a size*, and forces the superclass constructor, and we'll
Duck user to write two statements-one to create the Duck, and talk about that in a few minutes.
one to call the setSize () method. The code below uses a setter
method to set the initial size of the new Duck.

public class Duck {


Q.: How can you tell a con-
structor from a method? Can
int size; 'f-- iY\Sta\'lt..e ~aYiah\e you also have a method that's
the same name as the class?
public Duck() {

}
System. out.println ("Quack") ; 'f-- t.oY\ShvLto'r
A: Java lets you declare a
method with the same name as
your class. That doesn't make it
public void setSize (int newSize) { ~ set..t,eY ",et.'nod a constructor, though.The thing
size = newSize; that separates a method from a
} constructor is the return type.
} Methods must have a return
type, but constructors cannot
have a return type.
public class UseADuck {
0: Are constructors inher-
public static void main (String[] args){ it~(h Ifyou don't provide a
Duck d = new Duck () ; T constructor but your superclass
t--... i ~~r~'~ a bad thih h does, do you get the superclass
d. setSize (42) ; Ah~ iPO/ht ;1'1 ih~ l~ ~b~'iThe DlAtk is aI' constructor instead of the
hel'l I~' with t /V~ ai
}
1'1 "OlA'
to KNOW ~hatD~ yihS 01'1 ih~
lA
D:t a
Si~!*,
lAtk lr~atioh is k-fAS~r
default?
protess: Ol'le i
to tall th~ Stt1
~all ih~ tohSirlAtkiwo-pari
Ul-. ahd Oh~
A.: Nope. Constructors are
not inherited. We'll look at that in
*Instance variables do have a default value. 0 or
just a few pages.
0.0 for numeric primitives, false for booleans, and
null for references.
you are here), 243
initializing object state

Ushtg the eenstruetor to it1itialize


itMportat1t Pock state" Let the user make a new Duck
and set the Duck's size all in
If an object shouldn't be used until one or
one call. The call to new.
more parts of its state (instance variables) have The call to the Duck
been initialized, don 't let anyone get ahold of constructor.
a Duck object until you're finished initializing!
It's usually way too risky to let someone make- o
and get a reference to-a new Duck object that
isn 't quite ready for use until that someone rums
around and calls the setSize() method. How will
the Duck-user even know that he's required to call
the setter method after making the new Duck?
The best place to put initialization code is in the
constructor. And all you need to do is make a
constructor with arguments. \:.0 ~t
\,,~ ~a'<3""~t'!
public class Duck { fl\4~ 0.... 1cc~Jv:i'f'
int size; ~ \)uL~ !,o~

public Duck(int duckSize) (


System.out.println("Quack");
l,(~
the ar~Uft\~~ va
L lw: -to ~
size = duckSize; ~ the siz.e i"s!:.a"te variable.

System.out.println("size is " + size);

public class UseADuck {

"NOIIO Imply thai not all Duck state Is nol unlmportanL

244 chapte r 9
constructors and gc

Make it easy to ",ake a Pucle


Je sure you have a tlo..arg cOtldructor
What happens if the Duck constructor takes an argument?
Think about it. On the previous page, there's only oneDuck
constructor-and it takes an int argument for the sizeof the
Duck. That might not be a big problem, but it does make it You really want TWO ways to
harder for a programmer to create a new Duck object, especially
make a new Duck:
if the programmer doesn't knot» what the size of a Duck should
be . Wouldn't it be helpful to have a default size for a Duck, so
that if the user doesn't know an appropriate size, he can still public class Duck2
make a Duck that works? int size;

Imagine that you want Duck users to have TWO optlons public Duck.2 () (
for making a Duck-one where they supply the Duck II supply default size
size (as the constructor argument) and one where they size;; 27;
don't specify a size and thus get your default Duck size.

You can't do this cleanly with just a single constructor. public Duck2 (int dUckSize) (
Remember. if a method (or constructor-s-same rules) has / / uae duckSiz8 parameter
size'" duckSize;
a parameter, you must pass an appropriate argument when
you invoke that method or constructor. You can't just say, "If
someone doesn't pass anything to the constructor, then use
the default size", because they won't even be able to compile
without sending an int argument to the constructor call. You To make a Duck when you know the sIze:
could do something c1unkly like this: Duak2 d;; new Duck2(15):

'p ub l i c class Duck


To make a Duck when you do not know
int size;
the size:
Duck.2 d2 "" new Duck2 () ;

So this two-optlons-to-make-a-Duck Idea


needs two constructors. One that takes
an Int and one that doesn't. Ifyou haw
mor« than one constructor In a dau,
It means you have overloaded
constructors.
But that means the programmer making a new Duck object has
to knou: that passing a "0" is the protocol for getting the default
Duck size. Pretty ugly. What if the other programmer doesn't
know that? Or what if he really does want a zero-size Duck?
(Assuming a zero-sized Duck is allowed . lfyou don 't want
zero-sized Duck objects, put validation code in the constructor
to prevent it.) The point is, it might not always be possible
to distinguish between a genuine "I want zero for the size"
constructor argument and a "I'm sending zero so you'll give
me the default size, whatever that is" constructor argument.
you are here ~ 245
overloaded and default constructors

Poes""t the cotMpiler always


",ake a "o-arg eonstrueter
foryou? ~I,
You might think that if you write only
a constructor with arguments, the
compiler will see that you don't have a
no-arg constructor, and stick one in for
you. But that's not how it works. The
compiler gets involved with constructor-
making only if you don't say anything at all
about constructors.

If you write a constructor that


takes arguments, and you stili
want a no-arg constructor,
you'll have to build the no-arg
constructor yourself!

As soon as you provide a constructor,


ANY kind of constructor, the compiler
backs off and says, "OK Buddy, looks like
you 're in charge of constructors now,"

If you have more than one


constructor In a class, the
constructors MUST have
different argument lists.
The argument list includes the order
and types of the arguments. As long as
they're different, you can have more
than one constructor. You can do this
with methods as well, but we'll get to that
in another chapter.

246 c hapt er 9
constructors and gc

Overloaded constructors means you have


more than one constructor in your class.
To compile, each constructor must have a
dlffersnt argument IIstl
The class below is legal because all four constructors have
different argument lists. lfyou had two constructors that took
only an int, for example, the class wouldn't compile. What you
name the parameter variable doesn't count. It's the variable
type (int, Dog, etc.) and order that matters. You can have two
constructors that have identical types, as long as the order is
different. A constructor that takes a String followed by an int, is
not the same as one that takes an int followed by a String.
kr..o w th~ S'IU, Dlo-t ~Q\i.
pub l i c class Mushroom { . whc" 'jo'J. .r . L' ,.,.al:lit
~ dOWl' -t kF>Ow i-t 'n. s ;)

public Mushroom (int size) { } u-\.\.... ~


~ htJI 'fC)U. dor-.'t. kno-.l 6Y11""'"
public Mushroom ( ) {. W k i-t it's ,.,.a~It. (Jr Y\O-I:.

public:
~ wMl\ '1~t
Mushroom (boolean isMaqic) (. D\,I.-t dOWl
k nOW
t\l~ siu

p ubl1C: Mushroom (boolean isMaqic, int size) } ~~ ~ its


:~it., AND 'f$ \{,.O'<l
fpublic Mushroom (int size, boolean isMaqic) • thC siu. as well

~ Instance variables live within the object they belong to, on ~ Ifyou want a no-arg consructor and you've already put
the Heap. in a constructor with arguments, you'll have to build the
no-arg constructor yourself.
~ Ifthe instance variable is a reference to an object, both
the reference and the object it refers to are on the Heap. ~ Always provide a no-arg constructor if you can, to make It
easy for programmers to make a working object Supply
~ Aconstructor isthe code that runs when you say new on default values.
a class type.
~ Overloaded constructors means you have more than one
~ Aconstructor must have the same name as the class, and
must nothave a return type.

~ You can use a constructor toInitialize the state (Le. the


instance variables) ofthe object being constructed.
. constructor in your class.
Overloaded constructors must have different argument
lists.

~ You cannot have two constructors with the same


~ If you don't put a constructor in your class, the compiler argument lists. AIl argument list Includes the order and/or
will put In a default consnuctor.
type of arguments.
~ The default constructor is always a no-arg constructor. Instance variables are assigned a default value, even
~
~ Ifyou put a constructor~ny conslructor-in your class, when you don't explicitly assign one. The default values
the compiler will not build the default constructor. are DID.Olfalse for primitives, and null for references.

you are here ~ 247


..
overloaded constructors

class Duck {

int pounds = 6;
Match the new Duck () call with the constructor floa t flo a tabili ty = 2 . IF ;
that runs when that Duck is instantiated . We did String name = "Generic";
the easy one to get you started .
long[] feathers ={l,2,3,4,S,6,7};
boolean canFly =true:
int maxSpeed = 25;
public class TestDuck {
public Duck () (
public static void main(String[] args) ( System.out.printin("type 1 duck");
int weight = 8;
float density = 2. 3F; public Duck(boolean fly) {
String n8I118 = "Donald"; canFly = fly;
lonq[) feathers = {l,2,3,4,5,6}: System .out .printin("type 2 duck"):
boolean canFly = true:
int airspeed = 22:
public Duck(String n, long[] ~) (
Duck [] d = new name = n:
feathers = f;
d[O] = new Duck(): Syst&m.out.printin("type 3 duck"):
d[l] new Duck(density, weight);
public Duck(int w, float f)
d[2] = new Duck(name, feathers): pounds = w;
floatability f; =
d[3] = new Duck(canFly); SysteJn.out .println("type 4 duck"):

d[4] new Duck(3.3F, airspeed):


public Duck (float density, int IIIAX) {
d[S] = new Duck(false); floatability = density:
maxSpeed = max;
d[6] = new Duck (airspeed, density); SysteJn.out.println("type 5 duck") ;

Q.: Earlier you said that It's good to have a no-argu- (We're using three Ints for RGB values here .We'll get into
ment constructor 50 that if people call the no-arg con- using Color later, in the Swing chapters.) Otherwise, what
structor, we can supply default values for the "mlsslngn would you get? The Java API programmers could have de-
arguments. But aren't there times when It's Impossible to cided that if you call a no-arg Color constructor you'll get a
come up with defaults? Are there times when you should lovely shade of mauve. But good taste prevailed.
not have a no-arg constructor In your class? If you try to make a Color without supplying an argument:

Color c ; new Color();


.A..: You're right. There are times when a no-arg construc-
tor doesn't make sense.You'll see this in the Java API-some The compiler freaks out because It can't find a matching 00-
classes don't have a no-arg constructor. The Color class, for arg constructor in the Color class.
example, represents a...color. Color objects are used to , for
example, set or change the color of a screen font or GUI
button .When you make a Color Instance, that instance Is
of a particular color (you know, Death-by-Chocolate Brown,
Blue-Screen-of-Death Blue, Scandalous Red, etc .), If you
make a Color object you must specify the color In some way.

Color c ; new Color(3,45,200);

248 chapter 9
constructors and gc

Nattoreview: four thittQs to


relHelHber about eonstrueters


What about 5uperclasses?
A constructor is the code that runs when
somebody srrys new on a class type When you make a Dog,
Duck d = new Duck() ; should the Canine
construdor run too?
Ifthe superclass is abstract,.

• A constructor must have the same nome


as the class , and no return type
public Duck(int size) { }
should it even have a
construdor?

We'll look at this on the next


few pages, so stop now and

• If you don't put a constructor in your class,


the compiler puts in a default constructor.
The default constructor is alwrrys a no-arg
constructor.
think about the implicationsof
constructors and superclasses.

public Duck () { } dfim~~esti9ns


Q.: Do constructors have to be public?

A:

No. Constructors ca n be public,
You can have more than one constructor in your class, private, or default (which means no access
as long as the argument lists are different. Having modifier at all).We'll look more at default
more than one constructor in a class means you have access in chapter 16 and appendix B.
overloaded constructors.
Q.: How could a private constructor
publi c Duck () { ever be useful? Nobody could ever call It,
so nobody could ever make a new objectl
public Duck(int size) { }

public Duck(String name)


A..: But that's not exactly right. Marking
something private doesn't mean nobody
can access It, it Just means that nobody
public Duck (String name, int size) { } outside the class can access it. Bet you 're
thinking "Catch 22': Only code from the
same class as the class -witb -private-con-
structor can make a new object from that
class, but without first mak ing an object,
how do you ever get to run code from that
class in the first place7 How do you ever get
DoIng all the Brain Barbells has been shown 10oreduce a 42% increase in to anything in that class? Patience grasshop-
neuron size . And you know what they say, "8lg neurons .. '- per. We'll get there in the next chapter.

you a re here ~ 249


space for an object's superclass parts

Waif a tMI"ute... we "ever UIP talk about


superclasses and htherita"ce and how that all
fits I" with constructors.
Here's where it gets fun . Remember from the last chapter, the part where we looked at
the Snowboard object wrapping around an inner core representing the Object portion
of the Snowboard class? The Big Point there was that every object holds not just its oum
declared instance variables, but also roerythingjrom its superclasses (which, at a minimum,
means class Object, since every class extends Object) .
So when an object is created (because somebody said new; there is no other way to create
an object other than someone, somewhere saying new on the class type), the object
gets space for all the instance variables. from all the way up the inheritance tree. Think
about it for a moment... a superclass might have setter methods encapsulating a private
variable. But that variable has to live somewhere. When an object is created, it's almost as
though multiple objects materialize-the object being new'd and one object per each
superclass. Conceptually, though, it's much better to think of it like the picture below,
where the object being created has layers of itself representing each superclass,

Asi~le
Object Objett has IPlStar.tt varidbl~ objet+' Oft
Foo 8; trlUpslAlclUd by atuss ",ethods. the heay
Intb:
no~ il'lStal'lU Vc1\"'ic1bl~ c1ye
Inlc;
t\"'e..1~d when any 5lAbt.lass is
&qualsO iPlStantiaUd. (nest a.,.t;n't f.ht
gelClassO
hashCodeo
REAL Objttt va\"'idbl~, but we
IoStringQ donIt ta.,.e what tht'f dl"'t sil'lU
they're eY>tc1ps-Jaud)
T
Snowboard Sroowboard also has ir-sidntt
Foox variables 0+ its 0WJ\j so 1:.0 ...ake
Fooy a Snowboard objett wt ""eed
Inlz
5yc1tt .for the instante variables
lumO
shradO
geWrQ
-
0+ both classes.
Thert is only ON~ objett 0"" the he.ly htye. A
loseConlrolO Snowboard objett. Bt..t it t.ontail'lS both the
Sl"oowboard fdrt.s of ihtl.f and the .Q!.iet.t Yc1rt.s o.f
itself 1\11 il'lStar.te vc1l"'iables ~YOtll both dassts have
to be nC\"e.

250 chapter 9
constructors and gc

fhe role of superclass ecastrueters


itt att obJecfs life.
All the constructors in an object's inheritance
tree must run when you make a new object.
Let that sink in .
That means every superclass has a constructor
(because every class has a constructor), and each
constructor up the hierarchy runs at the time an
object of a subclass is created.
Saying new is a Big Deal. It starts the
whole constructor chain reaction. And yes,
Oblect
even abstract classes have constructors.
Although you can never say new on an
abstract class, an abstract class is still
a superclass, so its constructor runs I"
when someone makes an instance of a AnImal
concrete subclass.
The super constructors run to build
out the superclass parts of the object. -~f
Remember, a subclass might inherit
methods that depend on superclass state
HIDDO
(in other words, the value of instance variables
in the superdass). For an object to be fully-
formed, all the superclass parts of itself must be
fully-formed, and that's why the super constructor
must run. All instance variables from every class
in the inheritance tree have to be declared and A new Hippo object also IS-A Animal
initialized. Even if Animal has instance variables and IS-A Object. If you want to make a
that Hippo doesn't inherit (if the variables are Hippo, you must also make the Animal
private, for example), the Hippo still depends on and Object parts of the Hippo.
the Animal methods that use those variables.
This all happens In a process called
When a constructor runs, it immediately calls its Constructor Chaining.
superclass constructor, all the way lip the chain
until you get to the class Object constructor,
On the next few pages, you'll learn how superclass
constructors are called, and how you can call
them yourself. You'U also learn what to do if your
superclass constructor has arguments!

you a re here. 251


object construction

Maklt1Q a Hippo ttteat1s tMakit1Q the


At1hMal at1d Object parts too...
What's the real output? Given the
code on the left , what prints out
when you run TestHippo? A or 87
public class Animal {
(the answer Is at the bottom of the page)
public AnimAl () (
System.out.p1:'intln( "Maldllg an Animal");
~
% java TestHippo
A Starting ...
public class Hippo axtands Animal ( Making an Animal
public Hippo () { Making a Hippo
System.out.printin("Making a Bippo H) ;

public class T8StBippo { % java TestHippo


public static void main (String[] args) B Starting . . .
System. out .p r i n tln ("Starting . .. ") ; Making a Hippo
Hippo h .. new Hippo () ;
Making an Animal

• Code from another ... Hlp~ invokes • AnlmolO invokes @ ObjectO completes,
class says new the superclass the superclass and its stack frame
Hippo () and the constructor which constructor which is poppedoff the
HlppoQ constructor pushes the AnlrnalO pushes the Object() stock. Execution goes
goes into a stack constructor onto the constructor onto back to the AnlmolO
frame at the top of top of the stock. the top of the stock. constructor, and
the stack. since Object is the picks up at the line
supercloss of Animal. following Animal's
call to its supercloss
constructor

lSJy s94SlUij 19~1 JOPnJlsuCl:llewlUV' 91.11 S.l1


lnq 'ISJ~ pe~O!IU! &1 JOlOfIJlSUOO Oodd!H e41 'd 'eue ISJ~ 9lU

252 chapter 9
constructors and gc

How do you lnveke a superclass cOMstructot1


You might think that somewhere in, say, a Duck constructor,
if Duck extends Animal you'd call Anirnalj). But that's not
how it works:

public class Duck exttmds Animal {


int size;

public Duck(int newSize) { And how is it that we've


gotten away without
1(,~t>~ --4- Animal () i ~ NOI ti: . doing it?
size = newSize; . hl~ 's lIot Ie II
} ~. You probably figured that out,

} Our good friend the compiler


puts in a call to super() If you
don't.
The only way to call a super constructor is by calling superi),
That's right-super() calls the super consIn.tctor. So the complier gets involved in
constructor-making in two ways:
What are the odds?

public class Duck extends Animal { <D If you don't provide a constructor
int size; The complier puts one in that looks like:
public ClassName()
super () ;
public Duck(int newSize) {
super (); ~(-~

size = newSize;
® I' you do provide a constructor
but you do not put in the call to
superl)

The compiler will put a call to supert) in


A call to suPer() in your constructor puts the superclass each of your overloaded constructors."
constructor on the top of the Stack, And what do you The complier-supplied call looks like:
think that superclass constructor does? Calls its superclass
super();
constructor. And so it goes until the Object constructor is
on the top of the Stack, Once Object() finishes, it's popped It always looks like that. The compiler-
off the Stack and the next thing down the Stack (the Inserted (all to supert) Is always a no-arg
call. If the superclass has overloaded
subclass constructor that called Objul(») is now on top.
constructors, only the no-arg one is called.
That constructor finishes and so it goes until the original
constructor is on the top of the Stack, where it can now 'Unless the conslructor calls another overloaded
finish, constructor (you'll see thai in a few pages).

you are here ~ 253


object lifecycle

Catt the child exist before


the parents?
If you think of a superclass as the parent to the subclass child,
you can figure out which has to exist first, The superdass parts
ofan object have to beJUUy-jormed (completely built) btfore the
subclass parts can be constructed. Remember,
the subclass object might depend on things it
inherits from the superclass, so it's important
that those inherited things be finished. No
way around it. The superc1ass constructor
must finish before its subclass constructor,
Look at the Stack series on page 248 again,
and you can see that while the Hippo
constructor is the first to be invoked (it's
the first thing on the Stack), it's the last one
to complete I Each subclass constructor
immediately invokes its own superclass
constructor, until the Object constructor
is on the top of the Stack, Then Object's
constructor completes and we bounce
back down the Stack to Animal's
constructor. Only after Animal's constructor completes
do we finally come back down to finish the rest of the Hippo
constructor. For that reason :
The call to superO must be the first statement
In each eenetrueterr'

Possible constructors for class Boop


o public Boap ( ) (
o public Boop () { I
super () ;
0' public Boop (int i)
size '" i; f-~--
0' public Boop (int i) (

sup&r() ;
size =i; o public Boop (int i) ( BAD!! Thi5 '
VOlt t-ill 'f. txp/·(;
'4'otl t lOll,l>'j
} size = i; .1, '.l' [It.
U1~ ~II to I 'T.Jy pc-I:
super () ; / 'ClllythiM.J eI5e.lIoP~) belo'o.l

"There's an exception to this rule: you'lileam It on page 252.

254 ch apt er 9
constructors and gc

Superclass eoastrueters with argUtMettfs


What if the superclass constructor has arguments? Can you pass something in to
the super() call? Of course. If you couldn't. you'd never be abl e to extend a class Animal
that didn 't have a no-arg constructor, Imagine this scenario: all animals have a
name. There's a gelName() method in class Animal that returns the value of the private String name
name instance variable. The instance variable is marked private, but the subclass
(in this case, Hippo) inherits the getName() method. So here's the problem: Animal(StTing n)
Hippo has a getName() method (through inheritance), but does not have the name String getNameO
instance variable. Hippo has to depend on the Animal part of himself to keep the
name instance variable, and return it when someone calls geLNa1T/~() on a Hippo
object. But ... how does the Animal part get the name? The only reference Hippo
has to the Animal part of himself is through supert), so that's the place where
Hippo sends the Hippo's name up to the Animal pan of himself, so that the
T
Hippo
Animal part can store it in the private n~me instance variable.

public abstract class Animal {


Hlppo(String n)
private String name; ~ All al'li",al s (i"dwii,,~
slobdas.ses) hall' a "a",e [other Hippo-spe-
cific methods]
public String getName () (~~ 9~k "'rl::~od
return name; Illppo illherib ihai

public Animal(String
name = theName;

public class Rippo extends Animal (

~
public class MakeHippo ( %j a v a MakeHippo
public static void main(StJ:ing[] args) ( NJak e d Ili
Hippo h = new Bippo("Buffy"); ~ Il<lrnt "BI.I(ly~:
to~i.,. f..ot.
f:;"9 t~e
SS

the Ill ppo


Buffy
System. out. println (h. getName () ) ; Hip ~ I The,. tall f.h

C" _ po 5 'hht:rj~d eLvt e


\~ g l:./¥a'fte()

you are here. 255


calling overloaded constructors

lt1vokh,g Ot1e overloaded cot1structor


fro", at10ther
Use this\) to catt a
What if you have overloaded constructors that, with
the exception of handling different a.Tg1l!l1ent types,
all do the same thing? You know that you don 't want
-
constructor trom another
duplicate code sitting in each of the constructors (pain
to maintain, etc.), so you'd like to put the bulk of the o-vertoaded constructor in
constructor code (including the call to super()) in only
om of the overloaded constructors. You want whichever tl,e saute ctass.
constructor is first invoked to call The Real Constructor
and let The Real Constructor finish thejob of Tl,e caU to this\)
construction. It's simple: just say this(). Or this(aString).
Or this(27, x). In other words. just imagine that the can be used only in a
keyword this is a reference to the current object
You can say thist) only within a constructor. and it must
condl'uet o1', and must he
be the first statement in the constructor! the tirst statement in a
But that's a problem. isn't it? Earlier we said that
super() must be the first statement in the constructor.
-
constructor.
Well, that means you get a choice.
Every constructor can have a call to super() 1\. constructor can \\ave a
or thlsO, but never bothl
catt to sUfel'O ottthisO,
llut nevel' \loth!
class Mini extends Car (

Color color ; n, YIO-ay~ t.o\'\Stvl>Lttx d


lies a d'~ il",lt. ColO'/" d"
public Mini () { ~s tnt ol/CY'\oadtd Real
this (Color. Red) ; {----'" Col\3.~-\:.O'I" (~t OJIt that
) taIls SIIYcY(»'
public Mini (Color c)
8uper("Mini"); l-(----..
color = c;
JJ more ini tialization

public Mini (int size)


thi5(COIor.Re~) ;~
super (size);
(

~ WOl'l'i '4IO\"'k.!! eall'i have


slJ.rcy() a"d thisO ;1'1 the sa...e
lOl'l5tn.tt:or, bel41/.U they cad
....lUt be the +il"'St stau.... ent.
r
256 chapter 9

constructors and gc

~ YOIJr pencil
Some of the constructors In the SonOOoo class will not
compile. See ifyou can recogn lze which constructors are I
not legal. Match the compiler errors with the SonOfBoo
constructors that caused them, by drawing a Iine from the
I Malee i-/; Siitle
compiler error to the "bad" constructor. Roses Ore red. v
I
You,pa,en~ Ci'Iolets areblue.
public class Boo ( Th omen,s, It':
public Boo(int i) I ~
, e superc/ass r ay befo,e you
I formed b ~ parts of an ob ' .
public Boo (String s) ( , elOTe th lJect mu
exist. Just I'k e new sUbc/as sr be fU/ly_
public Boo(Strlng 8, int i) { } been b I e there's no w s Object can
Orn before You ay You could h
r parents. ave

class SonOfBoo ext:4ilnds Boo (

public SonOfBoo()
super ("boo") ;

public SonOfBoo(int i) (
super ("Fred") ;

public SonOfBoo(Strinq s) {
supar(42);

public SonOfBoo(int i, String s) {


}

public SonOfBoo(Strinq 8. String b, String c) (


8upar(a,b);

public SonOfBoo(int i, lnt j) (


supar("man", j);

public SonOfBoo(int i, int x, lnt y) {


super(i, "star");

you are here . 257


object lifespan

Now we know how an object Is boyn, ~ A local variable lives only


but how IOt1g does an object live? within the method that
An object's life depends entirely on the life of references
declared the variable.
referring to it- If the reference is considered "alive", the public void read() (
object is still alive on the Heap. If the reference d.ies int s = 42;
(and we'll look at what that means injust a moment) . the II's' can be used. on.1y
object wiU die . II within th.is method.
II When this mathod ends,
So if an object's life depends on the reference II's' disappeaLs completely.
variable's life, how long does a variable live?
That depends on whether the variable is a localvariable Variable 's' can be used only within the
or an instancevariable. The code below shows the life ofa readO method. In other words. the variable
local variable. In the example, the variable is a primitive. Is In scope only withIn Its own method. No
but variable lifetime is the same whether it's a primitive other code In the class (or any other class)
or reference variable. can see's'.

public class TeatLifeOne

public void read() {


r,
• An instance variable lives
int s '" 42; ~(_ _-- .s ;s oSlo as long as the object
sleep () ; ""rl:.hoc/
ped to th
d ' So
PlYWh&e else
if. td ,i "'eddO
~ (; be ~d
does. If the object is still
alive, so are its instance
public void sleep() { variables.
s = 7;
J<::- ~-tP public class Life (
\ \\ \-lat, \c.oj int size;
~f\~ .; 1It:<"t.\.
1Pt$ public void setSize(int s)
size = s;
II's' disappears at the
/ I end of this method,
II but 'size ' can be used
II anywhere in the class

Variable ' 5' (this time a method parameter)


Is In scope only within the setSize()
method. But instance variable size is
scoped to the life of the object as opposed
to the life of the method.

258 hapter 9
constructors and gc

The difference between life and


scope for local variables:
public void doStuff(}
boolean b "" true;
Life go (4) ;
A local variable is alioeas long as its Stack }
frame is on the Stack. In other words, publio void go(int x) {
until the method. completes. int z .. x + 24;
crazy() ;
/ / imagine more code here
Scope
A local variable is in scope only within the
public void crazy()
method in which the variable was declared. char c III 'a';
When its own method calls another, the
variable is alive, but not in scope until its
method resumes. You can use a variable only
when it is in scope.

o doStuff() goes onthe


stack. Variable 'b' is
o goO plops on top of
theStack. 'x' and't
e crazyO Is pushed onto
the Stack, with 'c' now
o CfilZ'/O completes and
Is popped off the Stack,
alive andInscope. arealiveand in scope, alive andInscope. The so '(j is out of scope
and 'b' Is alivebut nof otherthree variables anddead, When goO
in scope. arealivebut out of resumes where It left
scope. off, 'x' and 'z' are both
aliveand back In scope.
Variable 'b' 16 stili alive
While a local variable is alive, its state persists. butout of scope (until
As long as method doStuffO is on the Stack, for goO completes).
example, the 'b' variable keeps its value. But the
'b' variable can be used only while doStuffO's
Stack frame is at the top. In other words, you can
use a local variable only while that local variable's
method is actually running (as opposed to
waiting for higher Stack frames to complete).

you are here ~ 259


object lifecycle

What about referettce variables?


The rules are the same for primtives and references. A reference
variable can be used only when it's in scope. which means you can't use
an object's remote control unless you've got a reference variable that's
in scope. The Teal question is,
An object's life has no
"How does variable life affect object life?"
value. no meaning. no
An object is alive as long as there are live references to it, If a reference
variable goes out of scope but is still alive, the object it refers to is still
rem. unless aomebody
alive on the Heap. And then you have to ask... "What happens when the
has a reference to it.
Stack frame holding the reference gets popped off the Stack at the end n you can't get to it.
of the method?"
you can't ask it to do
If that was the only live reference to the object, the object is now anything and it's jUst a
abandoned on the Heap. The reference variable disintegrated with big fat waste of bit&.
the Stack frame, so the abandoned object is now, officially, toast. The
trick is to know the point at which an object becomes eligiblefor garbage
collection:
i'
But an object is
unreachable. the
Once an object is eligible for garbage collection (Ge), you don't have Garbage CoUet:t« will
to worry about reclaiming the memory that object was using. If your f1gure that out.. Sooner
program gets low on memory, GC will destroy some or all of the eligible or later. that object'8
objects, to keep you from running out of RAM. You can still run out of
memory, but not before all eligible objects have been hauled off to the
gom'down..
dump. Your job is to make sure that you abandon objects (i.e, make
them eligible for GC) when you're done with them, so that the garbage
collector has something to reclaim. lfyou hang on to objects, GC can't
help you and you run the risk of your program dying a painful
out-of-memory death.

Three ways to get rid of an object's reference:


An object becomes
eligible for GC when G) The reference goes out of scope, permanently L
, , dies a~
void go () { ~t~t:YtrLt z.
its last live reference } Life z = new Life () ;~ e.-4 J ",dhod
disappears.
® The reference is assigned another object
~
. ha.-4~
~ o'o~el.t. ,s 0 , -to
Life z = new Life (); , / the ~;y-S, _YO",,,,e&
z '" new Life () ; ~ "'''''' z.;1 yeyY-;,
a TIt'" o\:>jtt.t..
'3'
\:!,J
The reference is explicitly set to null
~ t. do" tt.'{.L'\1 .."L~~ed
(1<1 I
Life z '" new Li fa () ; the iyS. ' .1~ _yo...",e& .
z = null; (- ",'neYl z. \S l) r"-.J

260 ch apt er 9
constructors and gc

Object-killer #1
Reference goes
out of scope,
permanently.

I
I
public class StaclcR.ef {
public void foof() (
I
I
I
barf () ; I
I

public void barf() ( I


Duck d : new Duck() ;

o loof(J Is pushed ontothe


Stack, no variables are
declared.

o barf(J Is pushed onto the


Stack, where It declares
a reference variable, and
creates a new objectas-
signed to that reference.
The objectIs created on
the Heap, andthe refer-
ence Is alive and In scope.

Uh-oh. TIll: 'd' variable


w~t d'Na,! 'Nne" th~ bar·W

e bartO completes and pops


off the Stack. Its frame
SUlk t..a",e 'Na~ blo'Nft
o-f.f the stalk, so tht Dutlt
disintegrates, so 'd' Is now is aba"dClr\td. ~arba~t:­
dead andgone. Execution lollak bait.
returns to 100'0, but 100(0
can't use'd' .

yo u are here ~ 261


object lifecycle

Object-killer #2
Assign the reference
to another object

public class ReRef { Dude,all you


had to do was reset
Duck d = new Duck(); the r~ference. Guess
public void qo() { they didn't have memory
d = naw Duck () ; management back then.

o
o

The new Du.tk. ~oes on t he !leaf, . . e~et"tnLeci


b~ 'ei', ~nte '0' is cln inSt.a!'lte variable, tne
D",-\I. will live as \Ol'l~ as ~e ReRt.t obit.d:.
that il\5-t.al'ltiaW it is alive. l.()\less-..

'£1' is as.si~\'IeO a !'lew Du.t\l. objt.tt, leav\!'I~ the


ori~i\'lal ah'st) DlAl.k objed:. ahal'loont.o. That
tirst D",-k is 1\0,", as ~ood as dead..

262 chapter 9
constructors and gc

Object..killer #3
Explicitly set the
reference to null

public class ReRef {

Duck d == new Duck () ;

public void gal) (


d == nul.l:

Tee ~ D\oll.k ~oes ~ th~ \-ledf' y~.ftytyo,Ud


b'j 'd'. Sil'\U 'd' is a" inrtal'I U vaW'i4bl~, th~
The meaning of null
DlItlc. will live as l~~ as th~ R~c.f obj~l:1:
When you set a reference to nuJ.l, you're that. i~'I\tiat.ed it. is alive. U"Ies.s-··
deprogramming the remote control.
In other words, you've got a remote
control, but no TV at the other end. A null
reference has bits representIng 'null' (we
don't know or care what those bits are, as
long as the NM knows) .

If you have an unprogrammed remote


control, In the real world, the buttons don't
do a nythlng when you press them. But
In Java,you ca n't press the buttons (I.e.
use the dot operator) on a null reference,
because the NM knows (this Is a runtime
Issue,not a complier error) that you're
expecting a bark but there's no Dog there
to do Itl

If you use the dot operator on


a null reference. you'll get a
NullPolnterExceptlon at runtime. You'll
learn all about Exceptions In the Risky
Behavior chapter.

you are here ~ 263


object lifecycle

Fireside Chats Tonight'g Talk: An instance variable and

~4 a looal variable discuss life and death


(wi~ remarkable civilliy)

~
Instance Variable Local Variable
I'd like to go first, because I tend to be more
important to a program than a local variable.
I'm there to support an object, usually
throughout the object's entire life. After all,
what's an object without slate? And what is I appreciate your point of view, and I certainly
state? Values kept in instana variables. appreciate the value of object state and all,
but I don't want folks to be misled. Local
variables are really important. To use your
phrase, "After all, what's an object without
behaviorr" And what is behavior? Algorithms
in methods. And you can bet your bits there'll
be some local variables in there to make those
No , don't get me wrong, I do understand your algorithms work.
role in a method, it's just that your life is so
short. So temporary. That's why they call you
guys "temporary variables". Within the local-variable community, the
phrase "temporary variable" is considered
derogatory. We prefer "local", "stack" , "auto-
My apologies. I understand completely. matic", or "Scope-challenged",
Anyway, it's true that we don't have a long
life, and it's not a particularly good life either.
First, we're shoved into a Stack frame with
all the other local variables, And then, if the
method we're part of calls another method,
another frame is pushed on top of us. And if
that method calls another method... and so on.
Sometimes we have to wait forever for all the
other methods on top of the Stack to com-
I never really thought about it like that. What plete so that our method can run again.
are you doing while the other methods are
running and you're waiting for your frame to
Nothing. Nothing at all. It's like being in
be the top of the Stack again?
stasis-that thing they do to people in science
fiction movies when they have to travel long
distances. Suspended animation, really. We
just sit there on hold. As long as our frame is
still there, we're safe and the value we hold
is secure, but it's a mixed blessing when our .

264 c ha pte r 9
constructors and gc

IDstance Variable Local Variable


frame gets to run again. On the one hand, we
get to be active again. On the other hand, the
clock starts ticking again on our short lives.
The more time our method spends running,
th e closer we get to the end of the method.
We saw an educational video about it once. We all know what happens then.
Looks like a pretty brutal ending. I mean,
when that method hits its ending curly brace,
the frame is literally blownoff the Stack! Now Tell me about it. In computer science they use
that 's gotta hurt. the term poppedas in "the frame was popped
off the Stack". That makes it sound fun , or
maybe like an extreme sport. But, well, you
saw the footage. So why don't we talk about
you? I know what my little Stack frame looks
like, but where do you live?
I live on the Heap, with the objects. Well, not
with the objects, actually in an object. The
object whose state I store. I have to admit life
can be pretty luxurious on the Heap. A lot of
us feel guilty, especially around the holidays. But you don't always live as long as the object
who declared you, right? Say there's a Dog
object with a Collar instance variable. Imagine
you're an instance variable of the Collarobject,
maybe a reference to a Buckle or something,
sitting there all happy inside the Collarobject
who's all happy inside the Dogobject. But...
what happens if the Dog wants a new Collar,
or nulls out its Collar instance variable? That
makes the Collar object eligible for GC. So...
if you 're an instance variable inside the Collar,
OK, hypothetically, yes, if I'm an instance and the whole Collaris abandoned, what
variable of the Collar and the Collar gets happens to you?
GC'd, then the Collar's instance variables
would indeed be to ssed out like so many pizza
boxes. But I was told that this almost never
happens.
And you believed it? That's what they say to
keep us motivated and productive. But aren 't
you forgetting something else? What if you 're
an instance variable inside an object, and that
object is referenced only by a localvariable? If
I'm the only reference to the object you're in,
when I go, you're coming with me. Like it or
not, our fates may be connected. So I say we
forget about all this and go get drunk while
They let us drink? we still can. Carpe RAM and all that.

you are here ~ 265


exercise: Be the Garbage Colleclor

BE the Garbage CtJTIector


Wlnch 01' the lines of code onthe rigbt, if added
to & class on the left at point A, would eaase
exactly one additional object to he eliglhle for the
Garbage Collector? (AsSUlJle that point A(licall
more methods) will execute for a long time, giving the
Garbage Collector time to do its stu1f.)

public class GC (
public static GC doStuff()
GC newGC = new GCI)i 1 copyGC = nulli
doStuff2(newGC);
return newGCi 2 gc2 = null;

3 newGC = gc3;
pUblic static void maln(String [1 args) (
GC gel; 4 gel = null ;
GC gc2 = new GCI);
GC gc3 = new GCI) ; 5 newGC = null;
GC ge4 = gc3j

gel = doScuff(); 6 gc4 = null;

7 gc3 = gC2i
II call more methods

8 gel = gc4i

public static void doStuff2(GC copyGC) 9 gc3 nu Ll.;


GC localGC

266 chapter 9
constructors and gc

In this code example, several new objects are created.


Your challenge is to find the object that is 'most popular;
i.e. the one that has the most reference variables referring
to it. Then list how many total references there are for
that object, and what they are! We'll start by poi nti ng au t
one of the new objects, and its reference variable.
class Bees {
Good Luck!
Honey I] beeHAj
}

class Raccoon {
Kit Xi
Boney rh;
}

class Kit (
Boney kh;
}

class Bear {
Boney hunnYi
}

pUblic class Honey {


public static void main(String [] arqs) {
Roney honeyPot = new HoneY()i
Boney I] ha = {honeyPot, honeyPot, honeyPot, honeyPot};
Bees bl = new Bees():
bl. beeRA = ha;
Bear [) ba = new HearlS];
for (int x=O; x < 5; x++)
ba!x] = new Hear();
ba[x).hunny = honeyPot;
}
Kit k = new Kit()i
Here's a new
k.kh '" honeyPot; ~ Raccoon objectl
Raccoon r '" new Raccoon()i

~
r.rh = honeypot:
Here's Its reference
variable ·r'.
r.k '" Xj
k = null;
} II end of main
}

you are here ~ 267


puzzle: Five Minute Mystery

"We've run the simulation four times, and the main module's temperature consistently
drifts out of nominal towards cold", Sarah said, exasperated. "We installed the new temp-bats last
week. The readings on the radiator bats, designed to cool the living quarters, seem to be within
spec. so we've focused our analysis on the heat retention bats, the bats that help to warm the quar-
ters." Tom sighed, at first it had seemed that nano-technology was going to really put them ahead
of schedule. Now, with only five weeks left until launch. some of the orbiter's key life support
systems were still not passing the simulation gauntlet.
"What ratios are you simulating?", Tom asked.
"Well if I see where you're going, we already thought of that", Sarah replied. "Mis-
sion control will not sign off on critical systems if we run them out of spec . We are
required to run the v3 radiator bat's SimUnilS in a 2:1 ratio with the v2 radiator's
SimUnits", Sarah continued. "Overall, the ratio of retention bots to radiator bats is
supposed to run 4:3."
"How's power consumption Sarah?", Tom asked. Sarah paused. "Well that's
another thing, power consumption is running higher than anticipated. We 've got a team
tracking that down too, but because the nanos are wireless it's been hard to isolate the power
consumption of the radiators from the retention bats ." "Overall power consumption ratios", Sarah
continued. "are designed to run 3:2 with the radiators pulling more power from the wireless grid."
"OK Sarah", Tom said "Let's take a look at some of the simulation initiation code.
We've got to find this problem, and find it quick!"

import java.util.·;
class V2Radiator {
V2Radiator(ArrayList list) (
for(int ~O; x<57 x++) (
list.add(new SlmUnit{MV2Radiator U
) ) ;

class VJRadiator extends V2Radiator


V3Radiator{ArrayLlst lqlist)
super ( 19list) ;
for{lnt gmO; g<107 q++) {
lqlist.add(new SimUnit(MVJRadiator » 1 H

class RetentionBot {
RetentionBot(ArrayList rlist) {
rlist.add(new SimOnit(MRetention-»)

268 chapter 9
constructors and gc

public class TestLifeSupportSim {


rIVe-MInute public static void main(String [J args) {
ArrayList aList = new ArrayList();
Mystery V2Radiator v2 = new V2Radiator(aList);

C<intlnued... V3Radiator v3 = new V3Radiator(aList);


for(int z=O; z<20; z++) {
RetentionBot ret = new RetentionBot(aList);

class SimUnit {
String botType;
SimUnit(String type) {
botType = type;
}
int powerUse() {
if (URetention u.equals(botType»
return 2;
else {
return 4;

Tom gave the code a quick look and a small smile creeped across his lips. I think I've
found the problem Sarah, and I bet I know by what percentage your power usage readings are off
too!

What did Tom suspect? How could he guess the power readings errors, and what few
lines of code could you add to help debug this program?

you are here ~ 269


object Iifecycle

1 copyGC = null; No - this line attempts to access a variable


that is out of scope.
2 ge2 =' null; OK - 9c2 was the only reference variable
referring to that object.
3 newGC =' gc3; No - another out of scope variable .

4 gel = null; OK - gel had the only reference because


G.C. 5 newGC = null;
newGC is out of scope.
No - newGC is out of scope .

6 gc4 null; No - gc3 is still referring to that object.

7 gc3 gc2; No - 9c4 is still referring to that object.

8 gcl gc4; OK - Reassigning the only reference to


that object.
9 gc3 null; No - gc4 is still referring to that object.

It probably wasn't too hard to figure out that the Honey obJectfirst referredto by the honeyPot variableis by
farthe most -popular'object Inthis class. But maybe it was a littletrickier to see that all of the variablesthat
point from the code to the Honey object referto the same ob}edl There are a total of 12active referencesto
this object right before the maln() method completes. The Ic.kh variableis valid fora while,but kgets nulled
at the end. Sincer.kstili refersto the KIt object, r.k.kh (although never expllcitydeclared),refersto the object!

public class Boney {


public static void main(Striog [) args) {
Boney honeyPot ~ new Boney();
Boney [) ha = {noneyPot, honeypot,

L
honeyPot, honeYPot};
Bees bi m new Beesl);
bl.beeHA = ha;
Bear [) ba = new BearIS];
for (int x-OJ x < 5; x++) {
ba{x] = new Bear():
ba[xj.hunny c honeyPot;
T ( ends up null )
}
I 1 - - - Kit k = new Kit();
k.kh => honeyPot;
1- ---J
Raccoon r • new Raccoon();

r.rh = honeyPot:
r.k - k;
k • null;
}} II end of main

270 chapter 9
constructors and ge

Tom noticed that the constructor for the V2Radiator class took an
ArrayList. That meant that every time the V3Radiator constructor was called,
it passed an ArrayList in its supert) call to the V2Radiator constructor. That
meant that an extra five V2Radiator SimUnits were created. If Tom was right,
total power use would have been 120, not the 100 that Sarah's expected ratios
predicted.
Since all the Bot classes create SimUnits, writing a constructor for
the SimUnit class, that printed out a line everytime a SimUnit was created ,
would have quickly highlighted the problem!

you are here 271


10 numbers and statics

Numbers Matter

Do the Math. But there's more to working with numbers than Just doing primitive

arithmetic. You might want to get the absolute value of a number, or round a number, or flnd

the larger of two numbers. You mig ht want you r numbers to prl nt with exactly two decImaI

places, or you might want to put commas Into your large numbers to make them easier to read.
And what about working with dates? You might want to print dates In a variety of ways,or even
manipulate dates to say things like, "add three weeks to today's date" And what about parsing
a String Into a number? Or turning a number into a String? You're In luck. The Java API Is full of

handy number-tweaking methods ready and easy to use. But most of them are static, so we'll
start by learning what it means for a variable or method to be static, including constants In

Java-static final variables.

this IS a new chapter 273


Math methods

MArH tMethods: as close as you'll


ever get to a globa/tMethod
Except there's no global an),lhinginJava. But think about
this: what if you have a method whose behavior doesn 't
depend on an instance variable value . Take the round()
method in the Math class, for example. It does the same
thing every time-rounds a floating point number(the Methods in the.Math class
argument to the method) to the nearest integer. Every
time. lfyou had 10,000 instances of class Math, and ran
don't use any mstance
the round(42.2) method, you'd get an integer value of variable values. Ami because
42 . Every time. In other words, the method acts on the
argument, but is never affected by an instance variable
the methods are 'static',
state. The only value that changes the way the round() you don't need to have an
method runs is the argument passed to the methodl
illstance of.Math. All you
Doesn't it seem like a waste of perfectly good heap space
need is the Math class.
to make an instance of class Math simply to run the
round () method? And what about other Math methods
like mint), which takes two numerical primitives and
-
returns the smaller of the two. Or maxj). Or abst), which int x - Math.round(42.2) ;
returns the absolute value of a number. int y = Math.min(56,12) i
int z = Math.abs(-343);
These methods never we instance variable values. In fact the
Math class doesn't have any instance variables. So there's
nothing to be gained by making an instance of class
Math. So guess what? You don't have to. As a matter of
fact. you can 't,

If you try to make an instance of


class Math:
Math mathObject = new Math () i

You'll get this error:

274 chap ter 10


numbers and statics

fhe differet1ce betweeM regular


(.,on-static) at1d static tttethods
Java is object-oriented, but once in a while you have a special case,
typically a utility method (like the Math methods), where there is
no need to have an instance of the class. The keyword static lets
a method run without any instance o/the class. A static method means
"behavior not dependent on an instance variable, so no instance/object
is required.Just the class."

regular (non-static) method


-
static method

public class Soog ( a '.~'o\( "a\~ ~tt.L~


I~,.{,e ~
....." \ .J)
Strine} title; ~ the Otha"\~ cJ tht yar
public Sone} (String t) ".~~o<!.
public int min(int a, int b) (
tiUe = ti
//returns the lesser of a and b
}
public void play()
SoundPlayer player = new SoundPlayer () i
Math
player .playSound(tiUB)i
J ~e 'title'
minD
\' maxD
nt l."l'l'tJ\t.. "~I\~
L. e
1/.11'\<10
Lhe
IS ~
WTI~ that abs()
Song i"sv"tt. La\\ yl<l,/{)'
~\a'fS ...."e" 'to'J
tltIe

Song

you are here ~ 275


static methods

Call a static method using a


class name
Math . min (B8, 86) ;
mlnO
maxO
absO

Call a non-static method using a


reference variable name
Song t2 V--
= new Song() ;
.play () ;

What it tHea.,s to have a


class with static Ittethods.
Often (although not always), a class with static This does not mean that a class with one or more
methods is not meant to be instantiated. In Chapter static methods should never be instantiated. In fact,
8 we talked about abstract classes, and how marking every class you put a mainO method in is a class with
a class with the abstract modifier makes it a static method in itl
impossible for anyone to say 'new' on that class type.
Typically, you make a main 0 method so that you
In other words, it's impossible to instantiate an abstract
can launch or test another class, nearly always by
class.
instantiating a class in main, and then invoking a
But you can restrict other code from instantiating method on that new instance.
a non,,·abstract class by marking the constructor
So you're free to combine static and non-static
private. Remember, a method marked private means
methods in a class, although even a single non-static
that only code from within the class can invoke method means there must be S~ way to make an
the method. A constructor marked private means
instance of the class. The only ways to get a new
essentially the same thing-only code from within object are through 'new' or deserialization (or
the class can invoke the constructor. Nobody can
something called theJava Reflection API that we
say 'new' from outside the class. That's how it works
don 't go into). No other way. But exactly WM says new
with the Math class, for example . The constructor
can be an interesting question, and one we'Ulook at
is private, you cannot make a new instance of Math.
a little later in this chapter.
The compiler knows that your code doesn't have
access to that private constructor.

276 chapter 10
numbers and statics

Static tMethods caM'f use t1ot1.. statle


(instance) variables!
Static methods run without knowing about any particular
instance of the static method's class. And as you saw on
If you trj to use an
the previous pages, there might not even beany instances inStance variable from
of that class. Since a static method is called using the class
(Math.random()) as opposed LO an mstance reference (t2.playO), inside a static method.
a static method can't refer to any instance variables of the
class. The static method doesn't know which instance's variable
the compiler thitiks.
value to use. "I don't "know which
object's mstance variable
If you try to compile this code: you're talking about!"
public olass Duck ( y,[nit,'I'I 'D.,.t.~~ If you have ten DuCK
~(f.e ~\1,.l. .
private lnt size; ~ ( objects on the heap. a
public static void main (String[] arqs) ( ~ static method doesn't
System.out.println("SizfiIl of duck is " + size):
"know about any ofthem.
1.( fh~e's d DlAlk on
public void setsize (int 09) ~e):eap So"'ewhet-e, we
size = s; on ~ KI'IO'w dboc..i it
}
public iot getSize()
return size;

You'll get this error:

you are he re ~ 277


static methods

Static tMethods cattJt use "ott"'statlc


methods.. either! Q: What If you try to call a non-static
method from a static method, but the
What do non-static methods do? They usuaUy use instance non-static method doesn't use any In-
variable state tv affect the behavior of the method. A getName () stance variables. WIll the compiler allow
method returns the value of the name variable. Whose name? that?
The object used to invoke the getNameO method.

This won't compile: A: No.The compiler knows that


whether you do or do not use Instance
Cdl!il\~ ~efs.~() .t.st
public class Duck { ~~ ih~vji:db'e-4JS; ~os) tpolles variables In a non-static method, you can.
the si . And th ink about the impl ications ... if you
U
L J
I)UUI\le variabje.IA1l.s
IU
were allowed to compile a scenario like
private iot size; that, then what happens if in the future
you want to change the implementation
public static void main (Strinq[] args) ( of that non-static method so that one day
System.out.println(~Size is ~ + getsize()):
It does use an Instance variable? Or worse,
what happens if a subclass overrides the
method and uses an Instance variable in
public void setsize(int s) { the overriding version?
size = B;
}
public iot getsize()
return size;
Q: I could swear I've seen code that
calls a static method uslng a reference
variable Instead of the class name.

A: You can do that, but as your mother


always told you, "Just because it 's legal
doesn't mean it's good." Although It works
to call a static method using any instance
of the class,it makes for misleading (less-
readable) code.You can say,
Duck d = new Duck():
String[] s = {};
d.main(s);

This code is legal, but the complier Just


resolves It back to the real class anyway
("01( d Is of type Duck, and malnO Is static,
so I'll call the static malnO in class Duck").
In other words, using d to Invoke main£)
Roses are red,
m late doesn't Imply that maln() will have any
and known to bl00 special knowledge of the object that d Is
referencing. It's Just an alternate way to
StCJtlcs cCJn'. see Invoke a static method, but the method Is
instCJnce variable state still static!

278 c ha pte r 10
numbers and statics

Static variable:
value is the satHe for ALL
i"sta"ces of the class
Imagine you wanted to count how many Duck
instances are being created while your program is
running. How would you do it? Maybe an instance
variable that you increment in the constructor?
pub11c Duck ()( Now if. will ~
class Duck { dUckCountH; ~j"'rbnbli:i tp
int duC](Count =
0; ) the DlAlk lIS c.ilh b"'t
public Duck () {
bet.i~ d~t.ot. "uls,
dUckCount++; .ll'
l:",s wOIA1d I Gild 'fiIIOrl'f bt ~i is sidfit
~ dlAl.ke- d 'WdYS ~t ~i.oO.
d D k "i -&, J ~lh ti public void lfetSlze (int s) (
l.tt WdS r...id/! ...e size = !!I;
No, that wouldn't work because duckCount is an •
p ublic int qetslze ()
instance variable, and starts at 0 for each Duck. You return size;
could try calling a method in some other class, but
that's kludgey. You need a class that's got only a single
copy of the variable, and all instances share that one
copy.
That's what a static variable gives you: a value shared
by all instances of a class. In other words, one value
per class, instead of one value per instance.

Duck

you are here ~ 279


static variables

Static variables are shared.

All instances 01 the same


class share a single copy 01
the static variables.

instance variables: 1 per instance


static variables: 1 per class

~J:V Brain Barbell


Earlier in this chapter, we saw that a private
constructor means that the class can't be instantiated
from code running outside the class. In other words,
only code from within the class can make a new
instance of a class with a private constructor. (There's
a kind of chlcken-and-egg problem here.)

What If you want to write a class In such a way that


only ONE instance of It can be created, and anyone
who wants to use an instance of the class will always
use that one, single Instance?

280 chapte r 10
numbers and statics

htitializhtg a static variable


Static variables are initialized when a class is loaded: A class is
loaded because thejVM decides it's time to load it. Typically, All static variables
the jVM loads a class because sornebody's trying to make a
new instance of the class, for the first time, or use a static
in a class are
method or variable of the class. As a programmer. you also Initialized before
have the option of telling thejVM to load a class, but you're any object of
not likely to need to do that. In nearly all cases, you're better
off letting the jVM decide when to wad the class.
that class can be
created.
And there are two guarantees about static initialization:
Static variables in a class are initialized before any object of that
class can be created.
Static variables in a class are initialized before any static method
of the class runs.
olass Player {
static int playerCount ;:; 0;
private String name;
public Player(String n)
n&IIl8 = n;
playerCount++ ;

public class PlayerTestDrive (


public static void main (Strin'll] llrgs) (
Syabam.out.println(Player.playerCount);
Player one = new Player("Tiqer Wooda H ) ;

Syst8m.out .println(Player .playerCount);

\. Atuu a stitt Vjly',able j\<St. like a Sta-t'I(.


...d.hod-wit.h the tlass l'Id",e.

Static variables are initialized when the class is loaded. If you


don't explicitly initialize a static variable (by assigning it a
value at the time you declare it), it gets a default value, so int
variables are initialized to zero, which means we didn't need
to explicitly say "playerflount = 0", Declaring. but not initial-
izing, a static variable means the static variable will get the de-
fault value for that variable type, in exactly the same way that
instance variables are given default values when declared.

you are here ~ 281


static final constants

-
static fh1al variables are cot1stat1ts
A variable marked finalmeans that-s-once initialized-it can
never change. In other words, the value of the static final variable
will stay the same as long as the class is loaded: Look up Math.PI
in the API, and you'll find:
public static final double PI = 3.141592653589793;
The variable is marked public so that any code can access it.
The variable is marked static so that you don't need an
instance of class Math (which, remember, you're not allowed to
create).
The variable is marked final because PI doesn't change (as far as
Java is concerned).
There is no other way to designate a variable as a constant, but
there is a naming convention that helps you to recognize one.
Constant variable names should be in all caps!

Initialize a Rnal static variable:


• At the time you declQl"t It: If you don't give a value to a finol vorlable
public clulS ]1'00 ( in one of those two places:
publ~c static final lot FCC_X = 25;
public class Bar (
~t.e tJ,e ~ . '\ public static final double BAR_SIGN ;
tj~} I/ariabl ""~ lor.vblt OPl
~"'~ shOlJ.}d
lAPldc....,._.
be all "pp&
di-e ~)lb -~~i.lbt.
so J Ule
110 illi'b _}il4 t;olll

. -~ $Cpal"'ab .l,f.d$C, ....,i~ all


OR ~ Ule 'worcit
The complier will catch It:
• In 0 static Inltfollzer:
public class Bar {
public IlltatiC final double BAR SIGN;
numbers and statics

fitlal iSKt just for static


variables...
You can use the keyword final to modify non- A linaL variable means you
static variables too, including instance variables.
local variables, and even method parameters. In can't change its value.
each case, it means the same thing: the value can't
be changed. BUl you can also use final to stop
someone from overriding a method or making a
subclass.
A tinal method means you
non-static final variables
clan Foo! ( 'f0!> t.'!,,'f, thd,,~e S'IU
can't override the method.
final Int size '" 3; f-- YI()W

final int whuffi.e;

Foof () (
whuffie = 42; ~ \'\ow 'fo ... t<lI'I't Lha,,~e Wh
I.H'
re A tinal class means JOU
)
can't extend the class (i.e.
void doStuff{final iet x)
I I you can' t change )Ii you can't make a subclass).
void doMore () (
final iet z '" 7;
II you can't change z

final method
class Poo£ (
final void calcWhuffi.e ()
II ~rtant things
II that must never be overridden

final class
final class MyMostPer£ectClass
II cannot be llIxtended

you are here ~ 283


static and final

Q...: Astatic method can't access II • A static method should be called using the class
non-static variable. But can a non-statlc name rather than an object reference variable:
method access II static variable? Mao th . random () vs. myFoo . go ( )
• Astatic method can be invoked without any Instances
A: Of course.A non-static method ina
class can always call a static method In the
ofthe method's class on the heap.
• Astatic method isgood for autility method that does
class or access a static variable of the class.
not (and will never) depend on a particular Instance
variable value.
• Astatic method is not associated with aparticular
Q...: Why would I want to make a class instanee----only the c1ass---so Itcannol access any
final1 Doesn't that defeat the whole Instance vanable values offts class. Itwouldn't know
purpose of 007 which Instance's values to use.
• Astatic method cannot access anon-static method,
A: Yes and no. A typical reason for
making a class final Isfor security.You
since non-static methods are usually associated with
instance variable state.
can't, for example, make a subclass of the • Ifyou have a class with only static methods, and you
String class.Imagine the havoc If someone do not want the class tobe instantiated, you can mark
extended the String class and substituted the constructor private.
their own String subclass objects,
polymorphically, where String objects • A static variable isa variable shared byall members
are expected. Ifyou need to count on a ofa given class. There isonly one copy ofa static
particular Implementation of the methods variable ina class, rather than one copy per each
Ina class,make the class final. individual instance for instance variables.
• Astatic method can access a static variable.
• To make a constant in Java, mark a variable as both
Q...: Isn't It redundant to have to mark static and final.
the methods final Ifthe class Is final?
• Afinal static variable must be assigned a value either
atthe time it isdeclared, orin a static initializer.
A: If the class Is final,you don't need to
rnarkthe methods final. Thinkabout It-If
static {
DOG_CODE:: 420;
a class Isfinal It can never be subclassed, }
so none ofthe methods can ever be
• The naming convention for constants (final static
overridden.
variables) Is to make the name aU uppercase.
On the other hand, If you do want to allow
others to extend your class,and you want • A final variable value cannot be changed once Ithas
them to be able to override some, but not been assigned.
all,of the methods, then don't mark the • Assigning a value to a final Instance variable must be
class final but go In and selectively mark either at the time It Is declared, orinthe constructor.
specific methods as final. A final method
means that a subclass can't override that • Afinal method cannot be overridden.
particular method. • Afinal class cannot be extended (subclassed).

284 chapter 10
numbers and statics

~ yoor pencil
What's Legal?
Given everything you've just
learned about static and final,
which of these would compile?
...
KEEP

RIGHT

• public clll.Sl! 11'00


static: int Xi

public: void go() (


Systam.out.println{x) ;
• public class F004
BUtic final int x

public: void go() (


12;

Systam.out.println(x) ;

• public c:lass Foo2 {


int Xi

public static void go () (


Syatem.out.println(x);
• public: c1ass Foo5 (
statio tiDal int X '" 12;

public void go (final int x)


System .out.println(x);

• public class Foo3


final int X i

public: void go() (


Syatem.out.println(x);
• public class Foo6
int x '" 12;

public static void go(final int x) (


SyatBm ,out.println{xl;

you are here) 285


Math methods

Math lItethods
Now that we know how static
methods work, let's look Math.random{)
at some static methods in Returns a double between 0.0 through (but
class Math. This isn't all of not including) 1.0.
them,just the highlights. double rl = Math. random 0 ;
Check your API for the rest int r2 = (int) (Math.random() * 5);
including sqrtf), tant), ceilf),
floor'(), and asint).
Math.absO
Returns a double that is the absolute value of
the argument. The method is overloaded, so
if you pass it an int it returns an into Pass it a
double it returns a double.

int x = Math .abs(-240); II returns 240


double d = Math.abs(240.45); II returns 240.45

Math.roundO
Returns an int or a long (depending on
whether the argument is a float or a double)
rounded to the nearest integer value.
int x = Math.round( -24.8f); II returns -25
int y = Math.round(24.45f); II returns 24
t
Re"'e",bel"', .floa'bn~ point lit el"'als al"'e ass"''''ed
to be do",bles "'nless yo", add t he '.f',
Math.minO
Returns a value that is the minimum of the
two arguments. The method is overloaded to
take ints , longs, floats, or doubles.
int x = Math.min(24,240); II returns 24
double y = Math.min(90876.5, 90876 .49); II returns 90876.49

Math.maxO
Returns a value that is the maximum of the
two arguments. The method is overloaded to
take ints, longs, floats, or doubles.
int x = Math.max(24,240); II returns 240
double y = Math.max(90876 .5, 90876.49); II returns 90876.5

286 chapter 10
numbers and statics

Wrappit1g a pritttifive
Sometimes you want to treat a primitive like
an object For example, in all versions ofJava
~ object
prior to 5.0, you cannot put a primitive directly
into a collection like ArrayList or HashMap:
int x :: 32;
ArrayList list = new ArrayList();
list. add (xl i ~

This
't
'010" '" wO'r
s:
I"" t.:SS dr. L \ \&Si~Java
k 1
Tht"e s J>O a ,''v '"
L -~II
'S .O m-
od '11\ ~a'J!-ist.
() I _L~ods
primitive
~\'"ea=.. . LI (b...~ !-. t. 01\1'1 has add "'CV'
t.hat. takes a" ,,,'t.. f"lYTiJ'f ~ L . ' t.iv )
that. take objed:. ""t~ueJl(.t.s, fIO't. ~''''I es·
When you need to treat
There's a wrapper class for every primitive type,
and since the wrapper classes are in the java. a primitive like an object,
lang package, you don't need to import them .
You can recognize wrapper classes because
wrap it. Ii you're using any
each one is named after the primitive type it
wraps, but with the first letter capitalized to
version of Java before 5.0,
follow the class naming convention. you'll Jo this when you
Oh yeah, for reasons absolutely nobody on the
planet is certain of, the API designers decided need to store a primitive
not to map the names exactly from primitive
type to class type. You'll see what we mean:
value inside a collection like
Boolean ArrayList or lIashMap.
Chara~ter ~
Byte Watth 0I<t.! The N",es al"'~"J.t..
Short / ",ayyed e'll4d.l'f to the ~1"'i~l\Jt
t~s. The tlolS na...es are .. 'f
Integer sfelltd o>J.t..
Long
..,.."
Float int 1I
Double ~'feger o~f

Note: the plchJre III \he top Is a chocolate In e roll wrapper. Get
It? WraPP6r? Some people think It looks like a baked potato. bill
\hilt Wlll1ls100.

you are here. 287


static methods

This is stupid, You mean I can't


just makean ArrayList of ints??i I
have to wrap every single frickin' one in a new
Integer object, then unwrap it when I try
to access that value in the ArrayList?
That's a waste of t ime and an error
waiting to happen..,

Jefore Java 5:0, YOU had to do the work...


-
She's right. In all versions ofJava prior to 5.0, primitives were primitives
and object references were object references. and they were NEVER
treated interchangeably. It was always up to you, the programmer, to do
the wrapping and unwrapping, There was no way to pass a primitive to a
method expecting an object reference, and no way to assign the result of a
method returning an object reference directly to a primitive variable----even
when the returned reference is to an Integer and the primitive variable is
an int, There was simply no relationship between an Integer and an int,
other than the fact that Integer has an instance variable of type int (to hold
the primitive the Integer wraps). All the work was up to you.

An ArrayList of primitive ints

Without autoboxing (Java versions before 5.0)


t '? 0 ~~ tau\Jl.I l'lO"{.t,
Arr L:rt.- (Rt",t",'ber, be oYt. ' ~ Db' c.h)
pub Li c void doNumsOldWay () { Malu al'l a~/p'2- all l\rYa~L.i~b ..n:r~ \i~b ~e '
1feGi~~ t\o.t T 1 ' ~
ArrayList listOfNumbers = new ArrayList();
. 1., ('l' L
l
t.hl lise-,
I t add t\o.e yr"I"'IU llt ? \P .
listOfNumbers, add (new Integer (3» i ~ you c.a~~ i . wYa o "r\:. 'n' dl'l ll\u~~"" ~1""St.
so '/0'0' n<I\I~ \P I

In teger one = (Inteqer) lis tofNumbers . ge t (0) ; ~""'lS O'o't as t'fVl


Ob'td:., but. ~O'o> Ga" l..dst.
int intone = ODe. intValue () ; t.h~ ObjtGt to al\ I"U~er .

Fihd/ly y~ td" tt "


out 0+ the Inu~. hI! pl"''''ltivt:'

2BB chapter 10
numbers and statics

Autoboxing: blurring the line


between pritMitive and object
The autoboxing feature added to Java 5.0 does
the conversion from primitive to wrapper object
automatically!
Let's see what happens when we want to make an
ArrayList to hold ints.

An ArrayList of primitive ints

With autoboxing (.Java versions 5.0 or greater)


l1. L: t ok t'j\'e Il'lteCjer.
public void doNumsNewWay() { Make al'l f\rra~ IS

-l
ArrayList<Integer> listOfNumbe rs new Arra yList<Integer>();

li stOfNumbe rs.add(3); JlASt add it ! AH:holA~h there is NOT a ",eihod il'l ArrayList
.f01" add(iI'lV, the lon-piler does all the wrafpil'l5
int num = listOfNumbers.get(O); (bo)/,;n5) .for 'lOlA. 11'1 other words, there I"eall'l IS
a\'l Il'Ite~el" objelt stored il'l the Al"l"a'll-ist. blAt

:h':
"
I:~~~~~e:;uto",atilally ul'lwraps (IAl'lbo~es)
direli! to a :.lei"" ~o yo~ lal'l assi51'1 the int va/loe
intVallA~() fr Itlve '~/IthOlAt havin5 to lall the
....ethod 0\'1 the Inte5er objelt.
'lOlA 5et to "pl"etend" that the ~l"a'lList takes
ints. cyOIA lan add both ints al'ld l\'Ite~ers to al'l
A'f'l"a'lList<lnte~er>.)

Q.: Why not declare an ArrayList<int> if you want to


hold ints7

A.: Because...you can't. Remember,the rule for generic


types is that you can specify only class or interface types, not
primitives. So ArrayList<int> will not compile. But as you can
see from the code above, it doesn't really matter, since the
compiler lets you put ints into the ArrayList<lnteger>.ln fact,
there's really no way to prevent you from putting primitives
into an ArrayList where the type of the list is the type of that
primitive's wrapper, if you're using a Java S.D-compliant com-
piler, since autoboxing will happen automatically. So,you can
put boolean primitives in an ArrayList<Boolean> and chars
into an ArrayList<Character>.

you are here ~ 289


staUc methods

Aufoboxit1Q works al",ost everywhere


Autoboxing lets you do more than just the obvious wrapping and
unwrapping to use primitives in a collection... it also lets you use
either a primitive or its wrapper type virtually anywhere one or the
other is expected. Think about thatl

Fun with autoboxing

Method arguments
If a method takes a wrapper type, you
can pass a reference to a wrapper or
a primitive of the matching type. And
of course the reverse is true-if o
.~
"''>1''ger Ol:i~ /
\1
int
method takes (] primitive, you can
pass in either a compatible primitive
or a reference to a wrapper of that void takeNumber(Integer i) { }
primitive type.

Return values int giveNumber ()


If a method declares a primitive return X;
return type, you can return either a
compatible primitive or a reference
to the wrapper of that primitive type.
And if a method declares a wrapper
return type, you can return either a
reference to the wrapper type or a
primitive of the matching type.

Boolean expressions true


Any place a boolean value is expected,
you can use either an expression that
evaluates to a boolean (4 ) 2), or a ~/ean o~f
\1
boolean
primitive boolean, or a reference to a
Boolean wrapper.
~f
if (bool) {
System.out.println("true H
) ;

290 chapter 10
numbers and statics

Operations on numbers
This is probably the strangest one-yes, you
can now use a wrapper type as an operand
in operations where the primitive type is
expected. That means you can apply , say,
the increment operator against a reference
to an Integer object!
But don't worry-this is just a compiler trick.
The language wasn't modified to make the
operators work on objects; the compiler i++i
simply converts the object to its primitive
type before the operation. It sure looks
weird, though.
Integer i =new Integer(42);
i++;
And tnat means you can also do things like:
Integer j :; new Integer(5);
Integer k :; j .. 3;

Assignments
You can assign either a wrapper or primitive
to a variable declared as a matching wrapper
or primitive. for example, a primitive int
variable can be assigned to an Integer
reference variable, and vice-versa-o
reference to an Integer object can be
assigned to a variable declared as an jnt
primitive.

~ your pencil public class TastBox

Integer i;
Will this code compile? Will Itrun? IfII runs, int j;
what will ~do7
public static void main (String[] ll%gs) (
Take your time and think about this one; it T.stBox t ; new T.stBox() i
brings up an implication ofautoboxing that t.qo() ;
we didn't talk about. }

You'll have to go to your compiler to find public void go 0


the answers. (Yes. we're forclng you to j-ii
experiment, for your own good of course.) Systam.out.println(j);
Systam.out .println(i);

you are here) 291


wrapper methods

Jut waltl There1s ",ore! Wrappers


have static utility tMethods too!
Besides acting like a normal class. the wrappers have a
bunch of reaJly useful static methods. We','e used one in
this book before--lnteger.parselntO.
The parse methods take a String and give you back a
primitive value .

Converting a String to a
primitive value is easy:
String s "" "2";
int x = Inteqer.parseInt(s);
double d = Double.parSeDouble("420.24 H ) ;

You'll get a runtime exception:

Every method or
% java Wrappers
constructor that parses
Exception in thread "main N
a String can throw a
java .lang.NumberFormatException: two NumberFormatExceptlon.
at java.lang.lnteger.parselnt(Integer .java:409) It's a runtime exception,
at java .lang .lnteger.parselnt(Integer .java:458) so you don't have to
at Wrappers.main(Wrappers.java:9) handle or declare It.
But you might want to.
(We'U talk about Exceptions in the
next chapter.)
292 chapter 10
numbers and statics

Attd .,ow i" reverse... fuYttittg a


prhMitive ttutMber ittto a Strittg
There are several ways to tum a number into a String.
The easiest is to simply concatenate the number to an
existing String. Lh '+' o~cra~ is o...~y\oa~,d
R,,,,t"'\'cr \. t. loadt.d oycratoo- as a
double d '" 42.5; ~ i" Java (tht. _I'f t;-
Stt·..o. c.oWlu\:.t.Ni"LO
A",,.l.\.iWl~ .loot.d 1:.0 a
r.1 v'
String doubleString = .... " + d; ~"J L -CO es Shi,,~i-r't.d.
Sttl"!l Dt: 0'"
double d = 42.5;
String doubleStrinq '" Dcuble .toStrinq(d) ;

\ A~t.I". way to it
"'ethod dan Do..bk
Ih
do l.ISiJ\9 a st.;-bt

you are here ~ 293


number formatting

Nutttber fortttatti.,g
InJava, formatting numbers and dates doesn't have to be coupled with I/O. Think
about it. One of the most typical ways to display numbers to a user is through a
GUI. You put Strings into a scrolling text area, or maybe a table. If formatting was
built only into print statements, you'd never be able to format a number into a nice
String to display in a GUI. Before Java 5.0, most formatting was handled through
classes in the java. text package that we won't even look at in this version of the
book, now that things have changed.
In Java 5.0, theJava team added more powerful and flexible formatting through a
Formatter class injava.util. But you don't need to create and call methods on the
Formatter class yourself, because Java 5.0 added convenience methods to some of
the I/O classes (including printf'(j ) and the String class. So it's a simple matter of
calling a static String.formatO method and passing it the thing you want formatted
along with formatting instructions.
Of course, you do have to know how to supply the formatting instructions, and
that takes a little effort unless you're familiar with the frrintf() function in C/CH.
Fortunately, even if you don't know printf() you can simply follow recipes for the
most basic things (that we're showing in this chapter) . But you will want to learn
how to format if you want to mix and match to get anything you want.
We'll start here with a basic example, then look at how it works. (Note: we'll revisit
formatting again in the I/O chapter.)

Formatting a number to use commas

public class TestFormats (

public static void ma in (String[ ) args) {

String s = String. format ("lis, d",


System.out.println( s) ; ~

1,000,000,000

294 chapter 10
numbers and statics

FortMaffit1g decot1sfrucfed...
At the most basic level, formatting consists of two main parts
(th ere is more, but we'll start with this to keep it cleaner):

__ Formatting Instructions
You use special format specifiers that describe how
the argument should be formatted.

e The argument to be formatted.


Although there can be more than one argument, we'll
start with just one. The argument type can't be just
anything... it has tobe something that can be formatted
using the format specifiers inthe formatting instructions.
For example, if your formatting instructions specify a
floating point number, you can't pass ina Dog oreven a
String that looks like afloating point number.

Do this... to this.


format ("%, d", 1000000000); •
~ ~

i
Use these instructions... on this argument.
\
What do these Instructions actually say?
"Take the second argument to this method, and
format it as a decimal integer and insert commas."

How do they say that?


On the next page we'll look in more detail at what the syntax "%,
d" actually means, but for starters, any time you see the percent
sign (%) in a format String (which is always the first argument
to a formatf ) method), think of it as representing a variable,
and the variable is the other argument to the method. The rest
of the characters after the percent sign describe the formatting
instructions for the argument.

yo u are here. 295


the formatO method

The percettt (~) says, "ittsert argutltet1t here"


(a"d format It uslt1g these it1structiottS)
The first argument to a formatj ) method is called the format Suing, and it
can actually include characters that you just want printed as-is, without extra
formatting. When you see the % sign, though, think of the percent sign as a
variable that represents the other argument to the method.

I have 476578.10 bugs to fix.

The "%" sign tells the formatter to insert the other method argument (the
second argument to formatf), the number) here, At"lD format it using the
u .2r characters after the percent sign. Then the rest of Ute format Suing,

"bugs to fix" , is added to the final output .

Adding a comma

u
format("! have %,.2£ bugs to fix. , 476578.09876);

I have 476,578.10 bugs to f~.

296 chapter 10
numbers and statics

But how does it even KNOW


where the instructions end and the
rest of the characters begin? How come
it doesn't print out the "f" in "%.2f'? Or
the "2"( How does it know that the .2f
was part of the instructions and NOT
part of the StriT\9?

The format Stri"Q uses its


ow., little lattguage sytttax
You obviously can't put just an),thingafter the "%~
sign. The syntax for what goes after the percent
sign follows very specific rules, and describes
how to format me argument that gets inserted at
that point in the result (formatted) String.
You've already seen two examples:
%, dmeans "insert commas and format the
number as a decimal integer,"
and
%.2£ means "format the number as a floating
point with a precision of two decimal places."
and
%,.2£ means "insert commas and format the
number as a floating point with a precision of
two decimal places."
The real question is really, "How do I know what
to put after the percent sign to get it to do what
I want?" And that includes knowing the symbols
(like "d" for decimal and "f" for floating point)
as well as the order in which the instructions
must be placed following the percent sign. For
example, if you put the comma after the "d" like
this: k%d,~ instead of "'%,d" it won 't workl
Or will iv What do you think this will do:

String .for1llat("I have %.2£, bugs to fix.", 476578.09876);

(We'll answer that on the next page.)

you a re he re ~ 297
format specifier

The fortMat specifier


Everything after the percent sign up to and including the type indicator (like
"d" or "f') are part of the formatting instructions. After the type indicator, the
formatter assumes the next set of characters are meant to be pan of the output
String, until or unless it hits another percent (%) sign. Hmmmm ... is that even
possible? Can you have more than one formatted argument variable? Put that
thought on hold for right now; we'll come back to it in a few minutes. For now,
let's look at the syntax for the format specifiers-the things that go after the
percent (%) sign and describe how the argument should be formatted.

A format specifier can have up to five different parts (not


Including the MOJo"). Everything In brackets [] below Is optional, so
only the percent (0J0) and the type are required. But the order Is
also mandatory, so any parts you DO use must go In this order.

%[argument number] [flags] [width) [.precision)type

%[argument number] [flags] [width) [.precision) type

------~Jl format("%,6.1f N , 42.000);

298 chapter 10
numbers and statics

The ot1ly required specifier is for TVPE


Although type is the only required specifier, remember that if you do put
in anything else, type must always come last! There are more than a dozen
different type modifiers (not including dates and times; they have their own
set), but most of the time you 'll p robably use %d (decimal) or %f (floating
point) . And typically you 'll combine %fwith a precision indicator to set the
number of decimal places you want in your output.

The TYPE is mandatory, everything else is optional. You must include a


type in your tormat
%d decimal
format ("%d", 42) ;
~ wo",ld
A4-2.25 wcxo/d ot I
be th tI work, It instructions, and it you
d' e sallie as trt'tI to
. ,rettly assi3t1 a do",bl 3 specity things besides
Itlt variable. e atl

The argument must be compatible with an int, so that means type, the type must
only byte, short, int, and char (or their wrapper types) .
always COme last.
%f floating point
»e\"e we tOftlbil'le~ ~he
"kit Most ot the time,
format ("%.3£", 42. 000000) ; with a f\"etis',o\'\ 'l'Id,t~tov-
".,11
.7 so
we el'lded ",y WIth you'll probably tormat
42 .000 th\"ee u\"oes·
numbers using either
The argument must be of a floating point type, so that
means only a float or double (primitive or wrapper) as well
"d" ror
r J' ecrmal or "l't»
as somethin g called BigDecimal (which we don't look at in
thi s book) .
tor lloating point.

%x hexadecimal
format ("%x", 4 2);

The argument must be a byte , short, int, long (including


both primitive and wrapper type s), and BigInteger.

%c character
format ("%c", 42);

The argument must be a byte, short, char, or int (including


both primitive and wrapper types).

you are here . 299


format arguments

What happens if I have tltore than one argutltent?


Imagine you want a String that looks like this:
"The rank is 20,456,654 out of 100,567,890.24."
But the numbers are coming from variables. What do you do? You simply add two
arguments after the format String (first argument), so that means your call to formatt)
will have three arguments instead of two. And inside that first argument (the format
String), you'll have two different format specifiers (two things that start with "%"). The
first format specifier will insert the second argument to the method, and the second
format specifier will insert the third argument to the method. In other words, the
variable insertions in the format String use the order in which the other arguments are
passed into the formatf) method.

i n t one = 2 0 4 5 6 6 5 4 ;
do ub l e two = 100 567890.248907 ;
St r i n g s = String. f o r mat ("The r a nk i s %,d o u t of %,.2£", one, twO );

~
The rank is 20,456,654 out of 100 ,567,890 .25

We added tOl'l\l'I\OS to both vat'iables,


and t'estt'itted the .fIO<ltin~ point
n~l'I\bet' (the setond variable) to two
detil'l\al plates.

As you'll see when we get to date formatting, you might actually want to apply different
formatting specifiers to the same argument. That's probably hard to imagine until you
see how date formatting (as opposed to the numberformatingwe've been doing) works.
Just know that in a minute, you'll see how to be more specific about which format
specifiers are applied to which arguments.

Q: Um,there's something REALLY strange going on here. Just how many arguments can I
pass? I mean, how many overloaded format() methods are INthe String class? So,what happens
if Iwant to pass, say, ten different arguments to be formatted for a single output String?

A: Good catch. Yes, there is something strange (or at least new and different) going on, and
no there are not a bunch of overloaded formatO methods to take a different number of possible
arguments. In order to support this new formatting (printf-like) API in Java,the language needed
another new feature-variable argument lists (called varargs for short) .We'll talk about varargs
only in the appendix because outside of formatting, you probably won't use them much in a well-
designed system.

300 chapter 10
numbers and statics

So tMuch for t1utMbers, what about dates?


Imagine you want a String that looks like this: "Su n d ay, Nov 28 2004"
Nothing special there, you say? Well, imagine that all you have to start with is a variable
of type Date-AJava class that can represent a timestamp, and now you want to take that
object (as opposed to a number) and send it through the formatter.
The main difference between number and date formatting is that date formats use a
two-character type that starts with "t" (as opposed to the single character "f" or "d ", for
example). The examples below should give you a good idea of how it works:

The complete date and time %tc


String. format ("%tc", new Date());
Sun Nov 28 14 :52:41 MST 2004

Just the time %tr


String. format ("%tr", new Date () ) ;
03:01 :47 PM

Day of the week, month and day %tA %tB %td

There isn't a single format specifier that will do exactly what we


want, so we have to combine three of them for day of the week
(%tA), month (%tB), and day ofthe month (%td).

Sunday, November 28

Same as above, but without duplicating the arguments %tA %tB %td
Date today = new Date () ; The a\'l~le-bl"atkd: "<" is jlASt a\'lothel"
String. format (" %tA, %< t B %< t d " , today); ~Ia~ ill iht speti+iel" that tells the
+ol"",aH el" to "lASe the ..fl"eviOlAS al"~~"'el'lt
a~a il'l." So it saves '1~ hOM l"efeatil'l~ the
al"~lA",e\'lts, al'ld i\'lSuad 'i0~ +Ol"",at the
SaMe al"~~el'lt thl"ee diHel"el'lt ways.

you are here. 301


manipulating dates

Let's see... how many work


days will there be if the
project starts on Feb 27th and
ends on August 5th?

Workhtg with Pates


You need to do more with dates than just get
UN:ldy s date. You need your programs to adjust
dates, find elapsed times, prioritize schedules,
heck, make schedules. You need industrial
strength date manipulation capabilities .
You could make your own date routines of
course... (and don't forget about leap years l)
And, ouch, those occasional, pesky leap-
seconds. Wow, this could get complicated. The
good news is that the Java API is rich with
classes that can help you manipulate dates.
Sometimes it feels a little too rich ...

302 chapter 10
numbers and statics

Movit1Q backward at1d forward it1 tittte


Let's say your company's work schedule is Monday through Friday.
You've been assigned the task of figuring out the last work day in
each calendar month this year...
v
.ror a·
time-stamp o:trtt"
now,
It seems that java.util.Date Is actually••• out of date
Earlier we used java.util.Date to find today's date, so it seems
use Date. But lor everything
logical that this class would be a good place to start looking for else, use Calendar.
some handy date manipulation capabilities, but when you check
out the API you'll find that most of Date's methods have been
deprecated!
The Date class is still great for getting a "time stamp"-an object
that represents the current date and time, so use it when you want
to say, "give me NOW".
The good news is that the API recommends java.util.Calendar
instead, so let's take a look:

Use Java.util.Calendar for your date manipulation

The designers of the Calendar API wanted to think globally,


literally. The basic idea is that when you want to work with dates,
you ask for a Calendar (through a static method of the Calendar
class that you'll see on the next page), and the JVM hands you back
an instance of a concrete subclass of Calendar. (Calendar is actually
an abstract class, so you're always working with a concrete subclass.)
More interesting, though, is that the kind of calendar you get
back will be appropriate for your locale. Much of the world uses the
Gregorian calendar, but if you're in an area that doesn't use a
Gregorian calendar you can getJava libraries to handle other
calendars such as Buddhist, or Islamic orJapanese.
The standard Java API ships withjava.util.GregorianCalendar, so
that's what we'll be using here. For the most part, though, you
don't even have to think about the kind of Calendar subclass you're
using, and instead focus only on the methods of the Calendar class.

you are here . 303


getting a Calendar

&ettit1g at' object that extends Calendar


How in the world do you get an "instance" of an abstract class?
Well you don't of course, this won't work:

This WON'T work: v--- nt tompile¥ .....0I'I't allow this I


Calendar cal = new Calendar () ; .

Instead, use the static "getlnstanceO" method:


Calendar cal = Calendar .getlnstance() ;

Wait a minute.
If you can't make an
instance of the Calendar
class, what exactly are you
assigning to that Calendar
reference?

You can't get an instance of Calendar,


but you can can get an instance of a
concrete Calendar subclass.

Obviously you can't get an instance of Calendar, because


Calendar is abstract, But you're still free to call static methods
on Calendar, since SUllie methods are called on the class;
rather than on a particular instance. So you call the static
getInstanceO on Calendar and it gives you back... an instance
of a concrete subclass. Something that extends Calendar
(which means it can be polymorphically assigned to Calendar)
and which-by contract-s-can respond to the methods of class
Calendar.
In most of the world, and by default for most versions ofJava,
you'll be getting back ajava.util.GregorianCalendar instance.

304 ch a ple r 10
numbers and statics

Workittg with Calettdar objects


There are several key concepts you 'U need to understand in
order to work with Calendar objects:

• Fields hold state- A Calendar object bas many fields that are used to
represent aspects of its ultimate state, its date and time. For instance, you
can get and set a Calendar's yearor month.
• Dates and Times can be incremented - The Calendar class has methods that
allow you to add and subtract values from various fields, for example "add
one to the month". or "subtract three years" .
• Dates and TImes can be represented in milhseconds- The Calendar class
lets you convert your dates in to and out ofa millisecond representation .
(Specifically, the number of milliseconds that have occured since January
l st, 1970.) Th is allows you to perform precise calculations such as "elapsed
time between twO times" or "add 63 hours and 23 minutes and 12 seconds
to this time",

An example of working with a Calendar object: 1 ~o&r at \",~D.


. t.o Ja'" J o-ba$td.1
Calenda r c = Ca lendar . get I ns tance () i ~ b"'\L ,..(l¥\\)1 i.s z.l'"
,--_._~ n.JdUl.t.~nt.

c.set(2004,O, 7,15,40); ~ . L .LL' t.o a hie>J 01'


ConV~ "{.I\\s
long dayl = c. getTimelnMillis (); ~ oJ 3W\OIo'l'It. ot ",i\Iis«.ow-dS.
dayl +~ 1000 * 60 * 60;
c .setTimelnMillis(dayl); (
System.out.println("new hour " + c.qet(c.HOUR_OF_DAY») ;

c.add(c .DATE, 35) ;


~-------shOl.lld
Add 3'5 da'f1 to the dau, whith
""ove jPlto FebYu.ilry. lAS
System.out.println("add 35 days" + c.getTime());
c.roll(c.DATE, 35); <:~---~--
System.out.println("roll 35 days" + c.getTime(»)i
c.set(c.DATE, 1);

System.out.println("set to 1 " + c.qetTime(»);

This outp",t, ton~i_s how ...illis.


add, yoll, dPld set w~k

you are here ~ 305


Calendar API

Highlights of the Calettdar API


WeJUSt worked through using a few of the fields and
methods in the Calendar class. This is a big API so
we're showing only a few of the most common fields
and methods that you'll use. Once you get a few of
these it should be pretty easy to bend the rest of the
this API to your will.

Key Calendar Methods

add(lnt field. Int amount}


Adds or subtracts time from the calendar's field.

get(lnt field)
Returns the value of the given calendar field.

getTlmelnMllIIs()
Returns this Calendar's time In millis,as a long.
Key Calendar Fields -,
roll(int field, boolean up)
Adds or subtracts time without changing larger fields.
DATE I DAY_OF_MONTH
Get / set the day of
-
month
set(int field.lnt value} HOUR/HOUR_OF DAY
Sets the value of a given Calendar field. Get! Set the 12 h-
Our Or 24 hour value
set(year. month. day, hour. minute) (allints) MILLISECOND .
A common variety of set to set a complete time. Get / Set the milliseconds,
setTlmelnMfllis(long millis) MINUTE
Sets a Calendar's time based on a long rnllli-tirne. Get / set the mInute.
II more ... MONTH
Get / set the month.
- - -...._ ..._ - _. ._ - - . . , YEAR
Get / Set the year.
ZONE_OFFSET
Get / set raw offset of GMT I
1/ more... n mUUs.

06 chapter 10
numbers and statics

Evett ttlore Statics!... static jttlJ!orts


New to Java 5.0 ... a real mixed blessing. Some people love
this idea, some people hate it, Static imports exist only to save
you some typing. [f you hate to type, you rnightjust like this
feature. The downside to static imports is that - if you're not
careful- using them can make your code a lot harder to read.
The basic idea is that whenever you're using a static class, a
static variable, or an enum (more on those later) , you can
import them, and save yourself some typing. Use CareluUy:
static imports can
Some old-fashioned code: make your code
import java.lang.Math; contusing to read
class NoStatic {
publiC static void main (String () argsl (

Math.tan(60});

Same code, with static Imports:


;import static java.lanq.System.Outi - Caw.aII & Gokhas
;import static java.lanq.Math.*i • If you're only going to use a static member
a few times, we think you should avoid
class WithStatic ( static Imports, to help keep the code more
public static void main (String [] args) readable.
• Ifyou're going to use a static member a lot,
(like doing lots ofMath calculanons), then
it's probably OK to use the static Import.
• Notice that you can use wildcards (."), in
your static Import declaration.
• Abig issue with static imports is that it's
not too hard tocreate naming conflicts. For
example, if you have two different classes
with an "addO' method, how will you and
the compiler know which one to use?

you are here. 307


static vs. instance

Fireside Chats Tonight's Talk: An instance variable

@ takes cheap sIlots at a static variable

In.stanoe Variable S1atic Variable


I don't even know why we're doing this.
Everyone knows static variables are just used
for constants. And how many of those are
there? I think the whole API must have, what,
four? And it's not like anybody ever uses
them.

You really should check your facts . When


was the last time you looked at the API? It's
frickiri ' loaded with statics! It even has entire
classes dedicated to holding constant values.
There's a class called SwingConstarus, for
example, that's just fuU of them .
Full of it. Yeah, you can say that again. OK,
so there are a few in the Swing library, but
everybody knows Swing is just a special case. It might be a special case, but it's a really
important onel And what about the Color
class? What a pain if you had to remember the
RGB values to make the standard colors? But
the color class already has constants defined
for blue, purple, white, red, etc. Very handy.

Ok, but besides a few GUI things, give me an


example ofjust one static variable that anyone
would actually use. In the real world. How's System.out for starters? The out in
System.out is a static variable of the System
class. You personally don't make a new
instance of the System, you just ask the System
class for its out variable.
Well, that's another special case . And nobody
uses that except for debugging anyway.
Oh.Iike debugging isn't important?
And here's something that probably never
crossed your narrow mind-let's face it, static
variables are more efficient. One per class
instead of one per instance. The memory
savings might be huge !

308 chapter 10
numbers and statics

Instance Variable Static Variable


Urn, aren't you forgetting something?
What?
Static variables are about as un-OO as it gets!!
Gee why notjust go take a giant backwards
step and do some procedural programming
while we're at it.
What do you mean un-OO?

You're like a global variable, and any


programmer worth his PDA knows that's
usually a Bad Thing.
I am NOT a global variable. There's no such
thing. I live in a class! That's pretty 00 you
know, a CLASS. I'm not just sitting out there
in space somewhere; I'm a natural part of the
state of an object; the only difference is that
I'm shared by all instances of a class. Very
efficient.
Yeah you live in a class, but they don't call
it Clas.rOriented programming. That's just
stupid. You're a relic. Something to help the
old-timers make the leap to java. Alrightjust stop right there. THAT is
definitely not true. Some static variables are
absolutely crucial to a system . And even the
ones that aren 't crucial sure are handy.

Well, OK, every once in a while sure, it makes


sense to use a static, but let me tell you , abuse
of static variables (and methods) isthe~iDark
of an immature 00 programmer. A designer
should be thinking about objectstate, not class
state. Wh y do you say that? And what's wrong with
static methods?

Static methods are the worst things of all,


because it usually means the programmer is
thinking procedurally instead of about objects
doing things based on their unique object
Sure, I know that objects should be the focus
state.
of an 00 design, but just because there are
some clueless programmers out there... don 't
throw the baby out with the bytecode. There's
a time and place for statics, and when you
need one, nothing else beats it.
Riiiiiight. Whatever you need to tell yourself. ..
you are he re . 309
be the compiler

BE the comriIer
The Java file on this page represents a
complete progrlU'l. Your joh is to rIa)'
cOIlIpiler and deterrnne whether this
file will cOIllpile. If it won't cOIlIpile.
how would )'OU 1'lX it. and
class StaticSuper{
if it does compile. whllt
would he ~ output?
static {
System.out.println("super static block");
}

StaticSuper{ If it complies, which of these Is


System.out.println( the output?

"super constructor");
} Possible Output
} Rle Edit Wlndow Hel ell
%java StaticTests
static block 4
public class StaticTests extends StaticSuper {
in main
static int randj
super static block
super constructor
static {
constructor
rand = (int) (Math.random() * 6)j

system.out.println("static block n + rand);


}

StaticTests () { Possible Output


System.out.println("constructor"); File Edit Wlndow Het Electrle:l
} %java StaticTests
super static block
public static vcid main{String [] args) { static block 3
in main
System.cut.println("in main");
super constructor
StaticTests st = new StaticTests()j
constructor
}

310 chapter 10
numbers and statics

This chapter explored the wonderful, static, world


of Java. Your Job is to decide whether each of the
following statements Is true or false.

1. To use the Math class, the first step is to make an instance of it.

2. You can mark a constructor with the static keyword.

3. Static methods don't have access to instance variable state of the 'this' object.

4. It is good practice to call a static method using a reference variable.

5. Static variables could be used to count the instances of a class.

6. Constructors are called before static variables are initialized.

7. MA)CSIZE would be a good name for a static final variable .

8. A static initializer block runs before a class's constructor runs.

9. If a class is marked final, all of its methods must be marked final.

10. A final method can only be overridden if its class is extended.

11. There is no wrapper class for boolean primitives.

12. A wrapper is used when you want to treat a primitive like an object.

13. The parseXxx methods always return a String.

14. Formatting classes (which are decoupled from 1/0), are in the java.format
package.

you are here ~ 311


code magnets

Lunar Code Magnets


This one might actually be usefullin addition to what you've learned in the last few
pages about manipulating dates, you'll need a little more information...First full
moons happen every 29.52 days or so.Second, there was a full moon on Jan. 7th,
2004 . Your job is to reconstruct the code snippets to make a working Java program
that produces the output listed below (plus more full moon dates). (You might not
need all of the magnets, and add all the curly braces you need.) Oh, by the way, your
output will be different if you don't live in the mountain time zone.

I long dayl = c.getTimelnMillis() ; I


I c . s e t (2 0 04 , l , 7 , 1 5 , 4 0 ) ; I
java. lang. system. out;
rimPort static

~ 1
\
static int DAY IM :: 60

("full moon on llitc", c»;



Or 60 .. 24;

-
LCalendar C - new
.~I
(c. format
J
Calendar();

r
" l a s s FullMoo n s (
l
I public static void main (Strinq [] arqs) {
I
I dayl += (DAY_1M .. 29.52); I
Ifor (int x :: 0 ; X < 60; x++) {a
L~

stati.e int DAY


IM =: 1000
Or 60 Or 60 .. 24;- ,

I
println
l J. . -
l ~port Java.i.o.*;
\
("full moon on %t", c) ) ; ~
1
limport java .util.*;
}
I static import java.lanq.System.out;
~
I
e.set{2004,O,7,15,40);
r out.println

c .setT1meInHi
lliS(daYl); (string . format

Calendar c = Calendar.get1nst&nce();

312 chapter 10
numbers and statics

True or False

1. To use the Math class, the first step is to False


make an instance of it.
2. You can mark a constructor with the key- False
word 'static'.
3. Static methods don't have access to an True
object's instance variables .
4. It is good practice to call a static method False
using a reference variable.
5. Static variables could be used to count the True
instances of a class.
6. Constructors are called before static vari- False
ables are initialized.
staticSuper( ) {
System.out.println( 7. MAX_SIZE would be a good name for a True
usuper constructor H ) ; static final variable.
} 8. A static initializer block runs before a class's True:
constructor runs.
StaticSuper is a constructor, and must 9. If a class is marked final. all of its methods False
nave ( ) in its signature. Notice thor as
the output below demonstrates, the static must be marked final.
blocks for both classes run before either ]O. A final method can only be overridden if False
of the constructors run.
its class is extended.
11. There is no wrapper class for boolean False
Possible Output primitives.
File Ed~ WIndOW Hel elln 12. A wrapper is used when you want to treat a True
%java StaticTests
primitive like an object
super static block
static block 3 13. The parseXxx methods always return a False
in main String.
super constructor 14. Formatting classes (which are decoupled False
constructor
from I/O), are in the java.format package.

you are here . 313


code magnets solution

Notes on the Lunar Code Magnet:


import java.util.·;
You might discover that a few of the
import static java.lanq.Syatem.out; dates produced by this prognun are
olass FullMoons ( off by a day. This astronomical stuff
is a little tricky, and if we made it
statio int DAY rM : 1000 • 60 • 60 • 24; perfect, it would be too complex to
publi~ static void main (String [) args) make an exercise here.

Ca18nda~ c = Calendar.getlnstance(); Hint: one problem you might try to


solve is based on differences in time
c.aet(2004,O,7,15,40);
zones. Can you spot the issue?
long day! = c.qetTimelnM1l1i9();

for (int x ~ 0; x < 60; x++)


day! +: (DAY_1M • 29.52)

c. setTimslnMillis (dayl) ;

out.println(Strlnq.format("full moon on %tc", e»;

314 chapter 10
11 exception handling

Risky Behavior

Stuff happens. The file isn't there. The server Is down. No matter how
good a programmer you are,you can't control everything.Things can go wronq, Very wrong.

When you write a risky method, you need code to handle the bad things that might happen.
But how do you know when a method Is risky? And where do you put the code to handle the

exceptional situation? So far in this book. we haven't really taken any risks. We've certainly had
things go wrong at runtime, but the problems were mostly flaws In our own code. Bugs. And

those we should fix at development time. No, the problem·handllng code we're talking about

here is for code that you can't guaranatee will work at runtime. Code that expects the file to be

in the right directory, the server to be running, or the Thread to stay asleep. And we have to do
this now. Because in this chapter, we're going to build something that uses the risky JavaSound

API. We're going to build a MIDI Music Player.

this is a new chapter 315


building the MIOI Music Player

Let"s tMake a Music Machitte


Over the next three chapters, we'll build a few different sound
applications. including a BeatBox Drum Machine. In fact,
before the book is done, we'll have a multi-player version so
you can send your drum loops to another player, kind of like
a chat room . You're going to write the whole thing, although
you can choose to use Ready-bake code for the CUI parts.
OK. so not every IT department is looking for a new BeatBox
server, but we're doing this to learn more about Java. Building
a BeatBox isjust a way to have fun while we're learning java.
the fh11shed JeatJox looks sotMethl"g like this:

Crash Cymbal
Hand Clap )
High Tom
dance beat
Hi Bongo
Maracas
Whistle
Low Conga
Cowbell Andy: groove 112
Vibraslap Chris: groove2 revised
Low-mid To m 0 G
Nigel: dance beat
High Agogo
Open HI CongaO LJ ILJ .= 1..::, ~I LJ

Put checkmarks in the boxes for each of the 16 'beats', For example, on beat
1 (of 16) the Bass drum and the Maracas will play. on beat 2 nothing, and
on beat 3 the Maracas and Closed Hi-Hat... you get the idea . When you hit
'Start', it plays your pattern in a loop until you hit 'Stop'. At any time, you
can "capture" one of your own patterns by sending it to the BeatBox server
(which means any other players can listen to it). You can also load any of the
incoming patterns by clicking on the message that goes with it.

316 c hapter 11
exception handling

WeIll start with the basics


Obviously we've got a few things to learn before the whole
program is finish ed , including how to build a Swing GUl, how
to connect to another machine via networking, and a little I/O
so we can sendsomething to the other machine.
Oh yeah , and theJavaSound API. That's where we'll start in this
chapter. For now, you can forget the GUl, forget the networking
and the I/O, and focus only on getting some MIDI-generated
MIDI ~ih:
sound to come out of your computer. And don't worry if you
don't know a thing about MIDI, Or a thing about reading or
making music. Everything you need to learn is covered here.
You can almost smell the record deal.

fhe JavaSou)1d API


javaSound is a collection of classes and interfaces added to
java starting with version 1.3. These aren't special add-oris:
they're part of the standard J2SE class library.javaSound is split
into two parts: MIDI and Sampled. We use only MIDI in this
book. MIDI stands for Musical Instrument Digital Interface,
and is a standard protocol for gerting different kinds of
electronic sound equipment to communicate. But for
our BeaiBox app, you can think of MIDI as a kind oj
sheet music that you feed into some device you can think
of like a high-tech 'player piano'. In other words, MIDI
data doesn't actually include any sound, but it does
include the instructions that a MIDI-reacling instrument
can play back . Or for another analogy, you can think of MIDI dtllit.e b\Ows how to
a MIDI file like an HTML document, and the instrument \"caa' a MIDI .filt al'lQ flay batl<.
that renders the MIDI file (i.e. plays it) is like the Web the S04.lI\d. nt dtvite ...i~ht.
browser. be a syr.thtsiuY ~oaYa or
MIDI data says what to do (play middle C, and here 's how hard s.or..e ot.h~ kitld of i~\II>\ent..
to hit it, and here 's how long to hold it, etc.) but it doesn't say (,.(s.....lIy, a MIDI it'Sb--ellt.
anything at all about the actual sound you hear. MIDI doesn't tan playa LOT o.f diH~tnt
know how to make a Elute, piano, or Jimmy Hendrix guitar ~ (yi.1no, d..,.,..1, violil'l,
sound, For the actual sound, we need an instrument (a MIDI
eitJ, alia all at the sa",e +'i",e.
device) that can read and playa MIDI file. But the device is
usually more like an entire band or orchestra of instrurnen 15. And So a MIDI tilt is,,'+' like shed
that instrument might be a physical device, like the electronic "'Iolit ~ot" jldi Ot\e "'1ol' ltiall iPl
keyboard synthesizers the rock musicians play. or it could the baPld -- it. taft hold the
even be an instrument built entirely in software. living in your farh for ALL t.ht "'lolitiar\5
computer.
flayi,,~ a farbtlOlar SOl'>5'
For our BealBox, we use only the built-in , software-only
instrument that you get with Java. It's called a syntMsiu:r (some
folks refer to it as a softumre synth) because it creates sound.
Sound that you hear.
you are here. 317
but It looked so simple

First we t1eed a Sequet1cer


Before we can get any sound to play, we need a Sequencer object. The
sequencer is the object that takes all the MIDI data and sends it to the right
instruments. It's the thing that plays the music. A sequencer can do a lot of
different things, but in this book, we're using it strictly as a playback device. Like
a CD-player on your stereo, but with a few added features. The Sequencer class
is in thejavax.sound.midi package (part of the standard java library as of version
1.3). So let's start by making sure we can make (or get) a Sequencer object.

6 .d\ ~_e.\(-~~
import j avax. sound. midi . '* ; . aM:. t)-.~ i~ay...~ ...., Ii ~'\~tY ob)tt.t It:1 -tht
~ \llIY We.l'Iee ~ ok tne MIDI de~it.dll,sb- .....er..t
public class MusioTestl { ...d;n fd . It: -the -thi,,~ t.hat, ....el\•
....e ye l.LS",~. 1 r L, ' to
II tn, MIDI in-tO\""'auC7J\ I"
public void play 0 ( sc,\\OLnt.fS6 b ,..d
, 'Bllt. ....e dO'l'>'t Nlte 6 Y6
Sequencer sequencer = MidiSys tem. ga tSaquencer () ; a sonlj '
.....v-selves __ ....e
have to asK t'ke
"" " ,.... Ol'le "'"
System.out .println("We got a sequencer"); ~ Mid~yst.e'" to ~i~t. lAj, Ol'It·

II close play

public static void main(Strlng(] args)


MusicTestl mt = Daw MusicTestl(} ;
IDt. play () ;
II clOSE! main
II close class SOlMethingl wrong!
,This t.«Je won't t.tm.pile! The to",piler ~ys t.nt\""e's ah
IAhreporkd e~epi.iOh' thai "'lASt be t.al.l~ht. or detlared.

318 chapter 11
exception handling

What happet1s whet1 a tMethod you warttto call


(probably it' a class you didt1~t write) is risky?

" Let's say you want


to call a method In a
class that you didn't
--.
_n,
- . . . . 111

o
_ _ II ,
~- ,
_ I"
write.
~_ Q
•...,.u. l

your coc e class you


you didn't write

• That method does _


--,
t_ 1

_ f1,
void moo () (
something risky, if (serverDown)
something that might axplode()i
)
not work at runtime. class you
didn't write }

~ You need to know


that the method
you're calling is ~.- '
risky. ~=. I

crass you
didn't write
you

@ You then write code


that can handle the
failure if It does
happen. You need to be
prepared, just in case.
your co e
you

you ar e her e ~ 319


When things mIght go wrong

Methods iN Java ose except/om: to tell the ca/liM9 code,


·Sotttethlftg Bad HappeHed. I failed;'

Java's exception.handliog mechan~m",


a dean, well·lighted way to handle "exceptional
shuations' that pop up at runtime;;t lets}'OuPOl all your error.handling code in one
easy-to-readplace. It's based On you knowingthat the method you're calhng;, risky
(i.e. that the method mighl gene,",e an exception), SO thar you can write code '0 deal
w;th that pos,,;bmty. l£}'Oo k_ you might get an exception when you calla ParUcuJar
the exception.
method, you can be fmP- for-poss;bly even '''-from-the problem thaI caused

So, how
risky know if a method throws an eXception! You find a throw. clause;n the
do}'Oudeclaration.
method's

The getSequencer () lIIethOd takes a risk. It Can fail at runtlllle.


So It lIIust 'declare' the risk you take When you call it.

eee @ MldlSvslem (Java 2 PIa((orm SE vl.4.01


h ck Sll>p
t.~
Rdrt:Sh
It f
Hl>rrIC _ i_ A~Ic>RlI

~ API dots it" r-


getSe-quencer ....-
-~ M ~,"alta-()
Un thr-ow an tXQf'i;",,:
L~~~I pUb lic ~ t a t i c '~C'all(l
-- n s" r 9·ts~t h.ac.~
r o~ .9 ( Mldll1o
_l _ Av:ll 1 h l~ Ex£~Rt l Qn
MidiU..a\lai'ab'eE~o...
~ Oblains the default sequencer. A~od has fo dulal"f!
...~ the ~0fIS it ... iShi
/ Rtturns: cer thl"o....
g ~~:\':tOlJrq the defaultsequcn
Throws:
H! d HJo.) y a 1 I .J b• l"ExcC
• ns
I the seq
p rl on _ .f
.. I availabledue
<N'IucnCCTIS no
~ VOiceSlalys

5' ExcepUons
,,1 I

320 chapte r 11
exception handling

The cOlMpiler t1eeds to kttow


that YOU kttow you're caUit1g
a risky lMethod.
If you wrap the risky code in something called a
try/catch, the compiler will relax.
A try/catch block tells the compiler that you
knota an exceptional thing could happen in the
method you're calling, and that you're prepared
---
to handle it. That compiler doesn 't care Iwwyou
handle it; it cares only that you say you're taking
care of it,

import j AVax . sound. midi . * ;

public class MusicT~stl {


public void play ()

try {
,J, tM yisk'f iYl~
Sequencer sequencer = MidiSystElm . getsequenCGr () ; i:;- ! 'l..AJ' h'ot't .
System.out.prlntln( "Suceessfully got a sequencer");
IYI a v 1

} catch (MidiUnavailableException ex) {


Systelll. out. println ("Bummer") ;

II close play

public static void main{Strinq[] args)


MusicTestl mt = new MusicTestl():
mt.play{) :
II close main
II closit class

you are here. 321


exceptions are objects

A" exceptio" is a" object...


of type Exceptio"_
Which is fortunate, because it would be much harder
to remember if exceptions were of type Broccoli .

Remember from your polymorphism chapters that


an object of type Exception can be an instance of any
subclassof Exception.

Because an Exception is an object, what you catch is an


object. In the following code. the catch argument
is declared as type Exception, and the parameter
reference variable is ex,
Throwable
getMeasage{) try {
printStackTraceO . I . L \',\:.t. 4tl.\a't"il'l~
I I do risky th J..nq ·,t s J~ \:..
.LI."O ay~-tl'l
Part J t'he 'e.~.Ltyt.\ OYI ~a ",e'V'"

dass ~lleYaYl.n l T'IIl'/ all


T\I't"owa'ble
T } catch(Exception ex) {
t~~O l.\ass Exception
61'10 il'lheY'It two \I.e'( II try to recover
...dho~
} ~ This ~od I
E~tp£ tOllvr
, I Iqu
I'
if' Ii

.> <,
Otl Is tJ.ro'Nrl, "

IOElceeptlon Intarrupl&dExceptlon What you write in a catch block depends on the


exception that was thrown. For example, if a server
is down you might use the catch block to try another
server. If the file isn't there, you might ask the user
for help finding it.

322 chapter 11
exception handling

If it's your code that catches the exceptio",


the., whose code throws it?
-
You'll spend much more of yourJava coding time handling
exceptions than you'll spend cnatingand throwing them yourself.
For now, just know that when your code callsa risky method-a --.
._':..::~ I

_ ... J tn I
method that declares an exception-it's the risky method that _"" J.
throws the exception back to yfJU, the caller.
In reality, it might be you who wrote both classes. It really your code class with Q
risky method
doesn't matter who writes the code... what matters is knowing
which method throws the exception and which method catches it.
When somebody writes code that could throw an exception, they
must declare the exception.

\ tnt 'foI0'I'\0 C'o'1


&od MVS1 -\:,t\ ~ d~'f-l,eytIO"
• Risky, exception-throwing code: ~,~ "'~ A) -\:,hat 'I't t,hyo'OlS a a
~ ott~Y''''Y
public void takeRi.sk () BadExcepUon ( One methqd WIll
if (abandonAllHope) (
new BadException();
-
entch . .VhClt £lncnher
tnet llo J thr9'vv~. J\n
'\l~t:G~
-
)

objett i:;e/:h.-owE~~
w
it.
exce ptIon 'is aJVY'ly':i
thl"O\Vn back [o the
elll)e\".
The 111eth<)d thnt
• Your code that calls the risky method:
th\'ovv' ~ ha~ t<:> dechu-e
----=--
public void crossFingers()
(
that 'It nl'ir,-ht thrq\\!
anObject.takeRisk()j the exception.
) (BadException ex) {
System. out.println ("Aaarqh! ") ; If y04l l.i '.1 r
1I \. rU,over ih -tror" ..J,.,
ex . printStackTrace () ; . . / ~et. a sicltk b- . e ~er \.Ion, at LMsT
~ ~i II ~le ~'~ -the P""ini$tallcTrciteO .... tt.hod
a e-,ttepiior.s Illherit.

you are here ~ 323


checked and unchecked exceptions

The compiler checks for everything


except RuntimeExceptions.
E.'Il.ttf"t1Ol\S thai aye NOT s~t1asu:s of The compiler guarantees:
Runti",eEuepiic»l cll"e thet.ked .for by
If you throw an exception in your code you must declare it using
~c t.oto.pilcr. Th~'rc ~Iled "thetJccd the throws keyword in your method declaration.
t"J'-UpiiOflS Ii
Exception If you call a method that throws an exception (in other words,
a method that declares It throws an exception), you must
acknowledge that you're aware of the exception possibility.
One way to satisfy the compiler is to wrap the call in a try/catch.
(There's a second way we'Hlook at a little later in this chapter .)

InterruptedExceptlon

~: Walt just a mlnutel How come this Is the FIRST time Q.: I'll bite. WHY doesn't the complier care about those
we ve had to try/cate:h an EJcceptlon7 What about the runtime exceptions? Aren't they Just as likely to bring the
exceptions I've already gotten like NullPolnterEJcception whole show to a stop?
and the exceptJon for DlvldeByZero. I even got a
NumberFormatExceptlon from the Integer.parselntO
method. How come we didn't have to catch those? A: Most RuntimeExceptlons come from a problem in
your code logic, rather than a condition that fails at runtime

A.: The compiler cares about all subclassesof Exception,


unless they are a special type, RuntimeException. Any
in ways that you cannot predict or prevent. You cannot
guarantee the file is there .You cannot guarantee the server
is up. But you can make sure your code doesn't index off the
exception classthat extends RuntlmeExceptlon gets a end of an array (that's what the .length attribute is for) .
free pass.RuntimeExceptions can be thrown anywhere, You WANT RuntimeExceptions to happen at development
with or without throws declarations or try/catch blocks. and testing time.You don't want to code in a try/catch, for
The complier doesn't bother checking whether a method example, and have the overhead that goes with it, to catch
declares that It throws a RuntimeExceptlon, or whether the something that shouldn't happen In the first place.
caller acknowledges that they might get that exception at
runtime. A try/catch is for handling exceptional situations, not flaws
in your code, Use your catch blocks to try to recover from
situations you can't guarantee wlll succeed.Or at the very
least, print out a message to the user and a stack trace, so
somebody can figure out what happened.

324 chapter 11
exception hand Ii ng

• Amethod can throw an exception when something fails at runtime.


• An exception is always an object oftype Exception. (Which, as you
remember from the polymorphism chapters means the object is from a
class thai has Exception somewhere upitsinheritance tree.)
• The compiler does NOT pay attention toexceptions that are of
type RuntlmeException. A RuntimeExceplion does not have to be
declared orwrapped in a try/catch (although you're free todo either or
both of those things)

~etaco"Mitive tiP
• All Exceptions the compiler cares about are called 'checked
exceptions' which really means compiler-<:hecked exceptions. Only
RuntimeExceptions are excluded from compiler checking. All other \ m somethIng new,
exceptions must be acknowledqed in your code, according to the \f you're trying to ea try tolearn
make that\he /8s1 thln~O~nce yOU putthis
rules.
before goIng to sleep. 'can tearyourself
• A method throws an exception with the keyword throw, followed by book down .(assu~I~~~O~nyth\ng else more
a new exception object: away from It)don t b I< of a Cheerios'"
challenging t~an the atlC to process what
throw new NoCaffeineException(); d me
boX. Your braIn nBB Sad That could take
you've read and lea~ to'shova something
• Methods that might throw a checked exception must announce it with a feW hoUrs. If you f ur Java. some of the
a throws Exception declaration. new in right on to~ 0 .yo
Java might not'sllek.
• If your code calls a checked-exception-throwing method, it must . doesn't rule oullearning
reassure the complier that precautions have been taken. Of course, thIS rldn on your latesl
a physical sk1\1. Wo K~ICkBOXlng routine
• Ifyou're prepared 10 handle the exception, wrap the call In a tJy/catch, Ballroom
probably won'l affect your
and put your exception handling/recovery code in the catch block. Java leamlng.
ulls read Ihls
• Ifyou're not prepared tohandle Ihe exception, you can still make the For the b est res '
compiler happy byofficially 'ducking' the exception. We'll talk about book {orat least1001< al
the pictures) right before
ducking a little lalerin this chapter.
goin9 to sleep.

~ your penCil
Things you want to do What might go wrong

'v'connect to a remote server


Which of these do you think
might throw an exceptfon that _ access an array beyond its length
the com pller would care about? _ display a window on the screen
We're only looking for the
things that you can't control In retrieve data from a database
your code. We did the first one. _ see if a text file is where you think It is
(Because Itwas the easiest.) create a new file
read a character from the command-line _

you are here . 325


exceptions and flow control

Flow eontrol it1 try/catch blocks


When you call a risky method, one of two things can hap-
pen. The risky method either succeeds, and the try block
completes, or the risky method throws an exception back to
your calling method.

If the try succeeds


(doRiskyThlngO does not
throw an exception)
try {
(j Foo f x.doRiskyThing();
int b f . getNum () ;

catch (Exception ex) {


System.out.println("failed U ) ;

(~ lsystem. out. println ("We made it!"); 1

If the try fails


(because doRlskyThlngO
dOBS throw an exception)

try (
.------i~!flHIFoo
'<::I'
f
iot b

} catch (Exception ex) (


~ System. out. println ("failed") ;

~stem.out.println("We
-I
made it!");

326 chapte r 11
exception andling

Fh,ally: for the thlttQs you wattt


to do no fffatter what.
If you try to cook something, you start by turning on
the oven.
If the thing you try is a complete failure,
you haue to turn off the oven.

If the thing you try succeeds,


you haue to turn off the oven.
You have to turn off the oven no matter what!

A finally block is where you put


code that must run regardless
of an exception.

try (
turnOvenOn();
x , ba Ice () ;
catch (BakingException ex)
ex.printStackTrace()i
) finally (
turnOvenOf£();
)
If the try block fails (an exceptIDn), flow
Without finally, you have to put the
tumOvenOffO in both the try and the catch control immediately moves to the catch block.
because you have to turn off the oven JU> matter When the catch block completes, the finally
what . A finally block lets you put all your block runs. When the finally block completes,
important cleanup code in oneplace instead of the rest of the method conUnues on.
duplicating it like this:
If the tr-y block succeeds (no exception),
try {
flow control skips over the catch block and
turnOvenOn () ;
moves to the finally block. When lhe finally
x.bake o. block compleles, the rest of the method
turnOvenOff () ;
continues on.
} catch (BakingException ex) (
ex.printStackTrace(); If the try or catch block has a return
turnOvenOf f () ; statement, finally will still runl Flow
jumps lo the finally, then back to the relum.

you are here ~ 327


flow control exercise

~yourpendl
Look at the c:ode to the left. What do you think the

Flow ContPoI output of this program would bel What do you think
It would be If the third line of the program were
changed to: String test. "yes", 1
AssumeScaryExceptlon extends Exception.

public class TestExceptions {


Output when test =' "no"

public static void main(String () args) {

String test = "no N;


try {
Systern.out.println("start try");
doRisky(test);
System.out.println("end try");
} catch ( ScaryExceptioo se) {
Systern.out.println("sca:r:yexception");
} finally {
System. out. println( "finally") ;
}
System.out.println("end of main");
}
Output when test = "yes"

static void doRisky(String test) throws ScaryException {


System.out.println ("start risky");
if ("yes".equals(test)) {
throw new ScaryException();

System.out.println(Uend riskyN);
return;
}
}

ulew JO pua . ,(lIeuy . UOlldCl»)«l 've)~ . ~SIJ lJelS . Nl uelS :.5i1,.{. =~al U"4M
ulew lO pUiI - Alleuy - .tit pua - A~S!J pUCI - A~SIJ lJl?1S - ,VllJelS :.ou . = l5Cll UCl1.!M

328 chapter 11
exception handling

Pid we lIte.,tio., that atltethod ca.,


throw tMore tha., o.,e exception?
A method can throw multiple exceptions if it dam well needs to. But
a method's declaration must declare all the checked exceptions it can
throw (although if two or more exceptions have a common superc1ass, the
method can declare just the superclass.)

CatchlnQ lHultlple exceptlo"s


The compiler will make sure that you've handled all the checked excep-
tions thrown by the method you're calling. Stack the catch. blocks under
the try, one after the other. Sometimes th e order in which you stack the

~:~::~~~::~~.~~~~:\r:tto thata\Itdelate,
public void doLaundry() throws PantsException,
II code that could throw either exception

public class Foo {


publ ic void go ( )
Laundry laundry new Laundry () ; it doLa~dr'f() ~..o\WS a
try { Pa"b~uepiiCW\1 i.e lands ill the
Pa"b.~~O'r\ utth blotk.
laundry.doLaundry();
} catch (PantsException pex)
1/ {
~

II recovery code

) Catch(LingerieExcePti~) (
".,..0''''') t\lydOIS a
I I recovery code ~ J d~ 'T. 0'\. it. \a"as i" the
} L.i~'t~~. ~h blot.\t.·
U~ew'it~~tybOl'l

you are here ~ 329


polymorphic exceptions

Exceptiotts are polytMorphic


Exceptions are objects, remember. There 's nothing all that
special about one, except that it is a thing that can be thrown. All eU~QtIS ho'le
So like all good objects, Exceptions can be referred to exception f.~~ as a
polymorphically. A LingerieException object, for example, SlI" cY to lass-
could be assigned to a ClothingException reference. A
PantsException could be assigned to an Exception reference.
You get the idea. The benefit for exceptions is that a method
doesn't have to explicitly declare every possible exception it
might throw; it can declare a superclass of the exceptions.
Same thing with catch blocks-you don't have to write a catch IOExceptlon CloltilngExeeptlon

for each possible exception as long as the catch (or catches)


you have can handle any exception thrown.

@ You can DECLARE exceptions using


a supertype of the exceptions you
throw.

@ You can CATCH exceptions using a


supertype of the exception thrown.

try ( ~\, ""'I try (


1.<1" .../...•
·4-1-UT
l
.... ~
laundry. doLa und ry () ; . / C\atn laundry.doLaundry();
~ .~
'.' 0 ! I/~
If Ie \Jot\a.u <...·
\;I
r t. '
i-:-
:.l

catch(ClothingException cex) { catch (ShirtException sex)

II recovery code II recovery code

330 chapter 11
exception hand

Just because you CAN catch everything


with one big super polymorphic catch,
doesn't always mean you SHOULD.
You could write your exception-handling code so that
you specify only one catch block, using the supertype
Exception in the catch clause, so that you'll be able to
catch any excep tion that might be thrown.

try {

l a undry.doLaundry();

catch (Exception ex) { blotk will


w"~T? Tn,s tattn ,t
I I r e c ov ery code . .. ~ Rt.t.ol/t.'('( .{:'(0f'I -b so '(()II.
WOYl
L'h ~N'I ay,G all t.~t.t.f oY\S,
} ta-u- \.. t wt.\'It WV'o\'l~'
a~~atit.all'f k\'low wna

Write a different catch block for each


exception that you need to handle
uniquely.
For example, if your code deals with (or recovers
from) a TeeShirtException differently than it handles a
LingerieException, write a catch block for each. But if yo u
treat all other types of ClothingException in the same way,
then add a ClothingException catch to handle the rest.

try {

l aundry.doLau ndry();

.J.i "s 3Y10 :t.


S\iAt1Lt.t v O 0 o,~h'(eYl
} catch (TeeShirtException tex) { ~ Tee' .\:;IOYlS Ylet.
I,; ll.,t.'(iet1Le\, s....ov.\o. ~e
I I r e c ove r y from Tee ShirtEx c ept i o l 'YI;.I '-J t,oOel so ,!0II0"
~ fu '(et,o\lt.'( I tt..... 'o\ot"s.
~ o,~~t.'t't.Ylt. t,a
} catch(LingerieException lex) {

All oihet- CIo th'/tI~ EXlt,nJ. ·


Ut"t, talAaht h r I./QtlS
J et-t, .
I I recov e r y fr om al l others
}

yo u a re he re . 331
order of multiple catch blocks

Multiple catch blocks iMust be ordered ClothingException


froiM stttaliesf to biggest

catch(TeeShirtException tex)

catch (ShirtException sex)

The higher up the inheritance tree, the bigger the


catch 'basket', As you move down the inheritance
tree, toward more and more specialized Exception
classes, the catch 'basket' is smaller. Ir'sjust plain old
polymorphism.
A ShirtException catch is big enough to take
a TeeShirtException or a DressShirtException
(and any future subclass of anything that extends
ShirtException). A C1othingException is even bigger
catch(ClothingException cex) (i.e . there are more things that can be referenced
using a ClothingException type) . It can take an
exception of type ClothingException (duh), and
any ClothingException subclasses: PantsException,
UnifonnException, Lingerielixception, and
ShirtException. The mother of all catch arguments
is type Exception; it will catch any exception,
including runtime (unchecked) exceptions, so you
probably won't use it outside of testi ng.

332 chapter 11
\
exception handling

You cat1"t put bigger baskets


above stMalier baskets.
Well, you can but it won't compile. Catch
blocks are not like overloaded methods
where the best match is picked. With catch
blocks, theJVM simply starts at the first one
and works its way down until it finds a catch
that's broad enough (in other words, high
enough on the inheritance tree) to handle Size matters when
the exception. lfyour first catch block is you have multiple catch
catch (Exception ex). the compiler blocks. The one with the biggest
knows there's no point in adding any basket has to be on the bottom.
Otherwise, the ones with
others-they'll never be reached .
smaller baskets are useless.

try (
l a und r y. doLa und r y ( ) ;

catch(ClothingException cex) {
II recovery from ClothingException

catch (Linge.rieExc:eption lex) {


II recovery from LingerieException

Siblings can be in any order, because they


can't catch one another's e~tions.

You could put ShirtException above


catch(ShirtException sex) {
UngerieException and nobody would mind
II recovery from ShirtException Because even though ShlrtException is a bigger
(broader)type because It can eateh other classes
(its own subdasses),ShirtException can't catch a
UngerieExceptlon so there's no problem.

you are here ~ 333


polymorphic puzzle

Assume the try/catch block here Is legally coded.Yourtask is to draw


~n your pencil two different class diagrams that can accurately reflect the Exception
classes. In other words, what class Inheritance structures would make the
try/catch blocks in the sample code legal?

try {
x , doRisky () ;

catch(AlphaEx a) {
II recovery from AlphaEx
catch (BetaEx b) {

II recovery from BetaEx


ca toh (GammaEx c)

II recovery from GammaEx


cateh(DeltaEx d) {
II recovery from DeltaEx

Yourtask is to create two different legal try / catch structures (similar to


the one above left),to accurately represent the class diagram shown on
the left Assume ALL of these exceptions might be thrown by the method
BazEl with the try block.

T
FooElr

.> <,
8esEJ BIIlEJ

<.

334 cha pter 11


exception handling

Whe., you dO.,/t wa.,t to ha.,dle


a., exceptiott... !
!

iust dUCK it
If you don't want to handle an
exception, you can duck it by
declaring it.
When you call a risky method, the compiler
needs you to acknowledge it. Most of the time,
that means wrapping the risky call in a try/
catch. But you have another alternative, simply
d1Uk it and let the method that called you catch
the exception.
It's easy-all you have to do is declare that
you throw the exceptions. Even though.
technically, you aren't the one doing the
throwing. it doesn't matter. You're still the one
letting the exception whiz right on by.
But if you duck an exception, then you don't
have a try/catch, so what happens when the
risky method (dol.aundry/) ) does throw the
exception?
When a method throws an exception, that
method is popped off the stack immediately,
and the exception is thrown to the next
method down the stack-the caller. But if the
calleris a ducker, then mere's no catch for it so
the caller pops off me stack immediately, and
the exception is thrown to the next method
and so on ... where does it end? You'll see a
liul elate r.

public void foo() throws


II call risky method
laundry.doLaundry() ;
}
you are here. 335
handle or declare

Uuckhtg (by declaring) only


delays the inevitable

Sooner or later, somebody has to


deal with it. But what If MainO
ducks the exception?
public class Washe r (
Laundry laundry = new Laundry(J;

public void fool) throws ClothingException


laundry .doLaundry();

public static void main (String[ ] argsl throws ClothingException (


Washer a = new Washer( );
a .fooO;

o doLaundryO throws a
ClothingException
fooD ducks the
exception
mainO ducks the
exception
The JVM
shuts down

mainO calls focO doLaundryO pops off the fooD pops off the
stack immediately and stack immediately and
fooO calls doLaundryO
the exception is thrown the exception is thrown
doLaundryO is back to fooO . back to ... who? What'?
running and throws a There's nobody left
But fooD doesn't have a
ClothingException but the JVM, and it's
try/catch . so...
thinking. "Don't expect
ME to get you out of
this."

We're us)ng the tee-sh irt to represent a Cloth ing


Exception. We know, we know ... you would
have preferr ed the blue Jeans.

336 chapter 11
exception handling

Handle or Declare. It's the law.


So now we've seen both ways to satisfy the compiler
when you call a risky (exception-throwing) method.

• HANDLE
Wrap the risky call in a try/catch
This had betta- b b'
try { »<""> ha",dle all extepti e athl~ e",o~h tatth
laundry. doLaundry () ; ~ ...iaht ~ I'\. OI'IS, at doLa~",dt"yC)
J t"ow. vr e se th t '1
} catch (ClothingException cex) { still to...pl ' ~1L 1- I e OIftPI et" will
/ / recovery c ode of th•• ,.,L.
a,,,,
v. 'toa't yo~ toe t Lh
"'0 tau i",~ all
...."",er"IOI'IS.
}

• DECLARE (duck it)


Declare that YOUR method throws the same exceptions oil tnvoo-"s a
as the risky method you're calling. \ . tnt
.1 1 ",W'dvo'.l) ...e-\:.n Q
int lo'o\..A01~ b~t b'( dtt. avo''';,
void foo () throws ClothingException { C\otni,,~~1Ltyti;"~O ...ttnod ~c\:.s to
laundry. doLaundry () ; ~ ~tytio", tnt ..J.'OY\' No tVO'fIt.atJ,n.
d~\c. tnt t1Lt r'"

But now this means that whoever calls the fooO method
has to follow the Handle or Declare law. If fooD ducks
the exception (by declaring it), and mainO calls fooO, then
mainO has to deal with the exception.

pUblic class Washer {


Laundry laundry = new Laundry();

public void fo o() throws Cloth i ngExc ep t i on


laundry.doLaundry();

public static void main (String[] a r gs )


Washer a = new Washer();
a f o o Ij r
c ~

Beta~e the +000 ...tihod d~ks the


CI~hi",~ExteptiOl'l tht"OWl'l by doLa~",dt"vI')
...a,,,,() has to a ,. () T: I
Wt" P a·1"OO i", a tt"y/tatth
at" ...ai",O has to detlat"e that it, too, ,
ih...ows Cloihi",~ExtertjOl'l!
you are here. 337
fixing the Sequencer code

G-effittg back to our tMusic code...


Now that you've completely forgotten, we started this chapter
with a first look at some JavaSound code. We created a Se-
quencer object but it wouldn't compile because the method
Midi.getSequencerO declares a checked exception (MidiUnavail-
ableException). But we can fix that now by wrapping the call in a
try/catch.

public void play()


try {

Sequencer sequencer = MidiSystem.getSequencer();


System.out.println(~Successfullygot a sequencer");

}
II close play

Exception Rules
• You cannot have a catch or finally
without a try
void go () { t-/Oi~~~~~\ ? try {
Faa f = new Faa () ; wnt.V"i s -tnt -ty'1 ' x.doStuff();
f. foof () ; finally {
catch(FooException ex) { } II cleanup

• You cannot put code between the


try and the catch

try {
lode h t
NOT Lf..&:A
"': L!VOlA ....
".11'1 P"t
1;
• A try with only a finally (no catch)
must still declare the exception.
void got) throws FooException {

x , doStUff/()
; 1. e weell the try ~~ try {
) "Ule ldtth. Ii"" x.doStuff() ;
int y = 43; } finally { }
} catch(Exception ex) { }

338 chapter 11
exceptJon handl ing

Code Kitchen

(
.:

You don't have to do it


yourselt, but it's a lot
more fun if you do.
Tlte rest 01 tlUs chapter
is optionaL you can use
ReaJy- bake code tor all
the music apps.
But it you want to learn
more about JllvaSouncl,
turn the rage.

you are here ~ 339


JavaSound MIDI classes

Making actual sound


Remember near the beginning of the chapter, we looked at how MIDI data holds
the instructions for what should be played (and how it should be played) and we
also said that MIDI data doesn't actually create any sound that you hear. For sound
to come out of the speakers, the MIDI data has to be sent through some kind of
MIDI device that takes the MIDI instructions and renders them in sound, either
by triggering a hardware instrument or a 'virtual' instrument (software synthe-
sizer). In this book. we're using only software devices, so here's how it works in
JavaSound:

You need FOUR things:

eD The thing that


plays the music
• The music to be
playtd... o song. • The part of the
Sequence that
holds the actual
Information
The actual music
Information:
notes to play,
how long, etc.

Sequencer
plays
~ Sequence
has a
~ Track
holds e9
For this book, we only
need one Track,so Just
Imagine a a music CD
e9
with only one song. A
single Track. This Track
Is where all the song
The Sequence is the data {MIDI Information)
song, the musical piece I1ves.
The Sequencer Is the thing that the Sequencer will
that actually causes a song play. For this book, think
to be played. Think of It like of the Sequence as a
a music CD player. music CD, but the whole A MIDI event is a message
CD plays just one song. that the Sequencer can
understand. A MIDI event
might say (if It spoke
English), "At this moment
In time, play middle C,play
It this fast and this hard,
and hold It for this long."
A MIDI event might
also say something like,
"Change the current
instrument to Flute."

340 chapter 11
exception handling

And you need FIVE steps~

. . Get a Sequencer and open it


Sequencer player = MidiSyscem.gecSequencer();
player .openl);

. . Make a new Sequence


Sequence seq = new Sequenceltiming,4);

• Get a new Track from the Sequence


Track t = seq.createTrack();

• Fill the Track with MidiEvents and


give the Sequence to the Sequencer
t.add(myMidiEventl);
player.setSequencelseq);

player. start ( );

you are her e ~ 341


a sound application

Your very first sound player app


Type it in and run it. You'll hear the sound of someone playing a
single note on a piano! (OK, maybe not someone, but something.)

import javax.sound.midi.*;

public class MiniMiniMusicApp {

pUblic static void main(String[] args) {


MiniMiniMusi cApp mini = new MiniMiniMusicApp();
mini.play();
(
II clos e main

public void play()

try {

a.·.~ Sequencer player MidiSystem.getSequencer();

" pl ayer . op e n () ;

• Sequence seq = new

Tra ck track = seq.createTrack();

ShortMes sage a = new ShortMessage();


a.setMessage(144, 1, 44, 100);
Mid iEvent noteOn = new MidiEvent(a, 1);
track.add(noteOn); PlAt SOMe MidiEvetl'ts into the T-sek. This fart
is Mostly Ready-bake tode. The only thin~ YOlA'1l
have to tare abolAt al'"e the al'"~llMents to the
ShortMessage b = new ShortMessage()i
b. setMes sage (128, 1, 44, 100); setMessa~e() ""ethod, and the al'"~llMents to
MidiEvent noteOff = new MidiEvent(b, the MidiEvent t.onshlAtk. We'/Ilook at those
track.add(noteOff); al'"~llMents on the ne1l.t ra~e.

player. setSequence (seq); ~ qive the Se,\llent.e to the Se,\llent.er (like


player. start (); 4:-- flAHin~ the CD in the cD fla-yel'")
Sfdl'"i() the
catch (Exc eption ex) { SeC(llehter Oike PlASh'
e x. p r i nt St ackTr ace (); 'n~ PLAy)
} I I c l o s e play
I I clos e c lass

342 cha pt er 11
exception handling

Makit1g a MidiEvettt (SOttg data)


A MidiEvent is an instruction for part of a song. A series of MidiEvents is
kind of like sheet music, or a player piano roU. Most of the MidiEvents we 1 MidiEVent says
care about describe a thing to do and the momentin time to do it. The moment
in time part matters, since timing is everything in music. This note follows
whBt to do and
this note and so on. And because MidiEvents are so detailed, you have to say ~todo~
Everg~on
at what moment to start playing the note (a NOTE ON event) and at what
moment to step playing the notes (NOTE OFF event). So you can imagine
that firing the "stop playing note G" (NOTE OFF message) before the "start
playing Note en (NOTE ON) message wouldn't work. must include the
The MIDI instruction actually goes into a Message object; the MidiEvent is ~s.fortbat
a combination of the Message plus the moment in time when that message
should 'fire'. In other words, the Message might say, "Start playing Middle
in8tJtuction..
C" while the MidiEvent would say. "Trigger this message at beat 4".
In other words, at

-
So we always need a Message and a MidiEvent.
The Message says what to do, and the MidiEvent says when to do it.
which beat that
thing ahould happen.
• Make a Message
ShortMessage a = new Shor~Message();

• Put the Instruction in the Message "start y\a'li,,~ ~ ~.y


a. se~Message (144, 1, 44, 100); ~(- Th~ ...~~e s.a~ othtT """,'oeYS Ol\ ~e
(~e'\\ \oo\t at &e
"Vot. ya~e)
• Make Q new MidlEvent using the Message

• Add the MidiEvent to the Track

you are here ~ 343


contents of a Midi event

MIPltttessage: the heart of a MidiEvet1f


A MIDI message holds the part of the event that says toha: to do. The actual instruction
you want the sequencer to execute. The first argument of an instruction is always the type
of the message.The values you pass to the other three arguments depend on the type of
message. For example, a message of type 144 means UNOTE O~'·. But in order to carry
out a NOTE ON. the sequencer needs to know a few things....fuiagine the sequencer saying.
~OK, I'll playa note, but whu:h chantul? In other words. dc/you want me to playa Drum
note or a Piano note? And which note? Middle-C? D Sharp? I
And while we're at it. at which
vekJcity should I play the note? \
,
To make a MIDI message, make a ShortMessage instance and invoke setMessageO passing I

in the four arguments for the message. But remember, the message says only iahiu u» do. so
you still need to stuff the message into an event that adds when that message should 'fire'.

Anatomy of a message
The Message says what to do, the
The first argument to setMessageO always
represents the message 'type', while the other MidiEvent says when to do it,
three arguments represent different things
depending on the message type.
~t. ~"\ • ChoMel
-:>r>f" il'c. Jd, V ~ ~~
....t; ~ '(P - ~f:j Think of a channel like a musician in
a.setMessage(144, 1, 44, 100); a band. Channell is musician 1 (the
neldsf.3~
keyboard player), channel 9 is the
tyP ' . ~ Yd'ry dej>eJldj drummer, etc.
e. Thl$ 1$ i NOTE ~ 0I'l ~ ~
~~ ~~~ ~
f.o ~ .il"t tot" tJ.. .1, ~t, so the
k"o'ol i" ot"d .1 '~s U1t St,~
~ "[D rl.y • "ote. "eedt • Note to play
A number from 0 to 127, going
~ Message type from low to high notes.

• Velocity
How fast and hard
you press the key? 0 is so soft you
probably won't hear anything, but 100 is a
good default.

344 chapter 11
exception handling

Chat1ge a tMessage
Now that you know what's in a Midi message, you can start experimenting. You
can change the note that's played, how long the note is held, add more notes,
and even change the instrument.

• Change the note


Try a number between 0 and 127 in the note
on and note off messages.
a. setMessage (144, 1,
-
20, 100);

• Change the duration of the note


Change the note off event (not the message) so
that it happens at an earlier or later beat.

b.setMessage(128, 1, 44, 100);


MidiEvenc noteotf = new MidiEvent(b, 3);
-
Change the instrument
Add a new message, BEFORE the note-playing message,
that sets the instrument in channell to something other
than the default piano. The change-instrument message
is '192', and the third argument represents the actual
instrument (try a number between 0 and 127)

you are here 345


change the instrument and note

This version still plays just a single note, but you get to use command-line argu-
merits to change the instrument and note. Experiment by passing in two int values
from 0 to 127. The first int sets the instrument, the second int sets the note to play.
import javax.sound.midi.*; ,/

public class MiniMusiccmdLine / / thiS £ ' the first one

public static void main(Scringl) args;) (


I
MiniMusicCmdLine mini = new Mini~usiccmdL ine();
i f (a rqs .length < 2) (
System.ouc.println("Don'C forget che instrument and note args");
else (
int instrument = Integer.parse lnt(argsIO])i
int note = Integer.parselnC(args[l)l;
mini.play(instrumenc, note);

) 1/ c lose mai.n

public void play(int instrument, int note) {

try

Sequencer player = MidiSystem.getSequencer();


player.open();
Sequence seq = new Sequence(Sequence.PPQ, 4);
Track track = seq.createTrack(),

MidiEvent event = null;

ShortMessage first = new ShortMessage();


first. setMessage (192, 1, instrument, 0);
MidiEvent changelnstrument. = new MidiEvent (first, 1) ;
track.add(changelnstrument);

ShortHessage a = new ShortMessage(); Rvr. rt wi~ two i"i ~ -h-Ot'<'. D


a.setMessage(144, 1, note, 100); iD J'}..7. Try that: few ~
MidiEvent noteOn = new MidiEvent(a, 1);
track.add(noteOn);
%java MiniMusicCmdLine 102 30
ShortMessage b ~ new Shor~essage();
b.setMessage(12B, 1, note, 100); %j ava MiniMusicCmdLine 80 20
MidiEvent noteOff = new MidiEvenc(b, 16);
~ j ava MiniMusicCmdLine 40 70
track.add(noteOffl,
player.setSequence(seq);
player. start ();

I catch (ExCeption ex) (ex.printStackTrace();)


I / / cl os e p la y
/ I cl ose cla s s

346 chapter 11
exceptJon handling

Where we're headed with the rest


of the CodeKitchens
Chapter 15: the goal
When we're done, we'll have a working
BeatBox that's also a Drum Chat Client.
We'll need to learn about GUIs (includ-
ing event handling), I/O, networking, and
threads. The next three chapters (12, 13,
and 14) will get us there.

Chapter 12: MIDI events 0.11 !l!.

This CodeKitchen lets us build a little


"music video" (bit of a stretch to call it
that...) that draws random rectangles to
the beat of the MIDI music. We'll learn
how to construct and play a lot of MIDI
events (instead of just a couple, as we do
in the current chapter).

Chapter 13: Stand.-alone


BeatBox
Now we'll actually build the real Beat Box,
GUI and all. But it's limited-as Soon as you
change a pattern, the previous one is lost.
There's no Save and Restore feature, and
it doesn't communicate with the network.
(But you can still use it to work on your
drum pattern skills.)

Chapter 14: Save and


Restore
You've made the perfect pattern, and
now you can seve it to a file, and reload it
when you want to play it agoin. This gets
us ready for the 'final version (chapter 15),
where instead of writing the pattern to a
file, we send it over a network to the chat
server.

you ar e here ~ 347


exercise: True or False

This chapter explored the wonderful world of


exceptions. Your job is to decide whether each of the
following exception-related statements is true or false.

~rl\\I- 01\ F9~~


1. A try block must be followed by a catch ind a finally block.

2. If you write a method that might cause a compiler-checked exception, you


must wrap that risky code in a try I catch block.

3. Catch blocks can be polymorphic.

4. Only 'compiler checked' exceptions can be caught

5. If you define a try / catch block, a matching finally block is optional.

6. If you define a try block, you can pair it with a matching catch or finally block,
or both.

7. If you write a method that declares that it can throw a compiler-checked ex-
ception, you must also wrap the exception throwing code in a try / catch block.

8. The main ( ) method in your program must handle all unhandled exceptions
thrown to it.

9. A single try block can have many different catch blocks.

10. A method can only throw one kind of exception.

11. A finally block will run regardless of whether an exception is thrown.

12. A finally block can exist without a try block.

13. A try block can exist by itself, without a catch block or a finally block.

14. Handling an exception is sometimes referred to as .ducking' .

15. The order of catch blocks never matters.

16. A method with a try block and a finally block, can optionally declare the
exception.

17. Runtime exceptions must be handled or declared.

348 chapter 11
exception handling

Code Magnets
A working Java program is scrambled up on the fridge. (an you
reconstruct all the code snippets to make a work ing Java program
that produces the output listed below? Some of the curly braces fell
on the floor and they were too small to pick up, so feel free to add as
many of those as you needl

U)"
,/ system. out . pr 1.n
. t(Ur
I

\ system.out.print(ut u ) ;

doRisky(test)i

system .out .println(UsU); } finally

class MyEx extends Exception < }

public class ExTestDrive (

lU y e ~
S .equalslt») {

system.out.print(Ua U
) ;

throw new MyEX()i


} catch (MyEx e) {

static void doRisky(String t) throws MyEx (


Systern.out.print(Uh ");

. st iog [J args) {
public static void ma1.n( r
string test = args[O);

yo u are here . 349


puzzle: crossword

JavaOr~ss r. O
I
.' .
- I
/" 10 -
You know what to dol
-
16

I 1

I'~
- -

- rI flJ

I
f--

.
I LY

Across 20. Class hierarchy Down 12. Javac saw it coming


1. Togive value 21. Too hot to handle 2 Currently usable 14. Attempt risk
4. Flew off the top 24. Common primitive 3. Template's creation 16. Automaticacquisition
6. All this and morel 25. Coderecipe 4. Don't showthe kids 17. Changing method
8. Start 27. Unruly method action 5. Mostlystatic API class 19. Announce a duck
10. The family tree 28. No Picasso here 7. Not about behavior 22 Deal with it
13. No ducking 29, Start a chainof events 9. Thetemplate 23. Create badnews
15. Problem objects 11. Roll anotheroneoff 26. Oneof my roles
the line
18. One of Java's '49'

,.. SJ3qwnN 'S PetlSq\llON 'SZ ~ep,}p10 P~ul '£\


More Hints:
.J3U36. PION 'll (3Idw~IOUl --'0;1 '£ W31<lOJd ~ QJl!\S ·Ll. P0413W e IJl!lS "9
ilUntJQl,(II UJI!l a4\- - '9 1 4Sl!M1I1now l' '0 'z l(~pntl 'iz P1l4' l!IIprv '9
111l2jap JO 'lI<lnd ,(IUO '6 llMOQ U0I-I><lUro 10 ad.<l e 0Sfd 'oz ~

350 chapter 11
exception handling

Code Magnets
class MyEx extends Exception { }

public class ExTestDrive {

public static void main (String [J arqs) {


String test = args[O]:
try {
1. False, either or both.
2. False, you can declare the exception. syatem.out.print(Nt"):

3. True. doRisky(teat):
4. False, runtime exception can be caught.
System.out.print(Ho");
5. True .
} catch ( MyEx e) {
6. True, both are acceptable .
7. False. the declaration is sufficient.
8. False, but ifit doesn't theJVM may shut } finally {
down.
9. True. System.out.print(Hw");
}
10. False. System.out.println(Ns")j
}
11. True. It's often used to clean-up partially
completed tasks. static void doRisky(String t) throws MyEx {
12. False . System.out.print(Hh H);

13. False. if ("yesH.equals(t)


14 . False. ducking is synonornous with declar-
throw new MyEx();
ing.
}
15. False, broadest exceptions must be caught
by the last catch blocks. System.out.print(Wr")j

16. False, if you don't have a catch block, you


must declare. }
17. False .

yo u are here. 351


puzzle answers

362 chapter 11
12 getting Qui

A Very Graphic
Story
Wow! This looks great.
I guess presentation
really is everything.

Face it, yo U need to make GUIs. If you're bu iIdlng appllcatio ns that other

people are going to use,you need a graphical interface. If you're building programs for yourself.

you want a graphical Interlace. Even if you believe that the rest of your natural life will be

spent writing server-side code, where the client user interlace Is a web page, sooner or later

you'll need to write tools, and you'll want a graphical Interface. Sure, command -line apps are
retro. but not In a good way.They're weak, inflexible, and unfriendly. We'll spend two chapters

working on GUls,and lea rn key Java lang uage feat ures along the way Includ ing Event

Handling and Inner Classes. In this chapter, we'll put a button on the screen, and make It do
something when you click It. We'll paint on the screen, we'll display a Jpeg image, and we'll even

do some animation.

th is is a new cha p te r 353


your first gui

"If I see one more


It all starts with a WiMdow command-line app,
you're fired."
A]Frame is me object that represents
a window on the screen. It's where you
put all the interface things like buttons,
checkboxes, text fields, and so on. It can
have an honest-to-goodness menu bar
with menu items. And it has all the little
wiodowing icons for whatever platform
you're 00, for minimizing, maximizing, and
dosing me window.
TheJFr.ame looks different depending on
the platform you're on, This is aJFrame on
MacOSX:

"6 60
File Panlc ~ Devl al e

'" choose me
t c1lc\c me-" @

Making a GUI is easy:


• Make a frame (0 JFrame)
JFrame frame = new JFrame () ;
~~

@) Make a widget (button, text field , etc.)


JButton button = new JButton ("clicJc ms");
Put wldge1's it1 the wh,dow
Once you have aJFrame, you can put
things (widgets') in it by adding them
to the JFrame. There are a ton of Swing
components you can add; look for them
in rhe javax.swing package. The most
common include ]Button, JRadioBuHon,
JCheckBox,jLabel,jList,jScroIIPane,
JSlider,JTextArea,]TextFie1d. and
]Table. Most are really simple to use , but
some (likeJTable) can be a bit more
complicated. • Display it C9ive it a size and make iT visible)
frame.setsize(300,300);
frame.setvisible(true);

354 ch a pte r 12
geWng Qui

Your first &UI: a button Ott a frattte


import javax.swinq.*;

public class SimpleGuil { ~


public static void DlAi.n (String£] &rgll) ( ~ a.....e ar-d a
~ ",a'tt. a Y cb-\Ol.~
~r.ame frame :: new JFrame () ; ~ rc" ('/0'" Ul'l ~aS$ tne hv-cbm t,o~
JButton hutton '" new JButton ("click meN) ; tM W~ '(0" ....,al'l~ 0l'I the h

Let's see what happens when we run It:


%java SimpleGuil

Whoa! That's a
Really Big Rutton.
The button fills all the
available space in the frame.
Later we'll learn to control
where (and how big) the
button is on the frame .

you are here) 355


user Interface events

Jut ttothh1g happetts whett Iclick it... Q: Will a button look like a
Windows button when you run on
That's not exactly true. When you press the button it shows that Wlndows7
~pressed' or 'pushed in' look (which changes depending on the
plcttfonn look and feel, but it always does something to show when
it's being-pressed).
i\.: If you want it to. You can
choose from a few~look and
The real question is, "How do I get the button to do something feels~-c1asses in the core library

specific when the user clicks it?" that control what the interface looks
like. In most casesyou can choose
between at least two different looks:
the standard Java look and feel, also
We need two things: known as Metal, and the native look
and feel for your platform. The Mac
~ A method to be called when the user OSX screens in this book use either
the as x AquQ look and feel, or the
clicks (the thing you want to happen as Meta/look and feel.
a result of the button click).

@ A way to know when to trigger Q: Can I make a program look


like Aqua all the tJme7 Ellen when
that method. In other words , a way It's runnIng underWindows7
to know when the user clicks the
buttonl
A: Nope. Not all look and feels
are available on every platform. If
you want to be safe,you can either
explicitly set the look and feel to
Metal, so that you know exactly what
you get regardless of where the app
is running, or don't specify a look
and feel and accept the defaults.

Q: 1 heard Swing was dog-slow


and that nobody uses It.

When the user clicks, we want


to know. A: This was true in the past,
but Isn't a given anymore . On weak
machines, you might feel the pain of
We're interested in the user- Swing. But on the newer desktops,
and with Java version 1.3 and be-
takes-action-on-a-button event. yond, you might not even notice the
difference between a Swing GUI and
a native GUI.Swing Is used heavily
today, in all sorts of applications.

358 c hap ter 12


getting gui

&ettit1g a user evettt First, the button needs to know


Imagine you want the text on the button to that we care.
change from cuck me to I've been clicked when
the user presses the bltton. First we can write a
method that chang51' the text of the button (a
quick look.Jhr.ougfi the API will show you the ~C'f \l~, I ta--e aW
method): • ...,~t. haffe¥\S -to yt»-

public void changelt() ( r>


button. setText("I' va bean clickedl");
I your code I
But now what? How will we know when this
method should run? How will we know when the
button is clidred?

In java, the process of getting and handling a


user event is called event-handling. There are Second, the button needs a way
many different event types inJava, although
to call us back when a button-
most involve GUI user actions. If the user clicks
a button, that's an event. An event that says clicked event occurs.
-The user wants the action of this button to
happen." If it's a "Slow Tempo" button, the user
wants the slow-tempo action to occur. If it's a
Send button on a chat client, the user wants the
send-roy-message action to happen. So the most
straightforward event is when the user clicked
the button, indicating they want an action to
occur.
With buttons, you usually don't care about any
intermediate events like button-is-being-pressed 1) How could you tell a button object that you
and button-is-being-released. What you want to care about Its events? That you're a concerned
sa)' to the button is, "I don't care how the user listener?
plays with the button, how long they hold the
mouse over it, how many times they change their
2) Howwillthe button call you back? Assume
mind and roll off before letting go, etc. Just teD
that there's no way for you to tell the button the
me when the usermeans business! In other words, name of your unique method (changeltOl.So
don't call me unless the user clicks in a way that what else can we use to reassure the button that
indicates he wants the darn button [0 do what it we have a specific method It can call when the
says it'll dol" event happens? (hint:think Pet)

you are here) 351


event listeners

If you care about the button's events,

"'1W.i~iM"''''''''''''''IIiiII''''''-ii1thatsays,
ClI'm~or your events."
A listener interlace is the bridge between the \lJhen you imPlement a
',istener (you) and event source (the button). listener interface, you. give
JThe Swing GUI components are event sources. In Java terms, the hutton a way to call
an event source is an object that can tum user actions (dick you hack. The interface is
a mouse, type a key, close a window) into events. And like
virtually everything else in lava, an event is represented as an where the call-hack method
object. An object of some event class. If you scan th rough the is declared.
j ava.aWl.eve n t package in the API, you 'I) see a bunch of event
classes (easy to spot-they all have Event in the name). You'll
find MouseEvent, KeyEvent, '-\'indowEvent, ActionEvent, and
several others.

An event source (like a button) creates an event object when the


user does something that matters (like click the button) . Most
of the code you write (and all the code in this book) will receive
events rather than create events. In other words, you'lJ spend
most of your time as an event listenerrather than an event source.

Every event type has a matching listener interface. If you want


MouseEvents, im ple m e nt the MouseListen er interface. Want
WindowEvents? Implement WindowListener. You get the idea.
And remember your interface rules-e-tc implement an interface
you declare that you implement it (class Dog implements Pet) ,
which means you must write implementation methodsfor every
method in the interface.
<:</nfS.....
Some interfaces have more than one method because the Ki ""C8»
event itself comes in different flavors. If you implement eYLl8fener
Mousel.istener, for example, you can get events for keyprassed
keYRaJ (kaY£Venlev)
mousef'ressed, mouseReleased, mouseMoved, etc . Each of BaSed(ke
those mouse events has a separate method in the interface. keYTYl>&d YEvant ev)
(keYcven/ ev)
even though they all take a MouseEvent. If you implement
Mousel.istener, the mousePressedO method is called when the
user (you guessed it) presses the mouse. And when the user lets
go, the mouseReleased() method is called. So for mouse events,
there's only one event object; Mouseliveru, but several different
event methods, representing the different types of mouse events.

358 chapter 12
getting gui

How the listener and source


communicate:

"Button, please add me to


your Jist of listeners and call
my actionPerformedO method
when the user cl icks you."
"OK, you're an ActionListener,
so I know how to call you back
when there's an event -- I'll call
the actionPerformedO method
that I knowyou have."

<:>0
.1 0 Act ionList enef'(11...
o~· r"S)
",'"
'0'"

The Listener The Event Source


If your class wants to know about A button is a source of Action Events,
a button's Action Events,you so it has to know which objects are
im plement the ActionLlstener interested llsteners.The button has an
interface.The button needs to addActionUstenerO method to give
know you're Interested, so you Interested objects (listeners) a way to
register with the button by calling Its tellthe button they're interested.
addActionLlstener(this} and passing an
When the button's
ActionListener reference to It (In this case,
addAetionLlstenerO runs (because
you are the ActIon Listener so you pass
a potential listener invoked it), the
this).The button needs a way to call you
button takes the parameter (a
back when the event happens, so it calls
reference to the listener object) and
the method in the listener Interface. As an
stores it in a list. When the user clicks
ActionUstener, you must Implement the
the button, the butto n 'fi res' the event
interface's sole method, actlonf'erformedt).
by cal/Jng the actionPerformedO
The compiler guarantees It.
method on each listener In the list.

you are here ~ 359


getting events

Getting a button's ActionEvent

• Implement the ActionListener interface

• I) Register with the button (tell it you


want to listen for events)
Define the event-handling method (implement
the actionPerformedO method from the
ActionListener interrface)

public static void main (String[] args)


SimpleGuilB qui = new SimpleGuilB();
quLgoO;

<,
tt -- button .addActionListener(this);
I

frame.ge tContentPane() . add (button) ;


frame.setDefaultCloseOperation(JFrame .EXIT_ON_CLOSE) ; . tty~attS
frame. setSize (300 r 300) ; th At:t\O¥IL-is-\:.t"tY '" . t;
frame . setVisible (true) ; \",y\t"'t"t. t tdO ",tt.hod.. ih\S IS ht
. »<:": at..t.io,,?tY~OV'"' d\' ~ "'tt.hod!
• ~ . at..-tv.a\ t>le"t.-haY\ IYI
public void actionPerformed(ActionEvent event) {
button.setText("I've been clicked!");

160 chapter 12
getting gui

llsfetters, Sources, attd Evettfs


For most of your steUar Java career, yO'll will not be the source
\
of events. J
~=\er how much you /ci yourself the center of your social

Get used to it. Your~ to be a good listener.


(Which. if you do it sincerely, can improve your social life.)

As an e.vent source, my job is to


As a listener, my job is to accept rt9istrations (from listeners),
Implement the interface, get events from the. user. and
register with the button, and call the listener's event-handling
provide the event-handling. method (when the user clicks me)

Cb
Source SENDS
the event
II
Listener GETS the
event

Hey, what about me? rm a player too, you


knowI As an event object, I'm the argument
to the event call-back method (from the
interface) end my job is to carry data about
'ke event back to the listener.

Event object
HOLDS DATA
about the event

you are here) 361


event handling

Q: Why can't I be a source of events? Q: J don't see the Importa nee of the event object
that's passed to the event call-back methods. If
somebody calls my mousePressed method, what
..A..: You CAN.We just said that most of the time other Info would I need?
you'll be the receiver and not the originator of the
e~nt (at least in the early days of your brilliant Java
care~(he events you might care about
are 'fi red' by classes in the Java API,and all you have
A: A lot of the time, for most designs, you don't
need the event object. It's nothing more than a little
to do Is be a listener for them.You might, however, data carrier, to send along more info about the event .
design a program where you need a custom event, say, But sometimes you might need to query the event for
StockMarket Event thrown when your stock market specific details about the event . For example, If your
watcher app finds something It deems Important. In mousePressedO method is called, you know the mouse
that case, you'd make the StockWatcher object be an was pressed. But what If you want to know exactly
event source, and you'd do the same things a button where the mouse was pressed? In other words, what If
(or any other source) does-make a listener interface you want to know the X and Y screen coordinates for
for your custom event, provide a registration method where the mouse was pressed?
(addStockListener()), and when somebody calls It, add
Or sometimes you might want to register the some
the caller (a listener) to the list of listeners.Then, when
listener with multiple objects. An onscreen calculator,
a stock event happens, Instantiate a StockEvent object
for example, has 10 numeric keys and since they all do
(another class you 'll write) and send It to the listeners
the same thing, you might not want to make a separate
In your list by calling their stockChanged(StockEvent
listener for every single key.Instead, you might
ev) method. And don 't forget that for every event type
register a single listener with each of the 10 keys, and
there must be a matching listener Interface (so you'll
when you get an event (because your event call-back
create a StockLlstener Interface with a stockChangedO
method is called) you can call a method on the event
method),
object to find out who the real event source was. In
other words, which key sent this event.

Eachof these widgets (user Interface objects) are the


source of one or more events. Match the widgets with
the events they might cause. Some widgets might be a
source of more than one event, and some events can be
generated by more than one widget.

Widgets Event methods


check box wlndowClosing()

text field action Perfonned()

scrolling list ItemStateChanged 0

button mousePressed()

dialog box keyTyped()

radio button mouseExlted()

menu Item focusGalned()

362 chapter 12
getting Qui

&ettittg back to graphics...


Now that we know a little about how events work (we'll learn
more later), let's get back to putting stuff on the screen.
We'll spend a few minutes playing with some fun ways to get
graphic, before returning to event handling.

Three ways to put things on your GUI:

~ets on Q frame
Add buttons, menus, radio buttons, etc.
frame.getcont&ntPane() .add(myButton);
The javax.swing package has more than a dozen
widget types.

• Drow 2 t> graphics on Q widget


Use a graphics object to paint shapes.
graphics.fi110val(70,70,lOO,lOO) ;
You can paint a lot more than boxes and circles;
the Java2D API is full of fun, sophisticated
graphics methods. ;'f '\.
/ c.h3~1
<J~
• C;, sa,.. L.,.1\1'ICSS
l)

,,/.}J.. es, ~a~"'iC.~,


si
Qo~) -c: ~c\:t .

• Put Q JPEG on Q widget


You can put your own images on a widget.
qraphics.drawImage(myPic,lO,lO,this);

you are here ~ 363


making a drawing panel

Make your ow., drawi.,g widget


If you want to put your own graphics on the screen, your best
bet is to make your own paintable widget, You plop that widget
on the frame.just like a button or any other widget, but when it
shows up it will have your images on it. You can even make those
images move, in an animation, or make the colors on the screen
change every time you click a button.
"i~i~ of cake.
Make a subclass of JPanel and override one
method, palntComponentO.
All of your graphics code goes inside the paintComponentO
method. Think of the paintComponentO method as the method
called by the system to say, "Hey widget, time to paint yourself."
If you want to draw a circle, the paintComponentO method will
have code for drawing a circle. When the frame holding your
drawing panel is displayed, paintComponentO is called and your
circle appears. If the user iconifies/minimizes the window, the
JVM knows the frame needs "repair" when it gets de-iconified,
so it calls paintComponentO again. Anytime the JVM thinks the
display needs refreshing, your paintComponentO method will be

called.
One more thing, yflU never call this methodYfnl;T$e1j! The argumeo t
to this method (a Graphics object) is the actual drawing canvas
that gets slapped onto the real display. You can't get this by
yourself; it must be handed to you by the system. You'll see
later, however, that you can ask the system to refresh the display
(repaint() ), which ultimately leads to pai ntComponen t () being
called. J. lc."t~
import java. awt. * i _ ¢(.o b~
, ~ ~oI'

import j avax . swing. *; ~

364 chapter 12
getting gui

Futt fhit1Qs to do itt paittfCotMpottet1fU


Let's look at a few more things you can do in paintflomponentj).
The most fun, though, is when you start experimenting yourself.
Try playing with the numbers, and check the API for class
Graphics (later we'll see that there's even more you can do besides
what's in the Graphics class).

Dls~G ~s 't.eY t

public void paintComponent (Graphics g) { r ....,ov'(


I
~',\t ...a",t. ~

Image image = new Imagelcon ("catzilla. jpqU) . getImage () ;


J

Paint a randomly-colored circle


on a black background

public void paintComponant(Graphics g)

g.fillReot(O,O,this.getWidth(),

int red = (int) (Math.random() * 255);


int green = (int) (Math.random() * 255);
int blue = (int) {Math.random(} * 255);

Color randomColor = new Color(red, green,


g.setColor(randomColor);
g.fillOval(70,70,lOO,lOO);

~idrf
f~t to
70 .
pll(ds fro", fh J t:
J00 . p, ~ke it 100 . t: t"tt, 70 tr
Plxds ~II. pl'l<.e/s ....ide , il"d 0",

you are here. 365


drawing gradients with Graphics2D

'ehit1d every good c.raphics referettce


is a Oraphies!e object.
The argument to paintComponentO is declared as type
Graphics (java.awt.Graphics).
\
I
-
pubU.c void pa..intcomponent(G:r:a.phiclI q) ( } Methods you can call on 8
Graphics reference:
So the parameter 'g' IS-A Graphics object. Which means it drawlmageO
could be a subclassof Graphics (because of polymorphism). drawLlneO
And in fact, it is.
drawPolygon
The object referenced by the tg' parameter is adually an drawRectO
instance of the Graphics2D class.
drawOvalO
Why do you care? Because there are things you can do with
fillRectO
a Graphics2D reference that you can't do with a Graphics
reference. A Graphics2D object can do more than a Graphics fillRoundRect()
object, and it really is a Graphics2D object lurking behind the setColor()
Graphics reference.
Remember your polymorphism. The compiler decides which
methods you can call based on the reference type, not the To cast the Graphlcs2D object to
object type. If you have a Dog object referenced by an Animal a Graphlcs2D reference:
reference variable:
Graphics2D g2d = (Graphics2D) g;
Animal a = new Dog();
You can NOT say:
a.bark () i
Methods you can call on
Even though you know it's really a Dog back there. The
compiler looks at 'a ', sees that it's of type Animal, and finds
that there's no remote control button for barkr) in the Animal
class. But you can still get the object back to the Dog it really is
Ii II3DRecl 0
-
a Graphlcs20 reference:

draw3DRectO
by saying:
rotate 0
Doq d "" (Doq) Ai
d.buk () ; scaleO

So the bottom line with the Graphics object is this: sheerO

If you need to use a method from the Graphics2D class, you transformO
can't use the the paintComponent parameter ('g') straight selRenderingHlntsO
from the method. But you can cast it with a new Graphics2D
variable.
Graphics2D q2d B (Graphics2D) qi
(these are ~ot t.mr.pltf:t ",ethod lish,
thetk the API .few ",ewe.>

366 chapter 12
getting gui

'ecause life"s too short to paint the


circle asolid color when there"s a
gradient blend waithtg for you.

~ublic void IntComponent(Graphics g) (

Graphic 2D q2d : (Graphics2D) g:


~ tast it so 'Nt tar- tall ~ir-~ tha~
~.iphiul.D roas b~ ~rarhits aocsr-'i.
GradientPalnt gradient: new GradientPaint(70 ,70,Color.blue, 150,150, COlor.orange);
st.rf:j r ~rtih 't
h~ Poi~t s 4>Jor
~. ~
'''.9 poi,,/;
~~d;" ~
s toJor
~ this sets tht virboa I . 1. L .
d' falPl~ to .i
g2d. aetPaint (gradi.ent) :
1..
~ra I~l;; Ilumd 0+ a solid urush
lolor

g2d.filloval(70,70,100,100);

"'" 1\ OY\S "~i\\


tht ~i\\O~~\(~:~~t~\1:~eo (J'rI 'foVr
the O~d\ ~I~. Lhe ~rddit"t)
. LL...l>Sh u.e- '{. J
yal"~'

~llc void paintComponent(Graphics q) (


Graphics2D g2d = (Graphlcs2D) g;

int red D (lnt) (Math .random() .. 255);


int green: (int) (Math.random() .. 255);
lnt blue e (lnt) (Math .random() .. 255);
Color startColor = new Color(red, green, blue);

red = (lnt) (Math . random () .. 255);


green: (lnt) (Math.random() .. 255);
blue: (lnt) (Math,random() * 255);
Color endColor = new Color (red, green, blue) ;

GradientPalnt gradient = new GradientPalnt(70,70,startColor, 150,150, endColor);


q2d.setPaint(qradient);
g2d.fillOval(70,70,100,100) ;

you are here ~ 367


events and graphics

,...----- EVENTS--------------, , - - - - - - - - - - GRAPHICS -------,


• To make a GUI, start with a window, usually a JFrame • You can draw 20 graphics directly on to a widget
JFrame frame = new JFrame();
• You can draw a ,glf or ,jpeg directly on toawidget
• You can add widgets (buttons, text fields, etc.) tothe
JFrame using: • To draw your own graphics 0ncluding a .gif or .jpeg),
frame. getcontentPane () .add(button); make a subclass of JPanel and override the paintCom-
ponentO method.
• Unlike most other components, the JFrame doesn't let
you add to it directly, so you must add to the JFrame's • The paintComponentO method is called bythe GUI
content pane. system. YOU NEVER CALL ITYOURSELF. The argu-
ment to paintComponentO is a Graphics object that
• To make the window (JFrame) display, you must give It gives you a surface to draw on, which will end up on
a size and tell it be visible: the screen. You cannot construct that object yourself.
frama.setSize(300,300);
frame.sBtVisihle(true); • Typical methods tocall on a Graphics object (the paint-
Component paramenter) are:
• To know when the user clicks a button (ortakes some graphic5.setColor(Color.blue);
other action on the user interface) you need to listen for g.fillRect(20,SO,lOO,120);
a GUI event.
• To draw a .jpg, construct an Image using:
• To listen for an event, you must register your Interest Image ~qe = new DmageIoon("catzilla.
with an event source. An event source Isthe thing (but- jpg") .getImage();
ton, checkbox, etc.) that 'fires' an event based on user and draw the Imagine using:
interaction. g.drawDmage(image,3,4,this);
• The listener Interface gives the event source a way • The object referenced bythe Graphics parameter
to call you back, because the Interface defines the to palntComponentO is actually an instance ofthe
method{s) the event source will call when an event Graphlcs2D class. The Graphics 20 class has a variety
happens. of methods Including:
tiIl3DRect(). draw3DRect(). rotateO. scaleO, shearO,
• To register forevents with a source, call the source's
transformO
registration method. Registration methods always take
the form of: add<Event'TYpe>Usfen&r. To register for a • To invoke the Graphics2D methods, you must cast the
button's ActlonEvents, forexample, call: parameter from a Graphics object 10 a Graphlcs2D
button.addActionListener(this); object
Graphies2D g2d = (Graphics2D) g;
• Implement the listener interface byimplementing all of
the interface's event-handling methods. Put your event-
handling code inthe listener call-back method. For
ActionEvents, the method is:
publie void actionPerfoCll8d(ActionEvant
event) {
button. setText ("you elicked! ") ;
)

• The event object passed into the event-handler method


carries Information about the event, InclUding the source
ofthe event.

368 chapter 12
getting gui

We catt get att evet1t.


We catt paittt graphics.
&ufcatt we paittt graphics when we get att evettt?
Let'sJOOk up an event to a change in our drawing panel. We'll make the circle
chanle colors each time you click the button. Here's how the program flows:

Start the app


o The frame is built with the two widgets
(your drawing panel and a button). A
listener is created and registered with
the button. Then the frame is displayed
and it just waits for the user to click.

e The user clicks the button and the


button creates on event object and
calls the listener's event handler.

e The event handler calls repaintO on the


frame. The system calls paintCompone.ntO
on the drawing panel.

o Voila! A new color is painted because


paintComponentO runs again, filling the
circle with a random color.

you are here ~ 369


building a GUI frame

do you put TWO


things on a frame?

&Ullayouts: putti"g tttore thatt o.,e


widget Ott a frattte
We cover GUI layouts in the next chapter, but we'll do a
quickie lesson here to get you going. By default, a frame
has five regions you can add to. You can add only one thing
to each region of a frame, but don't panic! That one thing
might be a panel that holds three other things including a
panel that holds two more things and ... you get the idea. In
fact, we were 'cheating' when we added a button to the frame
using:

------
dd~u/t ~iOll

Given the pictures on page 351, write the


code that adds the button and the panel to
the frame.

-
370 chapter 12
getting gui

The circle changes color each time you


click the button.

import javax.awing.*;
import java .awt .*;
import java .awt.event.*; ~

public class SimpleGui3C (implemants ActionListaner (

JFrame frame;

public static void main (String [] arqs)


SimpleGu13C qui '" new SimpleGui3C():
qui. go (J ;

public void go() {


frame '" new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) ;

JButton button'" new JButton ("Change colors");


button. addActionListener (this) ; ~ _

MyDrawPanel drawPanel = new MyDrawPanel () ; A


dd tile two wid~e-b (b"i-
frame. ge tCon ten tPane () . add {BorderLayout. SOUTH, button); ~/ k dl'ld d\"..wi,,~ r~l'Iel) to
frame. 98tContentPane () . add (BorderLayout. CENTER, drawPanel); I( ~he two \"e~iOf\.S cJ the
frame. setSize (300,300) ; -tra"'e .
frame. setVisible (true) ;

class MyDrawPanel extends JPanel (

public void paintComponent(GraphicB q) (


/ / Code to 1Ul the oval wl th a random color
/ / See page 347 for the code

you are here) 371


multiple listeners

/ Let's try itwith TWO buttons

(
The south button will act as it does now, simply calling repaint 00 the
frame. The second button (which we'll stick in the east region) will
change the text on a label . (A label isjust text on the screen.)

So .,ow we t1eed FOUR widgets


-

label will
~o na-e
d__ awin~ panel ~oes
~

- ~t>t
in the tenu__

toICK-t~n~in~
b~ will ~o htre

e Attd we tteed to get


rwo events
Uh-oh.
Is that even possible? How do
Change Label you get two events when you
have only O11C actionPerfonnedO
method?

372 chapter 12
geWng gui

How do you get actio" eve"ts for two dlffere"t butto".,


whe~ each butto" "eeds to do solttethi"Q dffferettt?
i

I • option one

-. Implement two actionPerformedO methods


.--
class MyGui implements ActionListener (
II Iota of oode bere and then:

publi~ void actionPerfo~d(ActionEventevent) (


frame. repaint () ; ~ ~t. this is i"'possible'
~ .

public void actionPerformed(ActionEvent event) {


label. setText ( "That hurt! /I ) ;

Flaw: You can'ti You can't Implement the same method twice In a Java class. It won't compile.
And even if you could, how wou Id the event source know which of the two methods to call?

• option two
Register the same listener with both buttons.
class MyGui implements ActionLletaner (
I I declare a bunch of instance variables bere
-
publi~ void go() (
II build qui
eolorButton ~ new JButeon():
labelButton = new JButton() ;
colorButton. addActionLis tener (th1 e) ; ~ R.l!~isUr the ~",e lisU-"e"
labelBu t ton . addActionLis tener (this) ; l ( 'NI8, b~ blottoru
I I more qW. code here . ..

public void actionPerformed(ActionEvant event) {


if (event. gatSource () = colorButton) ( t, ab' ~d.
frama .repaintO; ~ G.~ t,nt l!'1l!'\tt. ~~8:Pn
elee ( to ~i)\d ov-t. '01". "d lASt
label.setText("That burt!/I); at~\\'( ~·,ye.ci It.. a L to do-
-lhd-t t.o dl!tid~ ",,"41~

Flaw: this does work, but In moat cases It's not very 00. One event handler
doing many different things means that you have a single method doing many different things.
If you need to change how one source is handled, you have to mess with everybody's event
handler. Sometimes It is a good solution, but usually it hurts maintainability and extensibility.

you are here. 373


multiple listeners

How do you get actio" evettts for two dffferettt butfotts,


whett each buttott tteeds to do sotltethittQ differettt?

• option three
Create two separate ActlonListener classes

alass MyGui (
JFraIDe frame;
JLabe.l label;
void gui() (
/ J code to instantiate the two listeners and reqister one
1/ wi th the color button and the other with the label button
)
II clos. class

class ColorButtonLiatener implements ActionListaner {


public void actionPer£ol:m8d (ActionEvent event) (
frame. repaint () ;
, WO'I\l wot"k! Tnis tlau dool'l't ha~t a ~e~tr'Cl'lU tp
tl\e 't~a"'t' variable o.f the M'1~\oi dau

cla.ss LabelButtonListener implements ActionLiatener (


public void actionPerfo~(ActionEventevent) (
la.bel.setText( "Tha.t hurt!H);

~ Proble...1 n °IS t.. Iau has 1'0 re-tere'lt..e


°
r
to the variable 'label'

Flaw: these classes won't have access to the variables they need
to act on, 'frame' and 'label'. You could fix It but you'd have to give each ofthe
listener classes a reference to the main GUI class,so that Inside the aetlonPerformedO
methods the listener could use the GUI class reference to accessthe variables of the GUI
class. But that's breaking encapsulatIon, so we'd probably need to make getter methods
for the g ul widgets (getFrameO.qetl.abelf), etc.). And you'd probably need to add a
constructor to the listener class so that you can pass the GUI reference to the listener at
the time the listener is Instantiated. And, well, it gets messier and more complicated.

There hQS got to be Q better wayl

374 chapter 12
getting gui

you are here. 375


inner classes

Itttter class tothe rescue!


You can have one class nested inside another. It's easy.
Just make sure that the definition for the inner class is
inside the curly braces of the outer class.

Simple inner class:


An inner class can
class MyOuterClass {
use aU tIle metltOJs
class MylnnerClass and ,'at'ial)les of the
void goO (
outer class, evert till'
)
lwi"atr ones ,
TIle inner class gets
to use tlto...e "ariahles
anJ metltOds just
as if tile mctltoJ...
An inner class gets a special pass to use the outer class's stuff. Even
and variables wel'C
the private stuff. And the inner class can use those private variables Jeclat'eJ within tlu~
and methods of the outer class as if the variables and members inner class.
were defined in the inner class. That's what's so handy about inner
classes---they have most of the benefits of a normal class. but with
special access rights.

Inner class using an outer class variable


class MyOuterClass {

private int x;

c1809MylnnerClas8 (
void go () {
x = 42; ~
}
II close inne~ class

II close outer class

376 c hapt er 12
getting gUi

A., f.,.,er class it1sfa.,ce tMust be tied to


---
at1 outer class it1stat1ce*.
Remember, when we talk about an inner class accessing
something in the outer class, we're really talking about an
illstan~ of the inner class accessing something in an instance of
An inner object
shares a special
bond with an
outer object. "
the 0tler class . But which instance?
Can dry
arbitrary instance of me inner class access the methods
and ~'l-iables of any instance of me outer class? No!
"-
An inner object must be tied to a spec fie outer object on
the heap. <D Make an instance of
the outer class

® the
Make an instance of
inner class, by
usin~ instance
of the outer class.
~ .;p
:Yl'"nner o'O~

G) The outer and inner objects


are now intimately linked,

"There's an exception to this, for a very special case-an Inner class defined
within a static method. BUI we're nol goIng there, and you might go your enUre
Java life without ever encountering one of these.

you are here ~ 37i


Inner class instances

How to "'ake an instance of an inner class


If you instantiate an inner class from code wilhin an outer class, the instance
of the outer class is the one that the inner object will 'bond' with. For
example, if code within a method instantiates the inner class, the inner
object will bond to the instance whose method is running.
./'

Code in an outer class can instantiate one of its own inner classes, in exactly
the same way it instantiates any other class... new MyInner ()

class MyOuter { \!is a ro-i'laU


n~~ t.\au t J

private int x; ~ \~fIU "aYiilb\~ ..,.

MyInner inner '" n_ MyInnar 0 ; ~ ~dkt dl\ instal'lU 0+ in


11I"tt" dilSS e
public void doStuff () { MyOuter
inner .go () ; II _u. _.I .LL(
} ~ ta il ...nnou 01\ "ton
iJ\l'l~ t.\au

class MyInner {
void goO {

}
2

II close inner class


-
('4r"--_

} II close outer class

MyOuter

Side b a r - - - - - - - - - - - - - - - - - - - - - ,
You can Instantiate an Inner Instance from code running outsidethe outer class, but you
haveto usea special syntax. Chances are you'll go through your entire Java life and never MyInner
need to makean Innerclass from outside,but just In case you'reInterested...
class Faa {
:publie statie void mairl (String[] arqll) (
MyOutA!llr outarObj '" new MyOutar () ;
MyOuter .MyInner innerObj .. outarObj. new MyInner () i

378 chapter 12
getting gui

Now we can get the two-button


code working
public class TwoButtons

JFr) frame ;
JL~/
labAl;

~liC
Cllong. LaMI
static void main CStrinq[) arqs)
TwoButtons qui = new TwoButtODS ();
qui .go () ;

public void got) (


frame = new JFrame();
frame. setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE) ;

(+,h J to t.he
JButton labelButton = new JButton ("Change Label"); ~ .,..rttad ere ~assi,,~ .:o..ab O'/'l
labelButton. aCldACtionLilltener (~" LabelLia1:aner () ) ;1 '\ ~"tton'~ \·~h.,.eY ~e~' ta"te o.c
. .J 61S a ",'OJ \Y\1
...e1:.hOU ' ~ . t.t \i~t.e"ey c.\ass.
JButton colorButton = new JButton ("Change Circle"); ~ t.he ilW~'il
colorButton. addActionListener (n_ ColorLiStaMr () ) :

label = new JLabel("I'm a label");


TwoButtorlS
MyDrawPanel drawPanel = new MyDrawPanel():
object

frams.qetContentpane() . add (BorderLayout. SOOTH, colorButton):


frame.getContentPane() . add(BorderLayout. CENTER, drawPanel) ;
frame.getContentpaneC) . add (BorderLayout. EAST, labelButton) ;
frame.getContentpane() . add (BorderLayout. WEST , label) :

frame.setSize(300,300): ColorListener
frame.setVisible(true): object

e:
class Lahelt.1atener ~l.amanta_ Ac~_~~ls ~~!. (
public void actionPerformed(ActionEvent event) (
lab&l.setTaxt("Ouch! ") :
), ~ iPl"~ tldSS kPlows
II close inner class ilbowt 'Iabd'

I
II close inner class

you are he re ~ 379


Inner classes

Ja¥a·~ed'
This weeks Interview:
Instance of an Inner Class

HeadFirst: What makes inner classes important? separate from everybody else. Inner classes aren't exactly
reusable. In fact, I've heard them called "Reuseless-
Inner object: Where do I start? We give you a chance to
useless over and over again."
implement the same interface more than once in a class.
Remember, you can't implement a. method more than Inner object: Yes it's true that me inner class is not as
once in a normalJava class. But using inner classes, each reusable, in fact sometimes not reusable at all, because it's
inner class can implement the same interface, so you can intimately tied to the instance variables and methods of
have all these diffemu implementations of the very same the outer class. But it-
interface methods. HeadFirst: -which only proves my point! If they're not
HeadFirst: Why would you ever warn to implement the reusable, why bother with a separate class? I mean, other
same method twice? than the interface issue, which sounds like a workaround
Inner object: Let's revisit GUI event handlers. Think to me.
about it ... if you want thru buttons to each have a Inner object: As I was saying, you need to think about
different event behavior, then use three inner classes, all IS-A and polymorphism.
implementing Actionl.istener-r-which means each class HeadFirst: OK. And I'm thinking about them because...
gets to implement its own acrionPerformed method.
Inner object: Because the outer and inner classes
HeadFirst: So are event handlers the only reason to use might need to pass differtm IS-A tests! Let's start with the
inner classes? polymorphic GUI listener example. What's the declared
Inner object: Oh, gosh no . Event handlers are just an argument type for the button's listener registration
obvious example. Anytime you need a separate class, but method? In other words, if you go to the API and check,
still want that class to behave as if it were part of another what kind of thing (class or interface type) do you have to
class, an inner class is the best-and sometimes only-way pass to the addActionLstener() method?
to do it.
HeadFirst: You have to pass a listener. Something that
HeadFirst: I'm still confused here. If you want the inner implements a particular listener interface, in this case
class to behave like it belongs to the outer class, why have ActionListener. Yeah, we know all this. What's your point?
a separate class in the first place? Why wouldn't the inner Inner object: My point is that polymorphically, you have
class code just be in the outer class in the first place? a method that takes only one particular rype. Something
Inner object: I just glIl.lt you one scenario, where you that passes the IS-A test for Actionl.istener, But-and
need more than one implementation of an interface. But here's the big thing-what if your class needs to be an IS-
even when you 're not wing interfaces, you might need A of something that's a cum type rather than an interface?
two different classes because those classes represent two HeadFIrat: Wouldn't you have your class just extend the
different tlting.s. It's good 00. class you need to be a part of? Isn't mat the whole point
HeadFirst: Whoa. Hold on here. I thought a big part of of how subclassing works? If B is a subclass of A, then
00 design is about reuse and maintenance. You know, the anywhere an A is expected a B can be used. The whole
idea that if you have two separate classes, they can each pass-a-Dog-where-an-Animal-is-the-declared-type thing.
be modified and used independently, as opposed to stuffing Inner object: Yes! Bingo! So now what happens if you
it all into one class yada yada yada. But with an inner class, need to pass the IS-A test for two different classes? Classes
you're still just working with one real class in the end, right? that aren't in the same inheritance hierarchy?
The enclosing class is the only one that's reusable and

380 chapter 12
getting gui

HeadFirst: Oh, weU you just, .. hrnmm. I think I'm get- HeadFirst: Whose life? Yours? The outer object? Both?
ting it. You can always implement more than one interface, Inner object: Mine. I can't be tied to any other outer
but you can extend only one class. You can only be one kind
object. My only way out is garbage collection.
\of IS-A when it comes to elms types .
\
HeadFirst: What about the outer object? Can it be
'Inner object: Well done! Yes, you can't be both a Dog associated with any other inner objects?
and a Burton. BUt if you're a Dog that needs to some-
times be a Burton (in order to pass yourself to methods Inner object So now we have it. This is what you really
that take a Buuon), the Dog class (which extends Animal wanted. Yes, yes. My so-called 'mate' can have as many
so it can't extend Burton) can have an inner class that acts inner objects as it wants.
on the Dog's behalf as a Button, by extending Burton, HeadFirst: Is that like, serial monogamy? Or can it have
and thus wherever a Button is required the Dog can them all at the same rime?
pass his inner Button instead of himself. In other words,
Inner object: All at the same time. There, Satisfied?
instead of saying x.takebunoruthis), the Dog object calls
x.takeButton(new Mylnnerfluttoru j). HeadFirst: Well, it does make sense. And let's nOI
forget, it wasyou extolling the virtues of "multiple
HeadFirst: Can I get a clear example?
implementations of the same interface", So it makes sense
Inner object: Remember the drawing panel we used, that if the outer class has three buttons, it would need
where we made our own subclass of JPanel? Right now. three different inner classes (and thus three different inner
that class is a separate, non-inner, class. And that's fine, class objects) to handle the events. Thanks for everything.
because the class doesn't need sp ecial access to the instance Here's a tissue.
variables of the main GUI. But what if it did? What if
we 're doing an animation on that panel, and it's getting its
coordinates from the main application (say, based on some-
thing the user does elsewhere in the GUI). In that case, if
we make the drawing panel an inner class, the drawing
panel class gets to be a subclass of]panel, while the outer
class is still free to be a subclass of something else.
HeadFirst: Yes I see! And the drawing panel isn't reus-
able enough to be a separate class anyway, since what it's
actually painting is specific to this one GUI application.
Inner object: Yes! You've got it!
HeadFirst: Good. Then we can move on to the nature of
the relatirmshi/J between you and the outer instance.
Inner object: What is it with you people? Not enough
sordid gossip in a serious topic Like polymorphism?
HeadFirst: Hey, you have no idea how much the public is
willing to pay for som e good old tabloid dirt. So, someone
creates you and becomes instantly bonded to the outer
object, is that right?
Inner object: Yes that's right. And yes) some have
compared it to an arranged marriage. We don't have a say
in which object we're bonded to.
HeadFirst: ALight, I'll go with the marriage analogy.
Can you gel a divorce and remarry something else?
Inner object: No, it's for life.
you are here) 381
Inner classes

Ushtg att itttter class for atthttatiott


We saw why inner classes are handy for event listeners, because
you get to implement the same event-handling method more
than once. But now we'Ulook at how useful an inner class is when
used as a subclass of something the outer class doesn't extend. In
other words. when the outer class and inner class are in different
inheritance trees]
Our goal is to make a simple animation, where the circle moves
across the screen from the upper left down to the lower right,

1.81'1

• Q:Why are we learning about


animation here11 doubt if I'm

• going to be making games.

A:vou might not be making


games. but you might be
How simple animation works creatIng simulations, where
things change over time to show
• Paint an object ot a particular x and y coordinate the results of a process.Or you
might be building a visualization
q.fillOval(20,50,lOO,100) ;
~ tool that, for example, updates

t 2-0 piuls +r-0I'tI the lett,


c;o ril(~ls ~r-0I'tI the top
a graphic to show how much
memory a program is using,
or to show you how much
trafflc is coming through
your load-balancing server.
Anything that needs to take a
• Repaint the object at a differe'1! x and y coordinate set of continuously-changing
g.fillOval(25,55,lOO,lOO) ; numbers and translate them Into
~ something useful for getting
t2? piuls ~rOl'tl the lett, 97
piuls kr-Of'Il -the iof
Informatlon out of the numbers.
Doesn't that all sound business-
like? That's Just theMofficial
(the objett ""oved a little justlflcatlon: of course.The real
dOWJl a...d to the \"i~nt.> reason we're covering it here is
Just because it's a simple way
to demonstrate another use
of Inner classes. (And because
we Just like animat ion, and our
• Repeat the previous step with changing x and y values next Head First book Is about
for as long as the animation is supposed to continue. J2EE and we know we can't get
animation in that one.)

382 chapter 12
getting gui

w\ we !eally want is something like...

/
t s s MyDrawPanel extends JPanel {
public void paintcomponent(Graphics g) {
g.setColor(Color.orange);
g.fillOval(x,y/100,lOO)i

~
eaL\I b",e Y'II"~&:~a'I~t. il
t,d\\ecl. -\:)Ie O"Iil ~
d\~~er",t. \~

~ your penCil
But where do we get the new x and y
coordinates?

And who calls repaint()?


See if you can design a simple solution to get the ball to animate from the top left of the
drawing panel down to the bottom right Our answer Is on the next page, so don't tum
this page until you're done!
Big Huge Hint make the drawi ng panel an inner class.
Another Hint don't put any kind of repeat loop In the palntComponentO method.
Write your Ideas (or the code) here:

you are here ~ 383


animation using an inner class

~\)complete simple animation code


import javax.swing.*;
import java.awt.*;

public olass SimplQAnimation ~ ~yo,U IIOtiab\es ,,, t,hL


",a\c.L t.'WC ,YIS ~ t,hL "" d"d 'I
int x = 70 it
~ ",d'l'I ~V.\ daS1. (/f" l.i'f'Ck
tnt y :II 70; ~ ~d"~ ~ t.ht.
public static void main (Strinq[] arqa) (
SimpleAnimation qu.i = new Si.mpleAnimation ();
qui .go () ;

public void go() (


JFrama frame '" MlW JFrame () ;
lrame.setDefaultCloa8Operat!on(JFrama.EXIT_ON_CLOSE)i

MyDrawPanel drawPanel = new MyDrawPanel () ;

traMa.qetcontentpane() . add (dra wPane l ) ;


frame.setSize(300,300);
frame.setVis~le(true);

for (int 1 - 0; i <130; i++) {

}/I close got) method

class MyDrawpanel extends JPanel (

public void paintcomponent(Graphics g) I


g.setcolor(Color.qreen);
q.filIOval(x,y,40,40);

II close inner class


II close outer class

384 chapter 12
geWng gui

u~. It didn't move••• it smeared.


What di'~e. do wrong?
There's one little flaw in the paintComponentO e e 6"--- -1
method. 1--
We forgot to erase what was
already there! So we got trails.
To fix it, all we have to do is fill in the entire panel with
the background color, before painting the circle each
time. The code below adds two lines at the start of the
method : one to set the color to white (the background
color of the drawing panel) and the other to fill the
entire panel rectangle with that color. In English, the
code below says, "Fill a rectangle starting at x and y of
0(0 pixels from the left and 0 pixels from the top) and
make it as wide and as high as the panel is currently.

publio void paintComponent(Graphics q) (


g.setColor(Color .white);
g. fillRect (0 ,0, this . qatWidth 0 , this .qetHeigbtO);

q.aetColor(Color .qreen);
g. fUIOva.l (x, y, 40,40) ;
~
~etw;dt.h()
1l
ar,d 9dl+ti ~t()

~
"'tthod$ il'lhtyoiUd r ~ drt
i"l-0I0I JPal'ItI.

~ IJ : 'Sharpen yu peooIloptional.just for funl


What changes would you make to the x and y coordinates to produce the animations below?
(assumethe first one example moves in 3 pixel Increments)

l[]Q start finish


x +3
v--±L
start finish
x
y--

2[][3 start finish


x
y--
'DO start finish
x
y--

'DD start finish


x
v__
'DD start finish
x
y--

you are here ~ 385


Code Kit~en

...
16 0 B §.~-----1


beat tow ...

let's make a music video. We'll use Java-generated ranJom


graphics that keep time with the music beats.
Along tbe way we'll register (and listen lor) a new lund ol
non-GUI event, triggered by the music itseLt.

Reme>r>be-, this paH: is ,)11 orti-al. Bl>t we th irJc. i-t's 500<.\ .fot' yo....
And yo~,.'11 likt it. And y~ tdn ~ it to i""f'YW ftoplt.
(Ole, Slol't, it mi5ht wot'k cw.1'I Of> ptoplt who .ll'e I'tally tasy to i"'fl"~
bllt still...)

186 ch ap ter 12
getting gu

OK, maybe not a music video, but we wiU make


a program that draws random graphics on the
screen with the beat of the music. In a nutshell, What the music art program
the program listens for the beat of the music needs to do:
and draws a random graphic rectangle with each
beat.
• Make a series of MIDI messages/
That brings up some new issues for us. So far,
we've listened for only GUI events, but now events to play random notes on a piano
we need to listen for a particular kind of MIDI (or whatever instrument you choose)
event. Turns out, listening for a non-GUI event is
just like listening for GUI events: you implement
• Register a listener for the events
a listener interface, register the listener with an
event source, then sit back and wait for the event
source to call your event-handler method (the • Start the sequencer playing
method defined in the listener interface) .
The simplest way to listen for the beat of the
music would be to register and listen for the • Each time the listener's event
actual MIDI events, so that whenever the handler method is called, draw a
sequencer gets the event, our code will get it random rectangle on the drawing
too and can draw the graphic. But... there's a panel, and call repaint.
problem. A bug, actually, that won't let us listen
for the MIDI events we're making (the ones for
NOTE ON ).
So we have to do a little work-around. There
is another tjpe of MIDI event we can listen We'll build it in three iterations:
for, called a ControllerEvent. Our solution
is to register for ControllerEvents, and then
make sure that for every NOTE ON event, • Version One: Code that simplifies mak-
there's a matching ControllerEvent fired at ing and adding MIDI events, since we'll
the same 'beat'. How do we make sure the be making a lot of them.
ControllerEvent is fired at the same time? We
add it to the track just like the other events! In
other words, our music sequence goes like this: • Version Two: Register and listen for
the events, but without graphics.
BEAT I - NOTE ON, CONTROLLER EVENT
Prints a message at the command-line
BEAT 2 - NOTE OFF with each beat.
BEAT 3 - NOTE ON, CONTROLLER EVENT
BEAT 4 - NOTE OFF • Version Three: The real deal. Adds
graphics to version two .
and so on.
Before we dive into the full program, though,
let's make it a little easier to make and add MIDI
messages/ events since in this program, we're
gonna make a lot of them.
you are here ~ 387
Util~ method for evenls
/

At' easier way to 'Make


'Messages / eVet1ts
Things that have to happen for
Right now, making and adding messages and each event:
events to a track is tedious. For each message,
we have to make the message instance (in this . . Make a message instance
case, ShortMessage), call setMessageO, make a ShortMsssage Drst :: new SbortHessage();
MidiEvent for the message, and add the event
to the track. In last chapter's code, we went
through each step for every message. That
means eight lines of code just to make a note
• Call setMessogeO with the instructions
play and then stop playingl Four lines to add a first . setMessage (192, 1, instrument, 0)
NOTE ON event, and four lines to add a NOTE
OFFevenl
ShortM8ssage a = new ShortMessage();
(I Make a MidiEvent instance for the message
a.setNessage(144, 1, note, 100); MidiEvent noteOn '" new MidiEvent(first, 1);
MidiEvent noteOn :: new MidiEvant(a, 1);
track. add (noteOn) ;
• Add the event to the track
ShortM8ssaqa b = new ShortMessage();
b.setMessagB(128, 1, note, 100); track .add(noteOn);
MidiEvent noteOff = new Mid..iEvent(b, 16);
track.add(noteOff);

Let's build a static utility method that


makes a message and returns a MidlEvent

public: static MidiEvant makeEvent(int comd, int chan, int one, int two, int tick) (
MidiEvent event = null;
try (

ShortMessllgB a '" new ShortMess&ge () J '


a.setMessag8(Comd, chan, one, two);
event = new MidiEvent (a, ticJc);

}catch(Exception e) { }
return e v e n t ; L LL L H·di~'w . t all
{a I~I\
~ yn"Yl'I "{;Ilt tVeT\"{;

loaded lI.y 'With t.ht ... ess.a~()

388 chapter 12
getting gui

Exatttple: how to use the new static


I\takeEvet1tO tttethod
There's no event handling or graphics here,just a sequence of 15
notes that go up the scale. The point of this code is simply to learn
how to use our new makeEventO method. The code for the next
two versions is much smaller and simpler thanks to this method.

import javax. sound. midi. * ; ~ dOh it tot- et


!J the i"'pot-t
public class MiniMUsicPlayer1 {

public static void main(String[] args) {

try
) a st,~t"t~
Sequencer sequencer = MidiSys tem. getsequencer 0 ; " - av.t (a"d eyt"
sequencer.open(); L~ '"

Sequence seq = new Sequence (Sequence. PPQ, 4); ake a se,\~nte +- ...
Track track = seq.createTrackO; ~ and a hatk

for (int i = 5; i < 61; i+= 4) {~ ...ake a b~nth 0+ events to ...ske the notes keel'
~oin~ ~l' (~YOftl l'iano note .; to l'iano note bD
track .add(makeEvent(144,1,i,100,i»;
track.add(makeEvent(128,1,i,lOO,i + 2»; tall ~r hew rr.akeEventO "'ethod to k
rr.essa~e ahd
event th ",a e the
II end loop
MidiCveht rd;~rh:d add /1'1
the reslA/t (the
the tratk Th i,0rr. rr.akeEvehtW to
NOTE . ese are ,.OTE ON att)
sequencer. setSequence (seq); ~ ta . OFF 29) pairs a ahd
sequencer. setTempolnBPM(220) ; s rf. It r..... hih!J
sequencer.start();
} catch (Exception ex) (ex.printStackTrace();}
II close main

public static MidiEvent makeEvent(int comd, int chan, int one, int two, int tick) {
MidiEvent event = null;
try {
ShortMessage a = new ShortMessage();
a.setMessage(comd, chan, one, two);
event = new MidiEvent(a, tick);

}catch(Exception e) { }
return event;

} II close class

you are here ~ 389


controller events

import javax .sound.Ulidi. *;


public class MiniMuaicPlayer2

public static void main(String[] args) (


~n£MusicPlayer2 mini : new MiniMusicPlayar2();
mini-goO ;

Sequence seq = new Sequence (Sequence. PPQ, 4) ;


Track track = s&q.createTrack();

sequencer.setsequence(seq);
sequencer.setTempoInBPM(220};
sequencer.start() ;
} catch (Exception ax)
II close

(~ -I:h~ CO'I'trol1ty-
L - T'nL ~"ty\tha"cilty "'~ ~c:t.,i... e 'fo/t. ~d ~e
~
'S""' ·. t. KIl to the tD",,,,a,,a- I"r.(..
.l \" l _
~..,e""
i,,~-tat~. 1
,
e..,e"t" '/ole'n F'"
public MidiEvent makeEvent (int cOJDd, int chan, int one, int two, int tick) (
MidiEvent event .. null;
try (
ShortMassage a ~ new ShortNessage():
a. BetM&ssage (comd, chan, on8, two);
evant = new Micli.Event(a, tick);
Code that's different from the previous
I catch (Exception e) I } version is highlighted in gray. (and we're
return event: not running it all within mainO this time)
}
I II close class

390 chapter 12
getting gui

Version Ihree: drawing graphics in thtte with the tltusic


This final version builds on version two by adding the GUI parts. We build a
frame, add a drawing panel to it, and each time we get an event, we draw a
new rectangle and repaint the screen. The only other change from version
two is that the notes play randomly as opposed to simply moving up the
scale.
The most important change to the code (besides building a simple GUI)
is that we make the drawing panel implement the ControllerEventListener
rather than the program itself. So when the drawing panel (an inner class)
gets the event, it knows how to take care of itself by drawing the rectangle.
Complete code for this version is on the next page.

The drawing panel inner class:

I ' a list.eYltV'
C Tht clV'a..,iYl~ ya Ylt 's

class MyDrawPanel extends JPanel implements ControllerEventListener

boolean msg = false; t-- r'~Lsd: a .fla~ to .faist, a",d ..,~'" Stt it
W 1;1"\Ot OI'Ily wht'" Wt g~t a", ~ve",t.
public void controlChange(ShortMessage event) (
msg = true; f..--..
repaint () ; r- We ~ot a", ~vtnt, so w~ set the .flag to
tl"\Ot and tall l"~pai"'tO

public void paintComponent{Graphics g) {


if (msg) (~
We hav~ to l.lS~ a .fla~ b~tal.lS~ OT»ER th·
a",d w~ want to Dai",i ONL\/ h Lh Iln~sCllli~~~ t\"i~~~\" a \"tpainiO,
r T w tn 1; ere S a OI'IvolJt\"Evtnt
Graphics2D g2 = (Graphics2D) g;

int r = (int) (Math.random{) * 250);


int gr = (int) (Math.random() * 250);
int b = (int) (Math .random() * 250); Tht I"est is tod~ to ~t"'t\"aie
a \"andOlll tolO\" and paint a
g.setColor(new Color(r,gr,b»; Stllli-\"andolll \"tttan~lt .
int ht = (int) «Math.random() * 120) + 10);
int width = (int) «Math.randomO * 120) + 10);
int x = (int) «Math.random() * 40) + 10);
int y = (int) ({Math.random() * 40) + 10);
g.fillRect(x,y,ht, width);
msg = false;

} II close if
} II close method
II close inner class

you are here ~ 391


MiniMusicPlayer3 code

~}V~
import j avax. sound. midi . * ; This is the complete code listing for Version
import java.io.* ; Three. It builds directoy on Version Two. Try
import javax.swing.*; to annotate it yourself, without looking at the
import java.awt.*;
previous pages.
public class Min1MusicPlayer3

static JFrame f = new JFrame(~My First Music Video");


static MyDrawPanel ml;

public static void main(String[] args) (


Min1MusicPlayer3 mini = new Min1MusicPlayer3();
mini.goO;
) / / close method

public void setUpGuiO (


ml = new MyDrawPanel();
f.setContentPane(ml) ;
f .setBounds(30,30,300 ,300);
f .setVisible(true) ;
/ / close method

public void qo()


setUpGui();

try {

Sequencer sequencer = MidiSystem.getSequencer();


sequencer.open();
sequencer .addControllerEventListener(ml, new int[] {127»;
Sequence seq = new Sequence(Sequence.PPQ, 4);
Track track = seq.createTrack() ;

int r = 0;
for (int i = 0; i < 60 ; i+= 4)

r = (int) «Math.random() * 50) + 1);


track.add(makeEvent(144,1,r,100,i»;
track.add(makeEvent(176,1,127,0,i»;
track.add(makeEvent(128,1,r,100,i + 2» ;
II end loop

sequencer.setSequence(seq);
sequencer.start();
sequencer.setTempoInBPM(120);
} catch (Exception ex) {ex.printStackTrace() ;}
/ / close method

392 chapter 12
exercise: Who Am I

A bunch of Java hot-shots, in full costume, are playIng the party game-Who
am Ir They give you a clue, and you try to guess who they are, based on
what they say. Assume they always tell the truth about themselves. If they
happen to say something that could be true for more than one guy, then
write down all ios whom that sentence applies. Fill In the blanks next to the
sentence with the names of one or more attendees.

Who am IP Tonight's attendees:


Any of the charming personalities from this chapter just
might show upl

I got the whole GUI, In my hands.

Every event type has one of these.

The listener's key method.

This method gives JFrame its size.

You add code to this method but never call It.

When the user actually does something, It's an _ _ .

Most of these are event sources.

I carry data back to the listener.

An addXxxLlstener( ) method says an object is an _ _ .

How a listener signs up.

The method where all the graphics code goes.

I'm typically bound to an Instance.

The 'g' In (Graphics g), Is really of class.

The method that gets palntComponent( ) roiling.

The package where most of the Swingers reside.

394 chapter 12
getting Qui

BE the eomriler
The Java nle on this page represents a
complete source t\le. Your jah is to play
import javax.swing.*j compiler and detertrtine whether this file
import java.awt.event.*; will cOl1Ipile. If it won't co11IPile, haw
import java.awt.*; would you t'xx it, and if it does
compile, what would it do?
class InnerButton

JFrame frame;
Jautton bi

public static void main(String II args)


InnerButtan qui = new InnerButton();
guL go () ;
}

public void gal) {


frame = new JFrame();
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);

b = new JButton(UA n ) ;
b.addActionListener()j

frame.getContentPane().add(
BorderLayout.SOUTH, b);
frame.setSize(200,lOO);
frame.setVisible(true)i
}

class BListener extends ActionListener {


public void actionPerformed(ActionEvent e) {
if (b.getText().equals(MAn» {
b.setText(uBn);
} else {
b. setText (UA to) i

}
you are here ~ 395
getting gui

import javax.swing.*; Once this code


import java.awt.event.*; is fixed, it will
Who am I? import java. awt. *J
create a GUI with
a button that
toggles between
I got the whole GUI. in my hands. JFrame class InnerButton A and B when you
click it.
Every event type has one of these . listener interface JFrame frame;
JButton b;
The listener's key method. actionPerlormed( )

This method givesJFrame its size. setSize( ) public static void main(String [I args)
InnerButton qui ~ new InnerButton():
You add code to this method but qui-go( I:
never call it. paintCompone.nt( )

When the user actually does public void go(l {


something, it's an __ event
frame = new JFrame();
Most of these are event sources. swing components frame.setDefaultCloseOperation(
JPrame. EXIT_ON_CLOSE) ;
I carry data back to the listener; event object
The addActionListener( )
An addXxxListener( ) method method takes a class that
says an obj ect is an _ event source implements the Actionl.is-
tener interface
How a listener signs up. addActionListe.ner( )

The method where all the b = new JButton("A")j


graphics code goes. paintComponent( ) b. addActionLiBtener( lIiW JLlstettar( I ) l

I'm typically bound to an instance. inner class frame.getContentPane() .add(


BorderLayout.SOOTB, bl;
The 's' in (Graphics g). is
frame.setSize(200,lOO)l
really of this class. Graphics2d
frame.setVisible(true);
The method that gets
paintCornponent( ) rolling. repaint( )
class BListener hllpltJll8l1t1 ActionListener {
The package where most of the public void actionPerformed(ActionEvent el
Swin ge rs reside. javax.swing if (b.getText().equals(UA"ll {
b. BBtText (»B'") :
else { ActionListener is an
b. setText (»A" Ii interface. interlaces
are implemented, not
extended

you are here. 397


puzzle answers

pool puzzle
import javax.swing.*;
import java.awt.*;
public class Animate {
int x = 1;
int y : 1;
public static void main (String[] args) {
Animate gui = new Animate ();
guLgo() ;

pUblic void go()


JFrarne frame new JFrame( 1 j
frarne.setDefaultCloseOperation(
The Amazing. Shrinking, Blue JFrame.EXIT_ON_CLOSE)j
Recta ngle.
MyDrawP drawP = new MyDrawPOi
frame.getcontentPane().add(drawP)j
f rame.setSi ze( 500 ,27 0 ) ;
frame.setViaible(true);
for (int i = 0; i < 124; i- X ++,Y++ ) {
x-;
drawP.repaintO;
try {
Thread.sleep(50);
} catch(Exception ex) { }

}
class MyDrawP extends JPanel {
public void paintComponent(Graphics 9 1 {
g.setColor(Color.white);
g.fiIIRect(O,0 ,5 00, 250 );
g.setColor(Color.blue);
g.filJRect(x,y ,500-x· 2 ,250 -y"" 2);

398 chapter 12
13 using swing

Work on Your
Swing

Swing is easy. Unless you actually care where things end up on the screen. Swing code

looks easy,but then you compile it, run it, look at it and think- 'h~y, that's not supposed to go
there." The thing that makes it easy to code Is the thing that makes It hard to canuo/-the
layout Manager. Layout Manager objects control the size and location of the widgets in a
Java GUJ. They do a ton of work on your behalf, but you won't always like the results.You want

two buttons to be the same size,but they aren't. You want the text field to be three inches long,

but It's nine. Or one. And under the label instead of next to It. But with a tittle work, you can get

layout managers to submit to your will. In th is chapter, we'll work on our Swing and in addition

to layout managers, we'll learn more about wIdgets. We'll make them, display them (where we

choose), and use them In a program. It's not looking 100 good for Suzy.

th is is a n ew c hap te r 399
components and containers

Camponent is the more correct term for what we've been calling a widget.
The things you put in a CUI. The things a usersees and interacts with. Text
fields , buttons, scrollable lists, radio buttons, etc. are all components. In A widget is teduucal.ly
fact, they all extend javax. swing. JComponent.
a Swing Com~ent._
COlMpo.,etds can be nested Almost every thing
In Swing, virtually all components are capable of holding other you can stick in a
components. In other words, you can siUkjust about anything into anything
else. But most of the time, you'll add userinteractive components such as GUI extends !rom
buttons and lists into background components such as frames and panels. javaLSWing.JComponent.
Although it's possible to put, say, a panel inside a button, that's pretty
weird, and won't win you any usability awards.
With the exception ofJFrame, though, the distinction between interactive
components and ba.ckground components is artificial. AJPanel. for
example, is usually used as a background for grouping other components,
but even aJPanel can be interactive. Just as with other components, you
can register for the JPanel 's events including mouse clicks and keystrokes.

Four steps to making a GUI (review)


• Make a window (e JFrame)
JFrame frama "" n_ JFrame () ;

• Make a component (button, text field, erc.)


JButton button - ne. JButton("click me U
) ;

• Add the component to the frame


frame. getContantPane () . add (BordarLayout. EAST • button);

• Display it (give it a size and make it visible)


frame .setsize(300,300);
frame.setVisible(true)i

Put interactive components: Into background components:


. ..o~
J?al\t\

400 chapler 13
using swing

Layout Mahagers
A layout manager is aJava object associated
with a particular component, almost always a
background component, The layout manager
controls the components contained within the
component the layout manager is associated
with, In other words, if a frame holds a panel,
and the panel holds a button, the panel's layout
manager controls the size and placement of
the button, while the frame's layout manager
controls the size and placement of the _IIIIII!IIII!!!II------~~,
panel. The button. on the other hand.
doesn't need a layout manager because the
button isn't holding other components.
If a panel holds five things. even if those
five things each have their own layout
managers, the size and location of the five
th ings in the panel are all controlled by the
panel's layout manager. If those five things,
in tum , hold otherthings, thea those other
things are placed according to the layout
manager of the thing holding them.
When we say hold we really mean add as in, a
oanel holds a button because the button was
added to the panel using something like:
~Panel.add(button);

Layou t managers come in several flavors, and


each background component can have its own
yo u t manager. Layout managers have their
wn policies to follow when building a layout,
For example, one layout manager might insist
that all components in a panel must be the same
size, arranged in a grid , while another layout
manager might let each component choose its
own size, but Slack them vertically. Here's an
example of nested layouts:
JPanel panelA = new JPanel () ; Panel A
JPanel panelB = new JPanel() ;
panelB.add(new JButton("button 1"»;
panelB.add(new JButton("button 2");
panelB.add(new JButton("button 3"));
panelA.add(panelB);

you are here • 401


layout managers

How does the layout tttat1ager decide?


Different layout managers have different policies for arranging
components (like , arrange in a grid. make them all the same size,
stack them vertically, etc.) but the components being layed out do
get at least some small say in the matter. In general, the process of
laying out a background component looks something like this :
Let's see here... the
A layout scenario: first button wants to be
30 pixels wide, and the text field
<D Make a panel and add three buttons to it. needs 50, and the frame is 200 pixels
wide and I'm supposed to arrange
@ The panel's layout manager asks each button-how big everything vertically...
that button prefers to be ,
oo
@ The panel's layout monager uses its layout policies to decide
whether it should respect all, part, or none of the buttons'
preferences.

@) Add the panel to a frame.

@ The frame's layout manager asks the panel how big the panel
prefers to be.

@ The frame's layout manager uses its layout policies to decide


whether it should respect all, part, or none of the panel's
preferences.

VlffereMt layout IMattagers have dlfferettf policies


Some layout managers respect the size the component wants to
be. If the button wants to be 30 pixels by 50 pixels, that's what the
layout manager allocates for that button , Other layout managers
respect only part of the component's preferred size. If the button
wants to be 30 pixels by 50 pixels, it'll be 30 pixels by however
wide the button's background panel is, Still other layout managers
respect the preference of only the largest of the components
being layed out, and the rest of the components in that panel
are all made that same size. In some cases, the work of the layout
manager can get very complex, but most of the time you can
figure out what the layout manager will probably do, once you get
to know that layout manager's policies .

402 ch apte r 13
using swing

Ihe Jig fhree layout tttat1agers:


border; flo~ and box.

BorderLayout
A BorderLayout manager divides a background
component into five r~ions. You can add only one \-------
component per region to a background controlled
by a BorderLayout manager . Components laid out
by this manager usually don't get to have their
preferred size. 9orderlayout Is the default layout
II\Qna~ for Q fromel
U
----- I

FlowLayout
A FlowLayout manager acts kind of like a word
processor, except with components instead of
words . Each component is the size it wants to be,
and they're laid out left to right in the order that
they're added. with ·word-wrap" turned on. So
when a component won't tit horizontally, it drops
to the next "line" in the layout. FlowLayout Is the
default layout mo~,. for a pone"

BoxLayout
A BoxLayout manager is like FlowLayout in that
each component gets to have its own size, and
the components are placed in the order in which
[ J
they're added. But. unlike FlowLayout. a BoxLayout o
manager can stack the components vertically (or 0..-.
horizontally, but usually we're just concerned with 1\ :§)
vertically). It's like a FlowLayout but instead of
having automatic 'component wrapping', you can
(~ 0
-
insert a Sort of 'component return key' and force
the components to start a new line.

you are here) 403


border layout

r BorderLayout cares
\--------- about five regions:

u east, west, north,


south, and center

Let's add a button to the!!!! region:

import javax. swing. * ; t' . \Alld.a...,t y.)t\(a¥


import java. an. *; ~ BcKdlYLa'fOlO I' In.r

public class Buttonl

public static void ma.in (Strinq[l argos) I


Buttonl qui = new Buttonl () i
qui-goO;

public void go () ( . ~ \}If. '"t.~iO"


JFrame frame = new JFrame () ; SVf.C,I 'f
JButton button = new JButton ("cliclc me"); ( '
frame. qetContentpane () .lldd(BorderLayout.EAST I button) i
frame.Betsi~e(200/200);
frame.setVisible(true);

'f.tttII'.J.':V Iraill Barllell----------,


How did the BorderLayout manager come up with eee -
this size for the button?
-
What are the factors the layout manage.r has to click me
consider?
I~ -

,j,
Why isn't it wider or taller? 1- - -

404 chapter 13
using swing

Watch what happens when we give


the button more characters•..

public void go() (


JFrame frame = new JFrame();
JButton button = new JButton("c1ick like you mean it");
!rame .getConcentPane() . a dd (Bo r de r La you t . EAST, button);
frame .setSize(200,200);
frame.setVisible(true);

o
o

oo

Since it's in the east


region of a border layout,
rll respect its preferred width. But
r don't care how tall it wants to be:
it's ganna be as tall as the frame,
because that's my policy.

eee -a --,

.
click like you mean II

r"

you are here ~ 405


border layout

Let's try a button in the NORTH region

public void go() (


J~rame frame = new JFrame();
.mutton button '" new .JButton ("There is no spoon ... ");
frame.getCohtentPane().add(BorderLayouL.~, button);
frame.setSize(200,200);
frame.setVisible(true);

Now let's make the button ask to be ~II!!,

How do we do that? The button is already as wide


as it can ever be-as wide as the frame. But we
can try to make it taller by giving it a bigger font.

pub Lf c void go () ( ~.\\ ~o'(t.~ t,\.e


JFrame frame = new JFrame () ; 'D\oll( ~O¥'\:. '01' .,.,.tJrl $~al.t.
JButton button = new .mutton ("Click This! ") ; ~ ... a"'t. -to a\\~t.i,~ht..
Font bigFont = new Font ("serif", Font. BOLD, 28); ~oY t,'nt'D\lt.tor-
button.aetFont(bigFont);
frame.getContentPane() .add(BorderLayout.NORTB, button);
frame.setSlze(200,200);
frame.setVisible(true);

406 chapter 13
using swing

I think rm getting it... if rm in eesr or


west, I get my preferred width but the
height is up to the layout manager. And
if rm in north or south, it's just the
opposite-I get my preferred height, but
But wltst happens
not width, in tlte center region?

The center region gets whatever's leftl


(except in one special case we'll look at later)

public void go ()
JFrame frame new JFrame();

JButton east new JButton("East");


JButton west new JButton("West H ) ;
JButton north = new JButc:.on("North");
JButton south = new JButton("South H ) ;
JButton center = new JButton("Center H ) ;

frame.getContentPane() .add(BorderLayout.&AST, east);


frarne.getContentPane() .add(BorderLayout.WEST, west);
frame.getContentPane() .add(BorderLayout.NORTH , north);
frame .gec:.ContentPane() .add (BorderLayout. SOUTH, south);
frame.getContentPane() .add(BorderLayout.CENTER, center) ;

frame.setsize(300,300);
frame. setVisible (t rue) ;
Le;e e =- ;;;;. ;;; ;.;;; -d
( North
!
~ei r----
e-, ~
IO~
),
West C~nl~r £an

1\ti
width·
aN:i
t.6. { South ~

~-----_J.

you are here ~ 407


flow layout

FlowLayout cares
about the flow of the
components: -
left to right, top to bottom, in
the order they were added.

Let's add a panel to the east region:

A JPanel's layout manager is FJowLayout, by default. Wnen we add


a panel to a frame, the size and placement of the panel is still
under the BorderLayout manager's control. But anytning inside the
panel (in other words, components added to the panel by calling
panel. add (aComponent») are under the panel's FfowLayout
manager's control. We'll start by putting an empty panel in the fl'"£lme's
east region, and on the next pages we'll add things to the panel.

import javax.8winq.*;
806 _..
import java.awt.·; -- --
public class Panel1

publio static void main (SuingIl llrgs) (


Panell qui: new Panel1();
qui. go () ;

public void go () (
JFrame frame :D new JFrame () ; ~Milkt. iht. pilPlt.1 ~yz so \lJt. tar. s
JPanel panel = new JPanel () ; Yih-.
.....
'.1 ' . 1 \
I"{; IS 0fI"Lllt. ;}...t.
ee
panel. setBackqround (Color. d&rkGray) i .
frame. getContantpane () . add (BorderLayout. EAST, panel);
frams.setsize(200,200)i
frame.setVisible(true) i

408 chapter 13
using swing

Let's add a button to the panel

public void go() {


Jframe frame = new Jframe();
JPanel panel = new JPanel(); th
aYlt:\ aYld add -tht:
panel.setBackground(Color.darkGray); Add t,hf ~ 1:.0
e Y Cll'le\' s la'fOl>t ...ar.d~('f"
Cll'le\ t.o t.'ne ~ya",e. -r-:~.!- a d t.ht: ~ya",e)s
JButton button'" new JButton ("shock me"); rHo...,) l-Ot'Ihols the '0)" hols -I:'ne yaYlel.
J ~ I t. n>d'l\d~t:Y (bcordty toOYl
panel.add{button); ~ ~ a~OI>
frame.getContentPane() .add(BorderLayout.EA$T, panel);

frame.setSize(250,200);
frame.setVisible(true);

00

controls controls ~

The frame's The panel's


8orderLayoutmanager FlowLayout manager

you are he re . 409


flow layout

What happens if we add TWO buttons


to the panel?
public void go ()
JFrame frame new JFrame();
JPanel panel new JPanel();
panel.setBackground(Color.darkGray);
-rw D'o...\:;\:P...s
JButton button = new JButton ("shock me"); ~ .,.jjy.e
JButton buttonTwo = new JButton("bliss"); V

panel. add (button) ; - ' - - add B


panel. add (buttonTwo) ; ~ OT» to thl!: rand
frame.getContentPane() . add (BorderLayout.EAST, panel);
frame.setSize(250,200);
frame.setVisible(true);

what we wanted: what we got:


» :uc .--=>

eee

~en your penCil


~L _ _ . •
If the code above were modified to the code below, Draw what you
what would the GUllook like? think the GUI would
look like If you ran
JButton button = new JButton("shock me"); the code to the left.
JButton buttonTwo = new JButton("bliss");
JButton buttonThree = new JBu tton("huh?H); (Then try ltl)
panel.add(button);
panel.add(buttonTwo);
panel.add(buttonThree);

410 chapter 13
using swing

[ J BoxLayout to the rescue!

o It keeps components
stacked, even if there's room
o~

c=::fl to put them side by side.


f- 0
Unlike FlowLayout, BoxLayout can force a
'new line' to make the components wrap to
the next line, even If there's room for them
to fit horizontally.

But now you'll have to change the panel's layout mancger from the
default FlowLayout to BoxLayout.

public void got) {


JFrame frame = new JFrame (l ; ...a,.a~C" to ~ a ~
JPanel panel = new JPanel () ; C\\a e-t\oIe \a'fO'l"t. t-
panel. setBackground (Color. darkGr:~iY\S~~ J 'rJo"..u~o~
panel.s8tLsyout(new BoxLayout(panel, BoxLayout.Y_AXIS»;

~Tn~ Bo~yovt toMb-ill k


JButton button =- new JButton ("shock me");
-th~ to"'POhblt if;s I ' huds to know
Jautton buttonTwo = new Jautt.on("bliss"); .ihd whilh d)(i! to tlY'F~ O\.lt (i,~" B.~ pal'ltl)
panel .add(button);
vertildl ~lH ~ we lASe Y_AXI~ +~ a
panel .add(buttonTwo);
frame.getContentPane() .add(BorderLayout.EAST, panel) ;
frame.setSize(250,200);
frame.setVisible(true);

e ee

you are here ~ 411


layout managers

Q: How come you can't add directly to a frame the way


you can to a panel? • Layout managers control the size and location of
components nested within other components.
• When you add a component toanother component
A : A JFrame Is speciaI because it's where the rubber (sometimes referred 10 as a background cornporent
meets the road In making something appear on the screen.
but that's not a technical distinction), the added
Whll e a II you r SWing components are pu re Java, a JFrame
has to connect to the underlyl ng OS In order to accessthe
component is controlled bythe layout manager ofthe
dl splay.Thin k of the content pane as a 100% pure Java layer background componenl
that sits on top of the JFra me. Or thi n k of it as thoug h JFrame • A layout manager asks components for their
is the window frame and the content pane Isthe...glass.You preferred size, before making a decision about
know, the window pane. And yo u ca n even swap the content the layout. Depending on the layout manager's
pane with your own JPanel,to make your JPanel the frame's policies, it might respect atl, some, or none ofthe
content pane, using,
component's wishes.
myFrama .•etcontantpane(myPanel);
• The BorderLayout manager lets you add a
component to one offive regions. You must specify
Q: can I change the layout manager of the frame? the region when you add the component, using the
What If I want the frame to use ftow Instead of border1 following syntax:
add (BorderLayout. EAST, panel);
• Wrth Bordertayout, components inthe north and
A:The easiest way to do this Is to make a panel, build south gettheir preferred heigh~ but not width.
the GUI the way you want In the panel, and then make that
Components In the east and west get their preferred
panel the frame's content pane using the code In the prevl-
ous answer (rather than using the default content pane).
width, but not height The component inthe center
gets whatever isleff over (unless you use pack () ).
• The pack() method Is like shrink-wrap for the
Q: What If I want a different preferred size? Is there a components; It uses the full preferred size ofthe
setSlzeO method for components1 center component, then determines the size ofthe
frame using the center as a starting point, building
the rest based on what's inthe other regions.
A : Yes, there Is a setSlzeO, but the layout managers will
Ignore It. There's a distinction between the preferredsize of • FlowLayout places components left to right. top to
the component and the size you wa nt It to be.The preferred bottom, In the order they were added, wrapping toa
size Is based on the size the component actually needs new line ofcomponents only when the components
(the component makes that decision for Itself). The layout won't fit horizontally.
manager calls the component's getPreferredSlzeO method,
• RowLayout gives components their preferred size in
and tho: method doesn't care If you've prevlously called
setSlzeO on the component.
both dimensions.
• BoxLayout lets you align components stacked
vertically, even If they could fit side-by-sida. Uke
Q:can't IJust put things where I want them? can I tum FlowLayout. BoxLayout uses the preferred size of
the layout managers off? the component inboth dimensions.
• BorderLayout isthe default layout manager for a
A:vep.on a component by component basis,you can call frame; FlowLayout Isthe default for a panel.
setLayout (null) and then It's up to you to hard-code • Ifyou want a panel to use something other than flow,
the exact screen locations and dimensions. In the long run, you have to call setLayout () on the panel.
though, It's almost always easier to use layout managers.

412 chapter 13
using swing

Playit1Q with Swittg colitpottettts


You've learned the basics of layout managers, so now let's try out a
few of the most common components: a text field , scrolling text area,
checkbox, and list, We won't show you the whole darn API for each of
these, just a few highlights to get you started.

JTextFleld
.8 6 6

A t 1.D y·rah.
W t.o\l>JI'I~1 ,,0 . dt'h ~
Constructors ~ W. ~af ts t'llt Y"'e~tyYtd 'HI
It: T'''~ (l.t'",,,
JText:F1&1d field % n_ JTex.tField(20); ~e ~.,rl ~'t\d.
J'TextField field: new JTAXtFi8ld(~Your nameff)i

How to use It

• Get text out of it


Systam.out.println(5eld.getTQXt());

• Put text in it
field . 1I8 t Text ("whatever") ;
field. lIetText (" \\) i \ ~t .~\e\d
" - - 'This t e.lI's

• Get an ActionEvent when the user VOlA l,dll alSo l'e~isk .f


presses return or enter rtally 'N.1l'1t iD htar a~t~iY evel'lh it yOlA
l/.1tt- P'r't:~s d kty. I every ti ...e the
fiald.addActionLiataner(myActionListener) i

• Select/Highlight the text in the field


fiald.aelectAll();

• Put the cursor back in the field (so the user


can just start typing)
field. requeatFocua () ;
you are here ~ 413
text area

JTextArea

Unlike JTextField, JTextArea can have more than one line of text. It
takes Q little configuration to make one, because it doesn't come out of
the box with scroll bars or line wrappi"9. To make a J'TextAr'e(] scroll, you
have to stick it in a ScroliPane. A ScroJiPane is an object that r'e(]11y loves
to scroll. and will take care of the text ereo's scrolli"9 needs. '- . \o..\)
JeY't'c6 nC\~
10 \,~ (~the Y'" ~~o. Ifj'o..\;,\,,)
~ l'S (~ -thC yrt
Constructor t 10 ""tal'S
r VJ ""ul'S VJ to ......
JTaxtArea taxt m new JTaxtArea(lO,20);

How to use It 6 ',IJC it &c~


J~~o\\?a~ 4". ~~ st;~o\\ dt'.
Mi~C a ~t It ~ ~,,~
• Make it have a vertical scroll bar only ~ U'llt a'ft.6
JSarollPane IIc:roller - ne. JSc:rollPane (taxt) ; Tell the stroll pal\t io ,
text.lIetLineWrap(true); ~ T",,"II 01\ line ~affi~ f
a ~ st\"ollba\" l&SC Ofty
sc:roller.aetvertiea1Sc:rol1BarPolicy(ScrollPaneConlitants .VERTlCAL SCROLLBAR AL~
IIcroller.set8orizonta1Sc:rol1BarPolicy(Sc:rollPaneConatants.BORIZONTAL_SCROLLBAR_NEVER);

• Append to the text that's in it


taxt.append("button cliaked H ) ;

• Select/Highlight the text in the field


taxt.lIelectAll();

• Put the cursor back in the field (so the user


can just start typing)
text.requelltFocua() ;

414 chapter 13
using swing

JTextArea example

import jaYaX.swing.*;
import java.art.*;
import java .art.event.*; "eee
-
~
,.,
~ ~ cHcJced .~
- cHcJced
but.ton ell eked
public class TaxtAreal implements ActionL~staner { z: -

JTextArea text;

public static void main (String [] &rqs) 0:-


~-~
TextAreal qui c new TextAreal();
qui .go () ;
} 1'= - :

public void go() (


r Just tUck It
~
JFrame frame - new JFrame();
JPanel panel = new JPanel () ;
JButton button::; new JButton("Just Click It");
button. addActionListener (this) ;
text::; new JTaxtArea(lO,20);
text.setLinewrap(true);

JScrollPane scrollar ~ new JScrollPane{taxt);


scroller.setVerticalScrolLBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AL~YS);
scrollar.setBorizontalScrollBarPolicy(ScrollPaneConstants.80RIZONTAL_SCROLLBAR_NEVER);

panel. add (scroller) ;

frame. qetContentpane (l . add (BorderLayout. CENTER, panel);


frame. qetContentpane () . add (BordarLayout. SOO'TB, button);

frame.setsize(350,300);
frame.setVisible(trlle);

public void actionPerformed(ActionEvent ev) ( """left I.h cu "._u_ (H ~~t.. eh


'. . . . . t ... ( \1~'CJ"ctl d ....-t. . (H
text.append("button clicked \n "); (ll....,..\O'Il"l lc........ l _ ( h ~ l

f~~l;~:=:;'~U~ ....t
i .., t\ I ~ '_ [ \ l o........, c\ t U.

I~t d
.' toI\ (a l c:\~ c- H ~~ teoI c.l t
new lihC: $0 B.c: w<J\-dsS . Ill" c:1~tOO'l [Hdl""'~ (ttf'\:

stpd'ra~ line: eatl L' L\ ~.o 0" a


b~ 1(~-:;':~=;l~;~:::::;1~ I
.k I) l;1",C: Ole: .
e/It ed. Other-wi~ B.
I ey'II 'rl/.n -togetha-.
n IS

you are here. 415


check box

there1atE}{l? "
JCheckBox OUUlD ~uesti9ns

Q: Aren't the layout manag-


ers just more trouble than they're
worth? If I have to go to all this
trouble, I might as well just hard-
code the size and coordinates for
where everything should go.

Constructor
JCheckBox check = new JCheckBox("Goes to 11"); A: Getting the exact layout
you want from a layout man-
ager can be a challenge. But think
about what the layout manager
How to use It
is really doing for you. Eventhe
seemingly simple task of figuring
• Listen for an item event (when it's selected or deselected) out where things should go on
check.addltemListener(this); the screen can be complex. For
example, the layout manager takes
care of keeping your components
from overlapping one another.
. . Handle the event (and find out whether or not it's selected) In other words, it knows how to
manage the spacing between
public void itemstateChanged(ItemEvent ev) components (and between the
String onOrOff = "off"; edge of the frame). Sure you can
if (check .isSelected(» onOrOff = "on"; do that yourself, but what happens
System.out.println( "Check box is " + onOrOff); if you want components to be
very tightly packed? You might get
them placed just right, by hand,
but that's only good for your JVM!
. , Select or deselect it in code Why? Because the components
can be slightly different from
check.setSelected(true); platform to platform, especially if
check .setSelected(false); they use the underlying platform's
native 'look and fee 1/, Subtle things
like the bevel of the buttons can
be different in such a way that
components that line up neatly
on one platform suddenly squish
together on another.
And we're still not at the really Big
Thing that layout managers do.
Think about what happens when
the user resizesthe window! Or
your GUI is dynamic, where com-
ponents come and go. If you had
to keep track of re-Iaying out all
the components every time there 's
a change in the size or contents of
a background component...yikes!

416 chapter 13
using swing

~List

Constructor
String [] H.atEntries '" ("a..lpha", "beta", \'ga:nmta", "delta",
"apailon", "zeta", "eta H , "theta "I;

list'" new JLlst(liatEntrie.);

How to use It

• Make it have a vertical scrollbar


JSerollPane acroller '" new JScrolIPane(liat) ;
scroller.setVerticalScrol~Poliey(ScroIIPaneConstanta.VERTlCAL_SCROLL8AR_ALMAYS);
acroller.setaorizontalScrollBarPolicy(ScrollPan8Constants.HORIZONTAL_SCROLLBAR_NEVER);

panel.add(acroller);

Set the number of lines to show before scrolling


liat.setVisibleRowCount(4);

• Restrict the user to selecting only ONE thing at a time


list.setselectionMode(ListSeleotioDModel.SrNGLE_SELECTION);

Register for list selection events


list.addListSelectionListenar(this);
y~\\ ¥*- t.ne e\la.'t.L TWIC~ J '10\> ooY\'t.
• Handle events (find out which thing in the list was selected~ / fllt. j" this i~ test.
public void va.lueChanqed (ListselectionEvent lse) (E;" .
if( Ilse.getValueIsAdjullting()) ( ~
String selecUon ." (String) list. getSelectedValue 0 ; ~eiSdttudV~lueO ad:. I~
SysteJD. out.println (lteleotion) ; _1. ~"
rcwn.s a" Objett, Alist i 'f.
li...iud to OYII"/ oL. •
~U"'''5 0
S:.
b':,)etu.

you are here. 417


Code Kitchen

This part's optional We're ~ing the lull BeatBox, GUI


and all In the Saving Objects chapter, we'll learn how to
save and restore drum patterns. Finally in the networlung
I

chapter (Mak a Connedionl, we'U turn the BeatBox into a


wor~ing chat client.
418 chapter 13
using swing

Makit1Q the JeatJox


This is the full code listing for this version of the BeatBox, with buttons for starting,
stopping, and changing the tempo. The code listing is complete, and fully-
annotated, but here's the overview:

• Build a GUI that has 256 checkboxes (JCheckBox) that start out
unchecked, 16 labels (JLabel) for the instrument names, and four
buttons.

• Register an ActionListener for each of the four buttons. We don't


need listeners for the individual checkboxes, because we aren't
trying to change the pattern sound dynamically (i.e. as soon as the
user checks a box). Instead, we wait until the user hits the 'start'
button, and then walk through all 256 checkboxes to get their state
and make a MIDI track.

• Set-up the MIDI system (you've done this before) including getting
a Sequencer, making a Sequence, and creating a track. We are using
a sequencer method that's new to Java 5.0, setLoopCount( ). This
method allows you to specify how many times you want a sequence
to loop. We're also using the sequence's tempo factor to adjust the
tempo up or down, and maintain the new tempo from one iteration of
the loop to the next.

• When the user hits 'start', the real action begins. The event-handling
method for the 'start' button calls the buildTrackAndStartO method.
In that method, we walk through all 256 checkboxes (one row at
a time, a single instrument across all 16 beats) to get their state,
then use the information to build a MIDI track (using the handy
makeEventO method we used in the previous chapter). Once the track
is built, we start the sequencer, which keeps playing (because we're
looping it) until the user hits 'stop'.

you are here ~ 419


BeatBox code

import java.awt.*;
import javax.swing .·;
import j avax. sound . midi. . * ;
import java.util.*;
import java.awt.event.*;

public elass BeatBox {

JPanel mainPanel;
ArrayList<JChecltBox.>
Sequencer sequencer;
Sequen~e sequence;
Track track;
JFrame theFrame ; ~ The'S( dre ~e I\d"'CS ~ the i~""LlftIents, dS a Shi"
'" an-dY, to'<" bl.tildi"~ t.hc qUI labels (on eJth 'row) ~
String [] instrumentNames =
("Bass Drum", "Closed Hi-Bat",
"Open Hi-Hat","Acoustic Snare", "Crash Cymbal", "Band Clap",
"H1gh Tom", "Hi Bongo", "Maxacas", "Whistle", "Low Conga",
"Cowbell", "Vibraslap", "Low-mid Tom", "High Aqoqo" ,
"0pQn Hi Conga");
int[] instruments : (35,42,46,38,49,39,50,60,70,72,64,56,59,47,67,63);

public static void main (String[] args) {


new BestBox2 () .buildGUI (J ;

checkboxList:: new ArrayList<JCheckBox.>() ;


Box buttonBox: new Box(BoxLayout.Y_AXIS);

JButton start c new JButton("Start");


start.addActionListener(new MyStartListener());
buttonBox.add(start) ;

JSutton stop: new JButton("Stop") ;


stop.addActionListener(naw MyStopListaner(»;
buttonBox. add (stop) ;

JButton upTempo : new JButton("Tempo CpU);


upTempo.addActionListener(new MyUpTempoListener());
buttonBox,add(upTempo);

JSutton downTempo :: new JButton ("Tempo Down");

420 chapter 13
using swing

downTempo . addActionLi s tener (n_ MyDownTempoListener () ) ;


buttonBox.add(dovnTempo);

Box nameBox = new Box (80xLayou t. Y_AX! S) ;


for (int i = 0; i < 16; i++) {
nameBox .add(new Label (i.nst..rumentNa.mes [i]» ;

background . add (BorderLayout. EAST, but tonBox) ;


background . add (80rd.erLayout. WEST, namaBox);

theFrame .getcontentpane() . add (background) ;

GridLayout grid = new GridLayout(16,16) ;


grid. setVgap (1) ;
grid. setHqap (2) ;
mainPanel = new JPanel (grid) ;
background. add (BorcierLayou t. CEN"l'ER, mainPanel);

for (int i = 0; i < 256; i++) {


JCheckBox c = new JCheckBox();
c.setselected(false);
checkboxList .add(c);
mainPanel.add(c) ;
II end loop

setOpMidi();

theFrame.setBounds(50,50,300,300);
th9Frame.pac:k();
theFrama.setVisible(true);
I I elose method

public void ••t~~() {


tz:y (
sequencer = MidiSystem..getsequencer () ;
sequencer. apan () ;
sequence = n_ Sequence (Sequence.PPQ,4) ;
track = eequence.creat8Track();
sequencer.aetTampolnBPH(120);

} catah(Exception e) (e.printStaakTrace();}
II clos9 method

you are here • 421


BeatBox code

sequence .deleteTrack(track) ;
track = sequence.createTrack();

for (int i = 0; i < 16; i++)


trackList = new int[16];

int key = instruments [i); ~

= 0; j < 16; j++ ) { ~ Do this ~OV" eath ~ the BE.ATS ~OV" this YOW

3
for (int j

JCheckBox jc = (JCheckBox) checkboxList.get(j + (16*i» ;


if ( jc.isSelected(» (
trackList[j) = key; r
else { Is t.he thetkbo"l. at. t.his beat. sdett.ed? I~ yes, fIAt.
trackList [j) = 0; the key vall.le in this slot in the ayyay (the slot that.
} Ye~esents this beaV. Otheywise, the inshWl'lent is
I I close inner loop NOT slAffosed to flay at this beat, so set it. to Uyo·

makeTracks (trackList) ; -,.-..::----- roY this i\'\StYWI'Ient., and ~OV" all Ib beats,
track. add (makeEvent (176,1,127,0,16) ) ; ",ake eve"ts and add the", to the hade
II close outer
~ We always want to ",alce SlAye that H,tye IS an event at
track. add (makeEvent (192,9,1,0,15) ) ; beat. IE. (it ~oes 0 to ,'S). OH,tywise, the 'BeatHo"l. ",i~ht
try ( not ~o the .flAil Ib beats be+oYe it staYts ovty·
sequencer.setSequence(sequence);
sequencer .setLoopCount(sequencer.LOOP_CONTINUOUSLY);
sequencer.start();
sequencer.setTempoInBPM(120) ;
} catch(Exception e) {e.printStackTrace();}
II close buildTrackAndStart method

public class ~!iI~~:£!DI~fM implements ActionListener


public void actionPerformed(ActionEvent a) (
buildTrackAndStart();
}
II close inner class

422 ch a pter 13
using swing

public class (mJ.HRa,~g~ implements ActionListener


public void actionPerformed(ActionEvent a) (
sequencer.stop() ;
}
II close inner class
The otheto il'l l'l eto dass
public class r~EtItl=i!iij~jimplements ActionListener listel'letos tOt" the bl<ttol'lS
public void actionPerformed(ActionEvent a) (
float tempoFactor = sequencer.getTempoFactor() ;
sequencer.setTempoFactor«float) (tempoFactor * 1.03»;
}
II close inner class
The TeMpo Fattoto stales
p ublic class "'"".c"'!
:m% .",~,'.'T): : " *9i':mr':~iil
w,~,.,."iI.,,,., ,, ,,,, ,.A' implements ActionListener the se,\\I.f:\'\te\'"'s teMPO by
public void actionPerformed(ActionEvent a) ( the tatk pY'o\fideGl. The
float tempoFactor = sequencer.getTempoFactor(); ~ deta",lt is J.O, so we'toe
sequencer.setTempoFactor«float) (tempoFactor * . 97 » ; adjlASti\'\5 +/- 3'0 pe\'"
} diek.
} II close inner class

public void lllll.ll~(int[] list)


~
for (int i = 0; i < 16; i++) (
int key = list[i];
i f (key != 0) {
track.add(makeEvent(144,9,key, 100, ~) Make the NOT~ ON a\'\d
); L
track.add(makeEvent(128,9,key, 100, 1+1»; ) NOT oFF e'le\'\ts. a\'\d
add thew> to the T \'"atk.

public MidiEvent ~ ~,ij( int comd, int chan, int one, int two, int tick) {
MidiEvent event = null ;
try {
ShortMessage a = new ShortMessage();
a. setMessage (comd, chan, one, two);
event = new MidiEvent(a, tick);

catch(Exception e) {e.printStackTrace();
return event;

} II close class

you are here. 423


exercise: Which Layout?

Which code goes with


which layout?
Five of the slx screens below were made from one
of the code fragments on the opposite page. Match
each of the five code fragments with the layout that
fragment would produce.

o 6 SC

lesuJI

~ .

• o (
ee
wala ri

G 606
tesuJi

le5uj l

424 chapt er 13
using swing

code Fragments
JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel. setBackground (Color. darkGray) ;
JButton button = new JButton(~tesuji") ;
JButton buttonTwo = new JButton(~watari") ;
frame.getContentPane() .add(BorderLayout.NORTH,panel);
panel.add(buttonTwo);
frame.getContentPane() .add(BorderLayout.CENTER,button);

JFrame frame = new JFrame() ;


JPanel panel = new JPanel();
panel.setBackground(Color.darkGray);
JButton button = new JButton(~tesuji");
JButton buttonTwo = new JButton(~watari") ;
panel.add(buttonTwo) ;
frame.getContentPane() .add(BorderLayout.CENTER,button);
frame.getContentPane() . add (BorderLayout.EAST, panel);

JFrame frame = new JFrame();


G JPanel panel =
new JPanel () ;
panel.setBackground(Color.darkGray);
JButton button = new JButton(~tesuji");
JButton buttonTwo = new JButton(~watari") ;
panel.add(buttonTwo);
frame.getContentPane() .add(BorderLayout.CENTER,button);

e JFrame frame = new JFrame();


JPanel panel = new JPanel () ;
panel. setBackground (Color. darkGray) ;
JButton button = new JButton(~tesuji");
JButton buttonTwo = new JButton(~watari") ;
panel. add (button) ;
frame.getContentPane() .add(BorderLayout.NORTH,buttonTwo) ;
frame.getContentPane() . add (BorderLayout. EAST, panel);

JFrame frame = new JFrame();


JPanel panel = new JPanel() ;
panel. setBackground (Color.darkGray) ;
JButton button = new JButton(~tesuji");
JButton buttonTwo = new JButton(~watari");
frame.getContentPane() . add (BorderLayout. SOUTH ,panel) ;
panel.add(buttonTwo) ;
frame.getContentPane() . add (BorderLayout.NORTH ,button) ;

you are here; 425


puzzle: crossword

GtJI-Or~ss ,.0
You can do It.

AaOS5 17. Shake It baby Down 13. Manager's rules


1. Artist's sandbox 21. Lots to say 2. Swing's dad 14. Source'sbehavior
4. Border's catchall 23. Choose many 3. Frame's purview 15. Borderby default
5. Java look 25. Button's pal 5. Help's home 18. User's behavior
9. Genericwalter 26. Homeof 6. Morefun than text 19. Inner's squeeze
actionPerformed 7. Componentslang
11. A happening 20. Backstage widget
12.Apply a widget 8. Romulin command 22. Maclook
15.JPanel's default 9. Arrange 24. Border's right
16. Polymorphictest 10. Border's top

426 chapter 1 3
using swing

~ExerciSe Solutions

~ JFrame frame .. Dew JFrame();


V' JPanel panel C Dew JPanel () ;
paDel.setBackground(Color .darkGray) ;
JButtOD button = Dew JButton("tesuji H ) ;
JButton buttonTwo .. new JButton (".auri N
) ;

panel.add(buttonTwo) ;
frame.getCoDtentPane() . add (BorderLayout. CENTER ,button) ;

A JFrame frame = Dew JFrame () ;


~ JPanel panel '" new JPanel Cl ;
panel.setBaokqround(Color.darkGray) ;
JButton button .. new JButton("tesuji N ) ;
JButton buttonTwo .. new JButton("wauri N
) ;

frame .getContentPane() .add(BordarLayout.NORTS,panel);


panel. add (buttonTwo) ;
frame .qetContentPane() .add(BorderLayout.CENTER,button);

~ JFrame frame = new JFrame () ;


..., JPanel panel" new JPanel{);
panel.setBaekqround(Color.darkGray) ;
JButton button = new JButton( "tesuji H
) ;

JButton buttODTwo = new JButton("watari") ;


frame.qetContentPane() .add(BordarLayout.SOUTH,panel);
panel.add(buttonTwo) ;
frame. getContantpane () .add (BorderLayout. NORTH, button) ;

o ~e e o .......
JFrame frame '" n_ JYram. () ;
JPanel panel = new JPanel () ;
panel.aetBackground(Color.darkGray);
JButtoD button'" new JButton("tesuji");
JButton buttonTwo '" new JButton("watari H ) :
panel .add(button):
frame.qetConbentpane() .addlBordarLayout.NORTH,buttonTwo):
frame.qetContentpane() .add(BorderLayout .EAST, panel);

JFrame frame = new JFr_ () :


O• JPanel panel .. n_ JPanel () :
panel.a8tBackqround(Color .darkGray);
JButton button = new JButton("taauji H ) ;
JButton buttonTvo CI new JButton ("watari ") ;
panel . add (buttonTwo) :
framo. qlltContantpane Cl • add (BordllLLayout . CENTE:R,button) ;
frame . getContentPane () .addl80rderLayout.EAST, panel);

you are here ~ 427


puzzle Answers
eaI-Or~ss z.o
14 serialization and file I/O

Saving Objects

Objects can be flattened and inflated. Objects have state and behavior .
Behavior lives in the dOH, but state lives within each ind ividual object. So what happens when
it 's time to savethe state of an object? If you 're writing a game, you're gonna need a Savel
Restore Game feature . If you 're writing an app that creates charts, you're gonna need a Savel
Open File feature. If your program needs to save state/you can do It the hard way, interrogating
each object, then painstakingly writing the value of each instance variable to a file, In a
format you create. Or, you can do Itthe easy 00 way-you simply freeze-dry/flatten/persistJ
dehydrate the object itself, and reconstltute/lnflate/restore/rehydrate It to get it back. But you'll
still have to do it the hard way sometimes, especially when the file your app saves has to be read
by some other non-Java application, so we'll look at both In this chapter.

this Is a new ch ap ter 429


saving objects

Capture the feat

You have lots of options for how to save the state of


yourJava program. and what you choose will probably
depend on how you plan to use the saved state. Here
are the options we'll be looking at in this chapter.

If your data will be used by only the Java


program that generated It:

~ Use ~erializQtion

Write 0 tile that holds flattened (serialized)


objects. Then have your program read the
serialized objects from the file and inflate them
back into living, breathing, heap-inhabiting objects.

If your data will be used by other programs:

@ Write a plain text file


-
Write a tile. with delimiters that other programs can parse,
For example, a tab-delimited file that a spreadsheet or
database application can USe.

These aren't the only options, of course. You can save data in any
format you choose. Instead of writing characters, for example,
you can write your data as bytes. Or you can write out any kind
ofJava primitive as a Java primitive-there are methods to write
ints, longs. booleans, etc. BUt regardless of the method you use,
the fundamental lIO techniques are pretty much the same:
write some data to something, and usually that something is either
a file on disk or a stream coming from a network connection.
Reading the data is the same process in reverse: read some data
from either a file on disk or a network connection. And of course
everything we talk about in this part is for times when you aren't
using an actual database.
430 ch apter 14
serialization and file 1/0

Savl"Q State
Imagine you have a program, say, a fantasy
adventure game, that takes more than one
session to complete. As the game progTesses,
characters in the game become stronger, weaker,
smarter, etc.• and gather and use (and lose) Imagine you
weapons. You don't want to start from scratch l1a-ve t 1 r

each time you launch the game-it took you .1 m"ee game
forever to get your characters in top shape for Cllaract
a spectacular battle . So. you need a way to save ers to sal'e...
GameCharacter
the state of the characters, and a way to restore
the state when you resume the game. And since 11'1 power
you're also the game programmer, you want the String type
whole save and restore thing to be as easy (and WeaponD weapons
foolproof) as possible.
gelWeaponO
usaWeaponO
IncreasePower()
• Option one II more
Write the three serialized
character objects to a file
Create a file and write three serialized
character objects. The file won't make
sense if you try to read it as text:
-l.uGa.meoharaot
-"'~ava/1anIJ
8t:rIDSi [weapoQt Nava/lang/
8t:r'lDS;QBtlfUrl:I4java.Jant.8t:rln4;..uvA.
i{Gzptbowt8wordtdUSUq- nt'l'rolluq-tb
are h.Ilndabig IIDq- ztMagloiaDuq-tepe
u.tInvialbWty

• Option two
Write a plain text file
Create a file and write three Jines of text.
one per character, separating the pieces
of state with commas:

80.mt,bow, lJWQrcl,dlUt
8OO,Troll,bare banlb,big ur:
18O,Megictl n ,ape!h,lnviaibUity

you are here ~ 431


saving objects

Wrlti"Q a serialized object to afile


Here are the steps for serializing (saving) an object Don't bother
memorizing all this; we'l1 go into more detail later in this chapter.

o Make a FileOutputStream

Wrlt~ the obj~ct r ..I 'o~h.1Yat-tc--


- lL L' to L yt:-t&fY\UU ..I
Uv vee
'a\"~ Ult: ODjt: ~ dl'lU
os. writeObject (characterOne) i it:---/.
O:~, ~nayad:.t.yT'fIo, il~d ~nil"'~~",c,~"'''. I
os. wri teObject (characterTwo); ~ ,./l'+tt-s thCJ'II to tnt: ~11t: N1~
oB.writeObject(characterThree); ~

432 chapter 14
serialization and file I/O

Pata lMoves itt streatMs frotM ot1e place to at1other.


CO"t1ectio"
strealMs represe)tt
a eOt1t1ectlot1
toa source or
destlt1aflot1 (file,
socket etc.) while

-
chal" streatMs
cat1't oot1"ecf Ot1
their OW" 3"d tMust
be chal"ed toa
cot1t1ectfo" dna",.

The java I/O API has amnection streams, that represent connections to destinations and
sources such as files or network sockets, and chain streams that work only if chained to
other streams.
Often, it takes at least two streams hooked together to do something useful-one to
represent the connection and another to call methods on. \\Thy two? Because connection
streams are usually too low-level. FileOutputStream (a connection stream), for example,
has methods for writing byles. But we don 't want to write byusl We want to write objects, so
we need a higher-level chain stream.
OK, then why not have just a single stream that does exactly what you want? One that lets
you write objects but underneath converts them to bytes? Think good 00. Each class
does one thing well. File OurpurStreams write bytes to a file. ObjectOurputStreams turn
objects into data that can be written to a stream. So we make a FileOutputStream that lets
us write to a file, and we hook an ObjectOutputStrearn (a chain stream) on the end of it.
When we call writeObject() on the ObjectOutputStream. the object gets pumped into the
stream and then moves to the FileOutputStream where it ultimately gets written as bytes
to a file.
The ability to mix and match different combinations of connection and chain streams
gives you tremendous flexibilityl If you were forced to use only a singlestream class, you'd
be at the mercy of the API designers. hoping they'd thought of everythitlgyou might ever
want to do. But with chaining, you can patch together your own custom chains.

01101001
object is flattened (serialized) object is written as bytes to
01101110
011010010110111001 01
is written to is chained to

ObjectOutput Streom FileOutputStream File


(a choin stream) (a connection stream)
you are he re ~ 433
serialized objects

What really happens to a., object


whet' itl serialized?

o Object on the heap G Object serialized

Objects on the. heap have state-the Serialized objects save the values
value of the object's instance of the instance variables. so that
variables. These values make one an identical instance (object) can be
instance of a class different from brought back to life on the heap.
another instance of the same class.

00100101

01000110

Foo myFoo = new Foo();


myFoo .setwidth(37);
myFoo.setBeight(70);

434 chapter 14
serlallzatlon and file I/O

-
'ut what exactly IS att object~ state?
What needs to be saved?
Now it starts to get interesting. Easy enough to save the primitive
values 37 and 70. But what if an obj ect has an instance variable
that's an object reference? What about an object that has five
instance variables that are object references? What if those object
instance variables themselves have instance variables?
Think about it. What part of an object is potentially unique?
Imagine what needs to be restored in order to get an object that's
identical to the one that was saved . It will have a different memory
location. of course. but we don't care about that, All we care about
is that out there on the heap. we'll get an object that has the same
state the object had when it was saved .

Vi!iiJlj1 Iraill Barbell


What has to happen for the Car The Car object has two
object to be saved in such a way Instance variables that
that It can be restored back to its reference two other
original state? objects.

Think of what-and how-you


might need to save the Car.

And what happens if an Engine


object has a reference to a
Carburator7 And what's inside the
nre 0 array object?

What doe8 It take to


save a Car object?

you are here. 435


serialized objects

When an object is serialized, all the objects


it refers to from Instance variables are also
serialized. And all the objects those objects Serialization saves the
refer to are serialized. And all the objects those
entire object grapb..
objects refer to are serialized••• and the best
part is, it happens automaticallyl All objects reterenced
This Kennel object has a reference to a Dog [] array object. The by instance variables,
Dog [] holds references to two Dog objects. Each Dog object holds starting with the
a reference to a String and a Collar object. The String objects
have a collection of characters and the Collar objects have an into
object being serialized.
When you save the Kennel, all of this ;s savedl
~ -

/\
~9[ ) arrcri o'o~
·l:-

436 chapter 14
serialization and file 110

If you want your class to be serializable,


itMpletMet1t Serializable
The Serializable interface is known as a marker-or tag interface,
because the interface doesn't have any methods to implement. Its
sole purpose is to announce that the class implementing it is, well,
serializable. In other words, objects of that type are saveable through
the serialization mechanism. Ifany superclass of a class is serializable,
the subclass is automatically serializable even if the subclass doesn't
explicitly declare implements Serializable. (This is how interfaces always
work. If your superclass "IS-A" Serializable, you are too). MIASI i",y\c",e'llt.
~ ~"eY O;,ot.s 'neY c r '\ t. Yu.f\t.i",c,
objectOUtputStream. wri teObject (myBox) ; ~ 'h\C t:J( it. ...i\\ -tal a
Sey\a\\~

, ' lhc ' a'la,io yat.\l.aO;,C. so


~'~\)\t 'S I'll" ,)
,
import java. io. *; ~ SeYli e..d t.'nt i""'y~'
'1011' 'II ..
public class Box implements Serializable
......... ~ ../

public void setWidth (int w)


width = w;

public void setHeight(int h}


height = h;

public static void main (String[] args) { ))

d \\~oo,seY
=
Box myBox new Box() ; l to i ~i\C YId.,.,.C I
COY\'IItt.". ~ 'It. dot.s,", t. ",i
¥.e a
myBox.setWidth(50};
myBox.setHeight(20); 10 lL
ovtV'abo"s t.a" "nYO'" eue...l.io\llS.!
r- r .t. e'Jl.Ists· \ d \\~oo·seY" .
i"l' I
1 I "c'" ~i\t YId"'c
try { ~
FileoutputStream fs = new FileOUtputStream("foo.ser") ;
ObjectOUtputStream os = new ObjectOUtputStream(fs);
os.writeObject(myBox); ~ Make ah Ob'etto
os. close () ; ......... thaihed to :J "tp"tstrea",
catch (Exception ex) { the tOhhettioh st
ex.printSt&ckTrace(); Tell it to W\-'te 1 rea""
I l::he objett.

you are here. 437


serialized objects

Serialization is all or nothing.


Can you imagine what would
happen If some of the object's
state didn't save correctly? Eeewww! That
creeps me out just thinking
about itl Like, what if a Dog comes
back with rIO weight. Or no ears. Or
the collar comes back size 3 instead
of 30 . That just can't be allowedl

Either the entire


object graph is
serialized correctly
or serialization fails.

You can't serialize


a Pond object if
import java.io .*; its Duck instance
~ POI'IO obj~eL ea" b~ so-ializ..ed. variable refuses to
public class Pond implements Serializable (
be senallzed (by
" POl'ld has ont 'IN taTlee
private Duck duck = new Duck(); ~ CIa ,.. D Ie. not implementing
va~iable, a vl. ,
Seriafizable).
public static void llIain (Strinq[] arqs) {
Pond myPond =
new Pond();
try (
FileOutputstreAm fs : new FileOUtputStream( "Pond.'ser");
ObjectOUtputStream os : new ObjeotOutputStream (fs) ;
. ..,e--. Wh
os . wr i t e Ob ) 8 c t (myPo n d ) ; . bl.yo.. . so-ia'i~ ""yPond ( P
os . close () ; obJuV, ih Dlotk i>\lU a ol'ld
aui:o-....a tit...i II c1.- . I'I~~ variable
catch(Exception ex) ( y 3 't-\ serlall~d. . PO'PIO:
ex .printStackTrace() ;
to YWI ~t ",ai" I" dass

438 ch ap te r 14
serialization and file 110

It's hopeless,
then? I'm completely
screwed if the idiot who
wrote the class for my instance
variable forgot to make it
Serializable?

Mark an Instance variable as transient


If It can't (or shouldn't) be saved. -
If you want an instance variable to be skipped by the
serialization process, mark the variable with the transient
keyword.
• import java.net.*:
. t !o4i'r' "Otil'C. ~ class Chat implements Serializable {
b-a.,.s~~iS ~aV"\a'o\tl O~~Il\~t.)I~ transient Strinq currentID;
sa"t v ' . 'I>S~ n.'" J ---
~V"ia\i-z.abO"f\,~
~ Strinq userNamej

lI..SC'rNa....e variable / / more code


will be saved as pari }
o.f ~t. obJt.d:'s st.dte
dUY"'9 st.\"laliz.aiiol'l.

lfyou have an instance variable that can't be saved because


it isn't serializable, you can mark that variable with the
transient keyword and the serialization process will skip right
over it.
So why would a variable not be serializable? It could be
that the class designer simply /ClTgot to make the class
implement Serializable, Or it might be because the object
relies on runtime-specific information that simply can't be
saved. Although most things in the java class libraries are
serializable, you can't save things like network connections,
threads, or file objects. They're all dependent on (and
specific to) a particular runtime 'experience'. In other words,
they're instantiated in a way that's unique to a particular run
of yoor program, on a particular platform, in a particular
JVM. Once the program shuts down, there's no way to bring
those things back to life in any meaningful way; they have to
be created from scratch each time.
you are here ~ 439
serialized objects

therelm-~?
DUmb ~uest19n8

Q: If serialization is so important,
why isn't it the default for all classes?
A: Yes! If the class itself is
extendable (i.e. not final), you can
as null, regardless of the value it had
at the time it was saved.That means
the entire object graph connected to
Why doesn't class Object implement make a serializable subclass,and just that particular instance variable won't
Serializable, and then all subclasses substitute the subclass everywhere be saved.This could be bad, obviously,
will be automatically Serializable. your code is expecting the superclass because you probably need a non-null
type. (Remember, polymorphism value for that variable.

A: Even though most classeswill,


and should, implement Serializable,
allows this.) Which brings up another
interesting issue: what does it mean if
the superclass is not serializable?
You have two options:
1) When the object is brought back,
you always have a choice. And you reinitialize that null instance variable
must make a conscious decision on back to some default state. This
a c1ass-by-c1ass basis,for each class Q: You brought it up: what does it works if your deserialized object isn't
you design, to 'enable' serialization mean to have a serializable subclass dependent on a particular value for
by implementing Serializable. of a non-serializable superclass? that transient variable. In other words,
First of all, if serialization were the it might be important that the Dog
default, how would you turn it off?
Interfaces indicate functionality, not
a lack of functionality, so the model
A: First we have to look at what
happens when a class is deserialized,
have a Collar, but perhaps all Collar
objects are the same so it doesn't
matter if you give the resurrected Dog
of polymorphism wouldn't work (we'll talk-about that on the next few a brand new Collar; nobody will know
correctly if you had to say/implements pages). In a nutshell, when an object the difference.
NonSerializable"to tell the world that is deserialized and its superclass is not 2) If the value of the transient variable
you cannot be saved. serializable, the superclass constructor does matter (say, if the color and design
will run just as though a new object of of the transient Collar are unique for
that type were being created. If there's each Dog) then you need to save the
no decent reason for a class to not
Q: Why would I ever write a class be serializable, making a serializable
key values of the Collar and use them
when the Dog is brought back to
that wasn't serializable? subclass might be a good solution. essentially re-create a brand new Collar
that's identical to the original.

A: There are very few reasons, but


you might, for example, have a security
Q: Whoall just realized
something big •••if you make a Q: What happens if two objects in
issue where you don't want a password variable 'transient~this means the the object graph are the same object?
object stored. Or you might have an variable's value is skipped over Like, if you have two different Cat
object that makes no sense to save, during serialization. Then what objects in the Kennel, but both Cats
because its key instance variables are happens to it? We solve the problem have a reference to the same Owner
themselves not serializable, so there's of having a non-serializable instance object. Does the Owner get saved
no useful way for you to make your variable by making the instance twice? I'm hoping not.
class serializable. variable transient, but don't we NEED
that variable when the object is
brought back to life? In other words,
isn't the whole point of serialization
A: Excellent question! Serialization
is smart enough to know when two
Q: If a class I'm using isn't to preserve an object's state? objects in the graph are the same.In
serializable, but there's no good that case,only one of the objects is
reason (except that the designer just
forgot or was stupid), can I subclass
the 'bad' class and make the subclass
A: Yes, this is an issue,but
fortunately there's a solution. If you
saved,and during deserialization, any
references to that single object are
restored.
serializable? serialize an object, a transient reference
instance variable will be brought back

440 cha pte r 14


serlallzatJon and file 1/0

Peserializatiot1= restorit1Q att object serializ.ed


The whole point of serializing an object is so that you can
restore it back to its original state at some later date, in a
J,.
different 'run' of theJVM (which might not even be the same
JVM that was running at the time the object was serialized).
Deserialization is a lot like serialization in reverse.

o Make a FilelnputStreQtn
FilelnputStream fileStream = new

e ~ the objects
Object one = os.readObject();
Object two = os.readObject();
Object three = os.readObject();

e -cast the objects

you are here, 441


deserlallzlng objects

What happe.,s durhtg deserializatio.,?


When an object is deserialized, thejVM attempts to bring
the object back to life by making a new object on the heap
that has the same state the serialized object had at the time it
was serialized. Well, except for the transient variables, which · . r ~e JVM
come back either null (for object references) or as default .\\ ~'(O-.l ell' eCJW:I~
primitive values. \his stty -.II \ d ~e dass.
- :t ~\"d'" ea

class is found and loaded, saved


01101001 object is read as bytes instance variables reassigned

01101110 __- - - - ~ 011010010110111001


is read by is chained to
01
FiJeInputStream ObjectInputStream Object
(0 connection stream) (a chain stream)
File

o The object is read from the stream.


e The determines (through stored with
JVM info
the serialized object) the object's class type.

The JVM attempts t? find and load the ob-


ject's class. If the JVM can't find and/or load
the class, the JVM throws an exception and
the deserialization fails .

A new object is given space on the heap, but


the serIalized obJeds constructor does
NOT runl Obviously, if the constructor ran, it
would restore the state of the object back
to its original 'new' state, and that's not what
we wont. We want the object to be restored
to the state it had when it was serialized, not
when it was first created.

442 chapter 14
serialization and file I/O

G If the object has a non-serializable class


somewhere up its inheritance tree, the
constructor for that non-serializable class
will run along with any constructors above
that (even if they're serializable). Once the
constructor chaining begins, you can't stop it,
which means all superclasses, beginning with
the first non-serializable one, will reinitialize
their state.

CD The object's instance variables are given the


values from the serialized state. Transient
variables are given a value of null for object
references and defaults (0, false , etc.) for
primitives.

:t1ere1lU'H ? 0
DUmb ~uestl9n8
argument, and if the JVM receiving the call doesn't have
Q: Why doesn't the class get saved as part of the ob" the class,it can use the URl to fetch the class from the
ject? That way you don't have the problem with whether network and load it, all automatically. (We'll talk about RMI
the class can be found. in chapter 17.)

A: Sure,they could have made serialization work that


way. But what a tremendous waste and overhead. And
Q: What about static variables? Are they serialized?
while it might not be such a hardship when you're using
serialization to write objects to a file on a local hard drive,
serialization is also used to send objects over a network
A: Nope. Remember, static means "one per class"not
"one per object" Static variables are not saved, and when an
connection. If a class was bundled with each serialized object is deserialized, it will have whatever static variable
(shippable) object, bandwidth would become a much larger its class currentlyhas.The moral : don't make serializable ob-
problem than it already is. jects dependent on a dynamically-changing static variable!
It might not be the same when the object comes back.
For objects serialized to ship over a network, though, there
actually is a mechanism where the serialized object can be
'stamped' with a URl for where its class can be found. This
is used in Java's Remote Method Invocation (RMI) so that
you can send a serialized object as part of, say, a method

you are here ~ 443


serialization example

Savit1g at1d restorit1g the gattte characters


import java.io.*;

public class GameSaverTest { Make sow-t tna~atte'rt-· ·


public static void main(String(] axgs} {
GameCharacter one = new GameCharacter(50, "Elf" , new Strinq{] ("bow", "sword", "dust"});
=
GameCharacter two new GameCha.racter (200, "Troll", new String! 1 {"bare hands" J "big ax"}) ;
GameCharacter three =
new GameCharacter(120, "Magician", new String[l ("spells", "invisibility"}) ;

/ / imagine code that does things with the characters that might change their state values

try {
ObjectOutputStream 09 =new ObjectOutputstream (new Fileoutputstream ("Game. ser") ) ;
os.writeObject(one) ;
os.writeQbject(two) ;
os.writeQbject(three) i
os. close () ;
catch(IOExceptioD ex) (
ex.printStackTrace() ;
}
one = null; Wt stt tnt... tD ""II so '\lit un't
two = null; ~ alUSS t.ht objttts 0l'I -\:he ht.af·
=
three null;
Now \'"tad tht... balK j" +\'"0'" the tilt...
~{ ~
Objectlnputstream is = new Objectlnputstream(new Filelnputstream ("Game. ser")) ;
Gamecharacter oneRestore = (GameCharacter) is. readObject () ;
GameCharacter twoRestore = (GameCharacter) is. readObject () ;
GameCharacter threeRestore = (GameCharacter) is. readObject () ;
~ .t. oVlt.t4·
System. out. println ("One' B type : \I + oneRestore. g8tType () ) ; Chtt'tt. -to see i \ ....
Systern.au t .println ("Two's type : " + twoRestore. getType () ) ; ~
System.out.println("Three's type: " + threeRestore .getTypeO) j
catch(Exception ex) (
ex .printstackTrace();

444 ch apter 14
serialization and file 110

fhe G-atl1eCharacfer class


import java.io. t ;

public class GameCharacter implements Serializable {


int power;
String type;
String[] weapons;
public GameCharacter(int p, String t, String[] w) {
power =p;
type =t;
weapons =w;

public int getPower ()


return power;

public String getType()


return type;

public String getWeapons () {


String weaponList = "":
for (int i =0; i < weapons. length; iff) {
weaponList += weapons[i] + " ";
}
return weaponList;

you are here " 445


saving objects

Ol.jed Serialization

)- You can save an objecfs state byserializJng the object.


)- To serialize an object, you need an ObJectOutputStream (from the
java.lo package)
)- Streams are either connection streams orchain streams
.. Connection streams can represent a connection to a source or
destination, typically afile, network socket connection, orthe
console.
)- Chain streams cannot connect to a source ordestination and must
be chained to a connection (or other) stream.
)- To serialize an object to a file, make a RleOuputStream and chain ~
into an ObjectOutputStream.
.. To serialize an object, call writeObject(theObject) on the
ObjectOutputStream. You do not need to call methods on the
FUeOutputSlream.
)- To be serialized. an object must Implement the Seriallzable interface.
Ita superclass ofthe class Implements Serializabls, the subclass will
automatically be seria\lzable even If ~ does not speclfically declare
implements Seri8/1zable.
)- When an object Isserialized, its entire oblect graph Isserialized. That
means any objects referenced bythe serialized object's instance
variables are serialized, and any objects referenced by those
obJects...and soon.
• If any object in the graph Is not serializable, an exception will be
thrown at runlime, unless the Instance variable referring tothe object
Isskipped.
.. Marie aninstance variable with the transient keyword if you want
serialization to skip that variable. The variable will be restored as null
(for object references) ordefault values (for primitives).
. • During deseriallzation, the class ofallobjects Inthe graph must be
available tothe JVM.
• You read objects In (using readObjeet()) Inthe order In which they
were originally written.
• The retum type ofreadObjectO is type Object, so deserialized
objects must be cast to their real type.
• Static variables are not serializedI Itdoesn't make sense to save
a static variable value as part of a specific objecfs state. sInce all
objects of that type share only a single valu&-the one Inthe class.

446 chapter 14
serialization and file I/O

Writi"g a Strittg to afext File


Saving objects, through serialization, is the easiest way to save and
restore data between runnings of a Java program. But sometimes you
need to save data to a plain old text file. Imagine your Java program
has to write data to a simple text file that some other (perhaps non-
Java) program needs to read. You might. for example, have a servlet
(Java code running within your web server) that takes form data the
60,Elf,how, sword,dust
user typed into a browser, and writes it to a text file that somebody else
loads into a spreadsheet for analysis . 200,Troll,ba.re ha.ndB,hlg ax
120,Maglolan,spel1B,invisibillty
Writing text data (a String, actually) is similar to writing an object,
except you write a String instead of an object. and you use a
FileWriter instead of a FileOurputStream (and you don't chain it to an
ObjectOutputStream) .

To write Q serialized object:


ObjQctOutputstream.vriteObject(someObject);

To write Q String:
fileWriter. wri te ("My first String to save") j

import

class WriteAFile {
public static void main (String[] args) {

try {
FileWriter writer =
/ 0 sb>~~
t\\...L- t)I~ \ b- I t.a-u.~.
...
II-$t. ~ ',1'1 a '(~... o'tJ
vl-''ri' ~.,.. "
't:.'J!'C'lv \1'1~ 1\
d1'l\
/
wri ter . wri te (" hello foo ! ") ; ~ Tht -.-iuO "'«hod uk

writer. close () ; ~ Cl
a St.ril'l~ es

\0'2-.,I.t.~y-b 0'/1•.
'l-
aSt '"1:. .... hCtl YO\l.'rt dO"ll
) catch(IOException ex) (
ex.printStackTrace();
}

you are here ~ 447


writing a text file

fext File ExatMple; e-Flashcards


Remember those flashcards you used in school? Where you
had a question on one side and the answer on the back?
They aren't much help when you 're trying to understand
something, but nothing bears 'em for raw drill-and-practice
and rote memorization. When JfYU have to burn in a faa. And
they're also great for trivia games.
We're going to make an electronic version that has three
classes:
1) QuizCardBuilder. a simple authoring tool for creating and
saving a set of e-Flashcards,
2) QuizCardPlayer. a playback engine that can load a
flashcard set and play it for the user. QulzCard
3) QuizCard, a simple class representing card data. We'll QuizCard(q, a)
walk through the code for the builder and the player, and
have you make the QuizCard class yourself, using this ~ question
answer
gelQuestion 0
18 0e Qvlz CMd",lIdo, I
gelAnswerQ
FI..
Quullon:
,
,
Which university Is featured In the ,
film -Good Will Huntlng~ 8 8e ()I~ card"-,
~ f j"

I ,What happens If you call


l:0bject.getPrimaryKeyO on a
I sian bean's remote reference?
J
,,~ .. An. ...r: I
M.I.T. ~ I~

::
,I
, LA)
IIi
10

( ShoW_, )
--
( Wulc.id )
-
- ;

- ~ "- ~

QulzCardBullder QulzCardPlayer

Has a File menu witk a ~SaveH option for saving Has a File menu with a "Load" option for loading a
the current set of cards to a text file. set of cards from a text fife.

448 chapter 14
serialization and file 110

Quiz Card 'uilder (code outli.,e)


public class QuizCardBuild er {

public void goO {


/ / build an d display gui

IMev- t.lass
private class NextCardListener implements ActionListener {
public void actionPerformed(Action Even t ev) {
/ / add the cu rr e nt card to the list and clear the text areas

IlIlIev- dass
private class SaveMenuListener imp lemen ts ActionListener {
public void action Performed (ActionEven t ev) {
/ / bring up a file dialog box
/ / let th e user name and save the set

IlIlIev- dass
p rivate class NewMenuListener implements ActionListener {
public void action Performed (ActionEven t ev) {
II d ear out the card list, and dear out the text areas

private void saveFIle(File file) {


/ / ite rate through the list of cards, and write each one ou t to a text file
/ / in a parseab le way (in oth e r words , with clear separations be tween parts)

Called by the Sa\leMell...L.istenev-;


does the at.hal ~ile WV"ibn~.

you are here ~ 449


Quiz Card Builder code

import java.util.*;
import java.awt .event. *;
import J,avax. swmq,
. *;
import java. awt. *;
import j.ava i.o . * ;
i

public class QuizCardBuilder


private JTextArea questi on;
private JTextArea answer;
private ArrayList<QuizCard> car dLi s t ;
private JFrame frame;

public static void main (String!] ar gs ) {


QuizCardBuilder builder = new QuizCardBuilder();
builder. go () ;

public void got) {


/ / build gui
f rame = new JFrame(uQuiz Card Builder");
JPanel mainPanel = new JPanel();
Font bigFont = new Font(Usanserif", Font.BOLD, 24);
question = new JTextArea(6,20);
question.setLineWrap(true);
question.setWrapStyleWord(true);
question.setFont(bigFont);
JScrollPane qScroller = new J Scro l l Pane (ques t i on) ;
qScroller .setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL SCROLLBAR ALWAYS);
qScroller .setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
answer = new JTextArea(6, 20);
answer.setLineWrap(true);
answer.setWrapStyleWord(true);
answer.setFont(bigFont);
JScrollPane aScroller = new JScrollPane(answer);
aScroller. setVerticalScrollBarPolicy (Scr ollPaneConstants.VERTICAL SCROLLBAR ALWAYS);
aScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);

JButton nextButton = new JButton(UNext Card");


cardList = new ArrayL ist<QuizCard>();
JLabel qLabel = new JLabel(uQuestion:" );
JLabel aLabel = new JLabel(UAnswer:");
mainPanel.add(qLabel);
mainPanel.add(qScroller);
mainPanel.add(aLabel);
mainPanel.add(aScroller);
mainPanel.add(nextButton);
nextButton.addActionListener(new NextCardListener());
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu(UFile");
JMenultem newMenultem = new JMenultem( UNew");

450 chapter 14
serialization and file I/O

JMenultem saveMenultem = new JMenultem("SaveH)i


newMenultem.addActionListener(new NewMenuListener());
saveMenultem.addActionListener(new SaveMenuListener());
tileMenu.add(newMenultem)i
fileMenu.add(saveMenultem)i
menuBar.add(fileMenu);
frame.setJMenuBar(menuBarli
frame.getContentPane() . add (BorderLayout. CENTER,
frame.setSize(500,600) i
frame.setVisible(true)i

public class NextCardListener implements ActionListener (


public void actionPerformed(ActionEvent ev) (
QuizCard card = new QuizCard(question.getText(), answer.getText());
cardList.add(card) i
clearCard () ;

public class SaveHenuListener implements ActionLiatener (


public void actionPerformed(ActionEvent ev) (
QuizCard card = new QuizCard(question.getText(), answer .getText());
cardList .add(card); t.nIS -b CI'f\
\)<I.... ar-d 'OIa\ l~
a ~i\e dia\~ 's.a~e tY'O"' ,; e j
'O-ri.. .~ ~ ~ t.MoSV . ~BO'\ a~
0=;:. ._ - \i...e W'lB\ ~\\ tM ~i\e di.1\:1 r.o~'11 01> '0'1 b'>e
d'Id\~ bo'1- r. ~ 'IS aOfle o>r
\ 't.bl\e> a ... ,\el \\'1 is HilS dS'f'
se ~ C~! It. ~ed
public class NewManuListener implements ActiOnListen~f\\f
public void actionPerformed(ActionEvent ev) (
cardList.clear(li
clearCard () i

private void clearCard() (


question.setText("")j
answer.setText(KHl j
question,requestFocuS()i

private void saveFile(File file) /


c>:
try {
BufferedWriter writer ~ new BufferedWriter(new FileWriter(file))i
e:-:)
for (QuizCard card: cardList) (
ij ~l! t.h.ai" d B~.f(l-edW\"ik

I
writer.write/card.getQuestion() + ... i")
writer, write (card.getAnswer () + "'\n") j
writer.close/);
catch (IOException ex) {
<. FJleWI"'ite-- to IR,)lce 't;
(We11 i:.llk abow! th i- Ot! to a 'lew
"~fI-e eHitie"f..
a ''I d 1'ew fa~e.v

Walle thr~h the ArrayL'~


.
0+
System .out.println("couldn't write the cardList out"); ~rd.s ar.d Wl"i~ tJ, t,'
ex. pr!ntStackTrace () i f(l- lillC wiLl 1..
, ~ =t Q lotS'bOt! ad.>
e...~" One tdrd
.s~t\" ~pdraud b \ "" " ..,,-
add /. y a /", and ihbl
a IItW'lIt thardt.te-- ("\11")
you are here. 451
writing fIles

fhe java.ioJiIeclass
The java.io.File class represents a file on disk, but doesn't
actually represent the contents of the file. What? Think of
a File object as something more like a pat/manu of a file
(or even a directory) rather than The Actual File Itself.
The File class does not, for example. have methods for
reading and writing. One VERY useful thing about a File
object is that it offers a much safer way to represent a A File object represents the name
file than just using a String file name . For example. most and path of a file or directory on
classes that take a String file name in their constructor disk, for example:
(like FileWriter or FileInputStream) can take a File
JUsersJKathy/DataJGameFile.txt
object instead. You can construct a File object, verify
that you've got a valid path, etc. and then give that File But it does NOT represent, or give
object to the FileWriter or FilelnputStream. you access to, the data in the filel

Some things you can do with B File object:

.. Make a File object repr~ntlng an


existing tHe
File f =new File(~MyCode.txtUI j

@ Make Q new directory


File dir =new File("Chapter7 n l ;
dir .mkdir () ;

• List the contents of a directory


if (dir.isDirectory()I {
String [1 dirContents = dir .list () ;
for (int i = 0; i < dirContents.length; iH) {
System.out.println(dirContents[i]);

8) Get the absolute path of Q file or directory


System.out.println(dir .getAbsolutePath(»;

I) Delete a file or directory (returns true If


successful)
boolean isDeleted =f.delete()j
452 chapte r 14
serialization and file 1/0

The beauty of buffers


If there were no buffers, It would be like
shopping without a cart. You'd have to
carry each thing out to your car. one soup
can or toilet paper roll at a time.

String is put into a buffer When the buffer ;s full. the Aspen
with other Strings Strings are all written to
Denver
"Boulder" ,... "BoulderH U~eD" •Aspen Denver Boulder M
Boulder
is written to "Denver" is chained to
String
BufferedWrlter FlleWrlter
File
(a chain stream that (a connection stream
works with characters) that writes characters
as opposed to bytes)

BufferedNriter writer = new BufferedKriter(new FileWriter(aFile))i

~
The cool thing about buffers is that they're much. more efficient than
working without them . You can write to a file using FileWriter alone, by
calling write (someString) , but FileWriter writes each and every thing you
pass to the file each and every time. That's overhead you don't want or
need. since every trip to the disk is a Big Deal compared to manipulating
data in memory. By chaining a BufferedWriter onto a FileWriter, the
BufferedWriter will hold all the stuff you write to it until it's full. Only when
the buffer isfull will theFUe Writer actually be told to unite to thefile on disk.
If you do want to send data beftn» the buffer is full, you do have control.
Just Flush It. Calls La writer.flush () say. "send whatever's in the buffer, now! h

you are here) 453


reading files

Readittg frotH a fext File


Reading text from a file is simple, but this time we'll use a File
object to represent the file, a FileReader to do the actual reading,
and a BufferedReader to make the reading more efficient.
The read happens by reading lines in a while loop, ending the loop What's 2 + 2?/4
when the result of a readl.inej) is null. That's the most common What's 20+22/42
style for reading data (pretty much anything that's not a Serialized
object): read stuff in a while loop (actually a while loop tesf),
terminating when there's nothing left to read (which we know
because the result of whatever read method we're using is null) .

~ ~ dthti"""~ MyText.txt
DO'I'I t dr~
I

import java. io. * ;

class ReadAFile {
pub1ic static void main (Strinq(J arqs) {
A Fild(eadty ~ a f.ctr., t t· ..L. ,.
tha b L' ~ oor, :ou-ea... i"or
try { ( yat , V1at (.OnnUts to a UlI.t .filt
File myFile = new File("MyText .txt");
FileReader fileReader = new FileReader(myFile);

BufferedReader reader =
.'bIt t.o nold
Makt a s.b-'Il'~ "a'(l" . Ii
. tl-lt linc IS yea
t4t.I-I Il't\t as '\,

String line = null;

while «line = reader.readLine(» != null) (


System. out.println (line) ;
}
reader.close();

catch(Exception ex) {
ex.printStackTrace();

454 chapter 14
serialization and file 1/0

Quiz Card Player (code outli"e)


public class QuizCardPlayer {

public void goO {


/ / build and display gui

class NextCardlistener implements ActionListener (


public void actionPerformed(ActionEvent ev) {
/ / if this is a question, show the answer, otherwise sh ow next question
/ / set a flag for whether we 're viewing a qu estio n or answer
}
}

class OpenMenuListener implemen ts ActionListener {


public void actionPerformed(ActionEvent ev) {
/ / bring up a file di alog box
/ / let the user navigate to an d choose a card se t to open

private void loadFile(File file) {


/ / must bu ild an ArrayList of cards, by reading them fro m a text file
/ / called from the OpenMenuListen er event h andler, reads the file one lin e at a time
/ / and tells the makeCard f) meth od to make a new card out of th e line
/ / (one line in th e file h olds bo th the question an d an swer, sep arated by a "I")

private void makeCard(String lineToParse) {


/ / calle d by th e Ioadf'ile method, ta kes a lin e fro m th e text file
/ / and parses into two pieces-s-qu estion and ans wer-a nd creates a new Q uizCard
/ / and adds it to th e ArrayList called CardList

you are here ~ 455


Quiz Card Player code

import java .util. *;


import java .awt. event.*;
import j avax . swi ng . *;
import java.awt. *;
import J. aVa. 10
' . *;

public cl as s QuizCardPlayer
private JTextArea display;
pr i vate JTextArea answer;
private Arr ayLi s t <QuizCard> car dLi s t;
privat e QuizCard currentCard;
privat e int cur r ent Car dI ndex;
private JFrame frame;
privat e JBut ton nextButton;
private boolean isShowAnswer;

public static voi d main (String [] args) (


QuizCar dPl ayer r ea der = new QuizCardPlayer();
reader.go();

publ i c void go()


II build gui
frame = new J Frame ("Quiz Card Player");
JPanel mainPanel = new JPanel();
Font bigFont = new Font("sanserif", Font.BOLD, 24);
display = new JTextA rea(lO, 20);
di splay. setFont (bigFont);
display. setLineWrap(true);
display. setEditable(false);
J ScrollPane qScroller = new JScrollPane(display);
qScroller.setVerticalScr ollBarPolicy(ScrollPaneConstants.VERTICAL SCROLLBAR ALWAYS);
qScroller. setHor izontalScrollBarPolicy (ScrollPaneConstants.HORIZONTAL SCROLLBAR NEVER);
nextBut ton = new JButton("Show Ques t i on" ) ; - -
ma i nPanel . add (qScro l l er ) ;
mainPane l.add(nextButton);
nextButton.addActionListener(new NextCardListener());
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
JMenuItem loadMenuItem = new JMenurtem ("Load card set");
l oadMenultem.addActionListener(new OpenMenuListener());
fileMenu. add (loadMenuItem) ;
menuBar .add (fil eMenu ) ;
f r ame.setJMenuBar(menuBar);
frame.getC ontentPane( ) .add(BorderLayout.CENTER, mainPanel);
frame.setSi ze( 640, 500);
frame. setVis ible(true) ;
II close go

456 chapter 14
serialization and file 110

public class NextcardListaner implements ActionListener (


public void actionperformed(ActionEvent eu) (
if (isShowAnswer) (
I I show the answer because they've seen the question
display.setText(currentCard .getAnswer(») ;
nextButton.setText(~Next Card");
isShowAnswer = false;
else {
II show the next question
if (currentCardIndex < cardList.size(»)
showNextCard();
else I
II there are no more cards!
display.setText(~That was last card");
nextButton .setEnabled(false);

public class OpenManuLiatanar implements ActionListener


public void actionPerformed(ActionEvent ev) (
JFileChooser fileOpen = new JFileChooser();
~ fileOpen.showOpenDialog(frame);
r 'loadFile(fileOpen .getSelectedFile(»:
)

~l
private void loadFile(File file) (
cardList = new ArrayList<QuizCard>();
try (
BufferedReader reader = new BufferedReader(new
String line = null:
while ((line = reader. readLine () I ! = null) (
makeCard(line) ;
I
reader.close();
catch(Exception ex) {
System. out. println ("couldn't read the card file") i
ex.printStackTrace();
I
II now t ime to start by showing the first card
showNextCard() ;
I
private void makeCUd(Stxing lineTOi'U88) ( ~I Eat.h liYlt: o.f U1\.-t t..on-uyonds to • si,,~le
String () result = lineToParse . spli t (" I"); ~ .fl~hu...d blAt. 'foIt: h6\1e to yal"~ ~ -the
QuizCard card = new QuizCard(result{Oj, resu.l t l Ll j r Iot:S'ti ~ d al\S'W£\'" as stf.lYab: yiet.e1, We
cardList. add (card) ; ~ Otl ~, l'tO tthoa to b...eak +.he
System. out prInt Ln ("made a card") j
i ~ the SU"I~ s.? I ... r.1L st.i
.,-« VIe '\\Iot 071
IiI\( i'llto t'folO tokC'llS (oM.
arod 0YIe .t« -the .1\1"",£\'"), We'll look at tht:
private void showNextCardO ( \itO ...dhod Of! the Ylt:1\.-t y,,~t,
currentCard = cardList.get(currentCardlndex); ~
currentCardIndex++;
display .setText(currentCard.getQuestion();
nextButton .setText("Show Answer");
isShowAnswer = true;
}
I I close class
you are here ~ 457
parsing Strings with splitO

Parsittg with Strhtg splitCJ


Saved In a question file like this:
Imagine you have a flashcard like this:

WhB.t is blue + yellow?j green


Wha.t 1B red + blue?jpurple
What is blue + yellow?
clJ\S'fie\"

green

How do you separate the question and answer?


When you read the file, the question and answer are smooshed
r
together in one line, separated by a forward slash" (because
that's how we wrote the file in the QuizCardBuilder code).

String splitO lets you break a String Into pieces.


The spJitO method says, "give me a separator, and I'll break out ell
the pieces of this String for you and put them in 0 String array:

token 1 separator

468 chapter 14
serialization and file 1/0

Q:OK,I look In the API and there are about five


mUllon classes In the Java.lo package. How the heck do
you know which ones to use? Make it. St.itk
ext
A..: The I/O API uses the modular 'chaining' concept so
that you can hook together connection streams and chain
Roses are first, violetsare next.
Redders and w,lters areonly for t .

streams (also called 'filter' streams) In a wide range of


combi nations to get Just a bout anyth Ing you couId wa nt .
The chaIns don't have to stop at two levels; you can hook
multiple chain st reams to one another to get just the right
amount of processing you need.
Most of the t ime, though, you'll use the same
smaII handfu I of classes.If you're wrlti ng text flies,
BufferedReader and BufferedWriter (chained to FlIeReader
and Fll eWriter) a re pro bably all you need. If you're wrlti ng
serialized objects, you can use ObJeetOutputStream and • To wrile a text file, start with a FileWriler
ObJectlnputStream (chained to FllelnputStream and connection stream.
FileOutputStream). • Chain \he FileWriter toa BufferedWriter for
In other words, 90% of what you might typically do with efficiency.
Java I/O can use what we've already covered. • A File object represents a file ata particular
path, but does not represenl the actual
Q:What about the new I/O nlo classes added In 1.41 contents of the file.
• With a File obiect you can create, traverse,

A.: The [ave.nlo classesbring a big performance


improvement and take greater advantage of native

and delete directories.
Mosl streams that can use a String filename
can use a File object as well, and a FJle obiect
capabilities of the machine your program Is runn ing
can be safer 10 use.
on. One of the key new features of nlo is that you have
direct control of buffers. Another new feature Is non- • To read a text file, start with a FileReader
blocking I/O, which means your I/O code doesn't just sit connection stream.
there, waItIng, if there's noth Ing to read or write. Some • Chain \he FileReader to a BufferedReader for
of the existing classes (Including FllelnputStream and efficiency.
FlleOutputStream) take advantage of some of the new
features, under the covers.The nio classes are more • To parse a text file. you need 10 be sure the
complicated to use, however, so unless you really need the file is written with some way to recognize the
new features, you might want to stick with the simpler different elements. Acommon approach is to
versions we've used here. Plus, If you're not careful , nio can use some klnd ofcharacter to separate the
lead to a performance loss. Non-nlo I/O Is probably right individual pieces.
for 90% of what you'll normally do, especially if you're Just
• Use the String splitO method 10 split a String
getting started In Java.
upinto indiVidual tokens.AString with one
But you can ease your way Into the nlo classes, by using separator will have two tokens, one on each
FilelnputStream and accessing its channelthrough the side of\he separator. The separator doesn~
getChannelO method (added to FllelnputStream as of
count asa token.
version 1.4).

you are here. 459


saving objects

Versio" IP: AJig Serializatio" &otcha


Now you 've seen that I/O inJava is actually pretty simple, especially if
you stick to the most common connection/chain combinations. But
there's one issue you might really care about. • You write a Dog class
10UOl
1011 01 ".
1010 1000010 ··
~~;~o10 1Q
1010101
\
taSS
,,~S\()Y\·
\1"'v1

Version Control is crucial! ~~~~~~~~Ol ~;Ar;


!fyou serialize an object, you must have the class in order to Dog.class
deserialize and use the object. OK, that's obvious. But what might


be less obvious is what happens if you change the classin the
meantime? Yikes. Imagine trying to bring back a Dog object when You serialize a Dog object
one of its instance variables (non-transient) has changed from a using that class
double to a String. That violatesJava's type-safe sensibilities in a Big
Way. But that's not the only change that might hurt compatibility.
Think about the following:

Changes to a class that can hurt deseriallzatlon:


Deleting an instance variable
Changing the declared type of an instance variable
Changing a non-transient instance variable to transient
Moving a class up or down the inheritance hierarchy
• You change the Dog class
~~~i~~
~:~:O~~':
Ol 01 0

;o~~~o:~:o
\
1.
tlass >JeYSIO'l\

:H=12-~
. \D

Changing a class (anywhere in the object graph) from Serializable 1. 0 1. 10 10

to not Serializable (by removing 'implemen ts Serializable' from a Dog.c1ass


class declaration)
Changing an instance variable to static

Changes to a class that are usually OK:


• You deserialize a Dog object
using the changed class

101101
10UOl ' "
101000010
Adding new instance variables to the class (existing objects will 1010 10 0
01.010 1
deserialize with default values for the instance variables they didn't 10 0001 1010
o

C
00 11 01 01
1. 0 1 10 1 0
have when they were serialized)
Dog.class
Adding classes to the inheritance tree
t\a ss >Jeys',OYl 'IS
Removing classes from the inheritance tree
:H=12-~
Changing the access level of an instance variable has no affect on
the ability of deserialization to assign a value to the variable
Changing an instance variable from transient to non-transient
• Serailization fails!!
(previously-serialized objects will simply have a default value for the
previously-transient variables) The JVM says, "you can't
teach an old Dog new code".

460 cha pte r 14


serialization an d file 110

Usi.,g the serialVersio.,UIP


Each time an object is serialized. the object (including
every object in its graph) is 'stam ped' with a version
ID number for the object's class. The ill is called
the serialVersionUlD, and it's computed based on
inform ation about the class structure . As an object is When you think your class
being deserialized, if the class has changed since the might evolve after someone has
object was serialized, the class could have a different serialized objects from it•••
serialVersionUID, and deserialization will faill But you
can control this.
@ Use. the serialver command-line too'
to get the version ID for your closs
If you think there Is ANY possibility that
your class might evolve, put a serial version
ID In your class.
When Java tries to deserialize an object, it compares
the serialized object's serialVersionUID with that of the
class the JVM is using for deserializing the object For
example, ifa Dog instance was serialized with an ill of,
say 23 (in reality a serialVersionUID is much longer).
when theJVM deserializes the Dog object it will first
compare the Dog object serialVersionUID with the
Dog class serialVersionUID. If the two numbers don't
match, rhejVM assumes the class is not compatible CD Paste the output into your closs
with the previously-serialized object, and you'll get an
exception during deserialization. public class Dog {

So, the solution is to put a serialVersionUID long .erialVersionOZD -


in your class, and then as the class evolves, the -6849194410154667110L;
serialVersion UID will remain the same and the JVM
will say. "OK, cool, the class is compatible with this private Strinq name;
serialized object." even though the class has actually private int size ;
changed.
/ / method code here
This works ()1lly if you're careful with your class
changes! In other words. YQU are taking responsibility
for any issues that come up when an older object is
brought back to life with a newer class .
~ Be sure that when you make changes to
To get a serialVersionUID for a class, use the serialver the closs , you take responsibility in your
tool that ships with your Java development kit. code for the consequences of the changes
you made to the clossl For example, be
sure that your new Dog closs can deal with
an old Dog being deserialized with default
values for instance variables added to the
doss after the Dog was serialized.

you are he re ~ 461


Code Kitchen

'*Code Kitchen*

Let's mak the BeatBox save and


restore our lavorite pattern

462 chapter 14
serialization and file I/O

SavinG a 'eatJox pattern


Remember, in the BeatBox, a drum pattern is nothing more than a bunch of
checkboxes. When it's time to play the sequence, the code walks through the
checkboxes to figure out which drums sounds are playing at each of the 16
beats. So to save a pattern, all we need to do is save the state of the checkboxes.
We can make a simple boolean array, holding the state of each of the 256
checkboxes. An array object is serializable as long as the things in the array are
serializable, so we'll have no trouble saving an array of booleans.
To load a pattern back in , we read the single boolean array object (deserialize
it), and restore the checkboxes. Most of the code you've already seen, in the
Code Kitchen where we built the BeatBox GUI , so in this chapter, we look at
only the save and restore code.
This CodeKitchen gets us ready for the next chapter, where instead of writing
the pattern to a file, we send it over the network to the server. And instead of
loading a pattern in from a file, we get patterns from the server, each time a
participant sends one to the server.

Serializing a pattern
This is an inner t\ass i'llSide
t.he Beat.Bo~ zede.
public class MySendListener implements ActionListener { l' \.,,, t.he
It. all happens ..,hen "he ~er " . s
public void actionPerformed (ActionEvent a) {~b~Hon and t.he Ad:ionE.'Ient. .{\res.

boolean [] checkboxState = new boolean [256]; t-- Zt a rbooleatl array to hold t.he
for (int i = 0; i < 256; i++) { 01" eath the'kbo~.

JCheckBox check = (JCheckBox) checkboxList.get(i); Walk t.hro~ h t.h


if (check.isSelected(» { (ArrayList. got e thetkbo~List
checkboxState[i] = true; get t.he state thetkbo~s), atld
add it to t 0+ eath Otle, and
he boo/eatl array.

try {
FileOUtputStream fileStream = new FileOUtputStream(new File("Checkbox.ser"»;
ObjectOUtputStream os = new ObjectOUtputStream(fileStream) ;
os.writeObject(checkboxState);
catch(Exception ex) {
ex.printStackTrace();

} II close method
II close inner class

you are here). 463


deserlallzlng the pattern

Resfori.,g a Jea1tox patter"


This is pretty much the save in reverse... read the boolean array and use it
to restore the state of the GUI checkboxes, It all happens when the user hits
the "restore" 'button.

Restoring a pattern

public class MyReadInListener impleJDenta ActionLiataner

publiC void actionPerfor.med(ActionEvent a)


boolean [] checkboxState :;;;; null;
try (
FilelnputStream filaIn:;;;; new Filelnputstream(new File("Checkbox.aer"»;
ObjectInputstream is • new ObjectInputStream(fileIn) ;
checkboxState = (boolean []) is. readObject () ; t--- Rao -the s"",~'e ~jed: i". the kil~~e
boolea" array> o"d ta1-t It W . 0
catch (Exception ex) (ex. printstackTrac. () ; } boolea" arr0'i (Yl:1"etI'w. ytaoObjett
\'"d~."s a yet ~a-.te ok ~e Ob}et
for (int i :;;;; 0; i < 256; i++) (
JCb.eckBox check :::r (JCheckBox) aheokboxLillt. get (1) ;
i f (eheckboxState till (
ohaek.satsalected(trua) ;
} elae (
eheck.aetselected{false);

sequencer.stop();
buildTrackAndStart();

} I I close I118thod
II close inner class

rpen your penCiI------- - - - - - - - - - - ,


This version has a huge IImltatlonl When you hit the "serlatlzelt" button, It
serlaIIzes automatlca lIy,to a file named "Checkbox.ser" (which gets created If It
doesn't exist) . But each time you save,you overwrite the previously-saved flIe.
Improve the save and restore feature, by Incorporating a JFlleChooser so that
you can name and save as many different patterns as you like, and loadlrestore
from any of you r prevIously-saved pattern flies.

464 chapter 14
serialization and file 110

~yourpenCii can they he saved?


Which of these do you think are,or should be,
serlallzable? If not, why not? Not meaningful7
Security rlsk7 Only works for the CU Trent
execution of the JVM?Make your best guess,
without looking it up in the API.

Object type Serlallzable? If not, why not?

Object Ves I No

String Yes I No

File Yes I No

Date Ves I No

OutputStream Yes I No

JFrame Yes I No

Integer Yes I No

System Ves I No

Whars Legalil FileReader fileReadar ~ new FileReader() i


BufferedReader reader :: new BufferedReader (fileReader) ;
:lrclethe code fragments
nat would compile (assuming
FileC>utputStream f :: new FileOutputStream (new File ("roo . se.r") ) ;
:hey're withIn a legaI dass). ObjectOutputstream 08 :: new ObjectOutputStream(f) ;

KEEP BufferedReader reader:: new BufferedReader(new FileReade.r(file)) ;


=
+-
String line null;
whila (line • reader.readLine()) != null) (
malcecard(line) ;

RIGHT
ObjectInputStream is = new ObjectInputstream (new Fil&Outputstream("Game. ser")) ;
GameCharacter oneAgain = (Gamecharacter) is.readObject();

you are here ~ 465


exercise: True or False

This chapter explored the wonerful world of


Java 110. Your Job Is to decide whether each
of the followi ng lID-related state ments is
true or false.

1. Serialization is appropriate when saving data for non-java programs to use.

2. Object state can be saved only by using serialization.

3. ObjectOutputStream is a class used to save serialized objects.

4. Chain streams can be used on their own or with connection streams.

5. A single call to writeObjectO can cause many objects to be saved.

6. All classes are serializable by default.

7. The transient modifier allows you to make instance variables serializable.

8. If a superclass is not serializable then the subclass can't be serializable.

9. When objects are deserialized, they are read back in last-in, first out sequence.

10. When an object is deserialized, its constructor does not run.

11. Both serialization and saving to a text file can throw exceptions.

12. BufferedWriters can be chained to FileWriters.

13. File objects represent files, but not directories.

14. You can't force a buffer to send its data before it's full.

]5. Both file readers and file writers can be buffered.

16. The String splitO method includes separators as tokens in the result array.

17. Any change to a class breaks previously serialized objects of that class.

466 chapter 14
u serialization and file 110
CoJe lYlaonets
This one's tricky, ~ we promoted it from an Exerciseto full Puzzle status.
Reconstruct the code snippets to make a working Java program that
produces the output listed below? (You might not need all of the magnets,
and you may reuse a magnet more than once.)

-
seriali'Zabl e {
class DungeonGame implements

fos = new
FileOutputstrearn short getZ () {
" drr, s e r " ) i
FileOutputs t r e am( ~
return Zi

e.printStackTrace()i
009. close ( ) :

ObjectlnputStream ois = new


int geU() {
ObjectlnputStream(fis);
return Xi

System.out.println(d.getX()+d.getY()+d.getZ())i

Filelnputstream fis = new ubl i c int x = 3;


FilelnputStream("dg.ser")j ransient long y = 4;
private short z = 5;
long getY() {
class D
return y;
ungeOnTest <

ois , close ( ) ;
import java.io'~i

fos.writeObject(d);
~ ----••"I } catch (Exception e) {

d = (DungeonGame) ois.readObject()j

ObjectOutputstream 009 = new


ObjectOutputStream(fos): oos .writeObject(d);

'd main(String I J arg9) {


public static vo~
DUngeonGame():
DungeonGame d = new
yo u are here ~ 467
exercise sol utions

1. Serialization is appropriate when saving data for non:Java programs to use. False

2. Object state can be saved only by using serialization. False

3. ObjectOutputStream is a class used to save serialized objects. True


4. Chain streams can be usedon their own or with connection streams. False

5. A single call to writeObjectO can cause many objects to be saved. True


6. All classes are serializable by default. False

7. The transient modifier allows you to make instance variables serializable. False

8. If a superclass is not serializable then the subclass can't be serializable. False

9. When objects are deserialized they are read back in last-in, first out sequence. False

10. When an object is deserialized, its constructor does not run. True
11. Both serialization and saving to a text file can throw exceptions. True
12. BufferedWriters can be chained to FileWriters. True
13. File objects represent files, but not directories. False

14. You can't force a buffer to send its data before it 's full. False

15. Both file readers and file writers can optionally be buffered. True
16. The String splitf) method includes separators as tokens in the result array. False

17. Any change to a class breaks previously serialized objects of that class. False

468 chapter 14
serialization and file 110

class DungeonGame implements Serializable {


public int x = 3;
transient long y = 4:
private short z =
5:
int getX() {
return Xj
}
long gety() {
return Yj
}
short getZ() {
return 2:
}
}

class DungeonTest {
public static void main(String [) args) (
DungeonGame d = new DungeonGame{)j
System.out.println(d'getX() + d.getY() + d.getZ{»j
try (
FileOutputStream fOB = new FileOutputStream{Udg.ser H
) :

ObjectOutputStream oos = new ObjectOutputStream(foB)j


oos.writeObject(d);
oos.close():
FilelnputStream fis = new FilelnputStream(Udg.ser n ) :
Fit ~~ W1~ Help Es:apo ObjectlnputStream ois = new ObjectlnputStrearn{fis):
\ j ava DungeonTest d = (DungeonGame) ois.readObject();
12 ois.close();
8 catch (Exception e) {
e.printStackTrace()j
)
system.out.println(d.getX() + d.getY{) + d.getZ{»;
}

you are here. 469


15 networking and threads

Make a Connection

Connect with the outside world. Your Java program can reach out and touch a

program on another machine. It's easy. All the low-level networking details are taken care of by

classes In the java.net library. One of Java's big benefits is that sending and receiving data over

a network Is Just I/O with a slightly dIfferent connection stream at the end of the chain. If you've

got a BufferedReader. you can read. And the BufferedReader could care less if the data came

out of a file or flew down an ethernet cable. In this chapter we'll connect to the outside world

with sockets.We'll make cllentsockets.We'll make server sockets.We'll rnake clients and servers.

And we'll make them talk to each other. Before the chapter's done, you'll have a fully-functional,

multithreaded chat client. Old we just say multithreaded? Yes, now you will learn the secret of

how to talk to Bob while simultaneously listening to Suzy.

t his is a new chap ter 471


tbo)(. chat

You're working on a computer game .You and your team

B :O"~C:h:a:t -:r~~~;si~~~@~c::~~;1
are doing the sound design for each part of the game.
Using a 'chat' version of the Beat 'Box, your team can

.i~
collaborate-You can send a beat pattern along with
your chat message, and everybody in the Beat __
getS So yO,u don't just get to rtad\ th e othder. .. "I<.t
""'\<IO.sl'I"...• 0>"
pa",clpa. ",,,sages. yoU gel 10 oad an e.... - ..
, - ' <en me "'" ..... ee ,.
;;;;.<"" ...

~~~
pl<ry a bea lSpattern s,,,,ply by chclcing the
l
message in the incoming . messages
In this chapter we' re going 10 ' area.
. learn what ,t ' ,.f'· ,. ......
Go .'-' _t \ t \ 1\ "", ,."
,"-, l' \\
t''- to\!.

takes 10 ",ake a chat chenl hke th". We're oc ,,.n " ,<t. """
even going 10 ,earn a hlde .boUI ",aking a
cba IS,,"'" We'n save the fun Beat Be' Chat
If
t:..', In ..."
\00""""
r\~
>;'f""'" ..... <1' - ;
"'"
for the Code lGochen. but in mis chapter you
",iUwn"" Ludicrously Si",ple Chat Client and
Very Si",ple Chat Se",er that send and ,eceive
t"''''''
~~ ,.,fI''''''' ""
"''' m"",g'" <;t, s." """,

472 chapter '\5


networking and threads

Chat Program Overview

The Client has to know


ahoutthe Server.
The Server has to know
about ALL the Clienti.

Client C
How it Works:
o Client connects to the server

Client A

G The server makes a


connection and adds the client
Client A Server
to the list of participants
~V~, I'd lik~ to l.o9I~t
- to tht
e Another client connects
t~ stHite

Client B Server
-~~

"Who took ~ lava liMf_ _---1 I ~


o
--- I ~. '.-
.

Client A sends a message to - ~---. My OOhtl f


the chat service
Client A Server

o The server distributes the


message to ALL participants
Client A Server
(including the original sender)
Client B

you are here ~ 473


socketconnecllons

The three things we have to learn to get the client working are :
1) How to establish the initial connection between the client and server
2) How to send messages UJ the server
S) How to receive messagesjrom the server
There's a lot of low-level stuff that has to happen for these things to work. But we're
lucky, because the Java API networking package (java.net) makes it a piece of cake
for programmers. You'll see a lot more GUI code than networking and I/O code.
And that's not all.
Lurking within the simple chat client is a problem we haven't faced so far in this
book: doing two things at the same time. Establishing a connection is a one-time
operation (that either works or fails). But after that, a chat participant wants to
send outgoing messages and simultaneously receive incoming 7TU'.SSages from the other
participants (via the server). Hmmmm... that one's going to take a little thought, but
we'll get there injust a few pages.

o Connect
Client connects to the server by
establishing a Socket connection.

Ma~ a sotlcd:. l.mIPlettiO'll to


J~I>.lbt.r.rO; .if. rort c;ooo

Client A

• Send
Client sends a message to the server

Client A

e Receive
Client gets a message from the server

Client A

474 chapter 15
networking and threads

Make a ttetwork Socket cotntectiott


To make aSoc"ket
To connect to another machine, we need a Socket connection.
A Socket (java.ner.Socket class) is an object that represents
connection, you need
a network connection between two machines. What's a to know ~ things
connection? A relationship between two machines. where two
pieces of software know about each other. Most importantly, about the server: %0
those two pieces of software know how to communicatewith it is, and which port
each other. In other words . how to send bits to each other.
We don't care about the low-level details, thankfully, because
its running OIL
they're handled at a much lower place in the 'networking
stack'. If you don't know what the 'networking stack' is, don't
In other words,
worry about it. It's just a way of looking at the layers that
information (bits) must travel through to get from aJava IP address and TCP
program running in aJVM on some OS, to physical hardware
(ethernet cables, for example). and back again on some other
port l11U1lher.
machine. Somebody has to take care of all the dirty details.
But not you. That somebody is a combination of O~pecific
software and the Java networking API. The part that you have
to worry about is high-level-make that v~ high-level-and
shockingly simple. Ready?
7 Port 1l""'ba-
Socket chatSocket = new Socket(~196.164.1.103H, 5000);
lr:ci r t1S ~or the sa-vt:r

Client

ASocket connection means the two machines have


inforztlation about each other, including networl
location (IP address) and TCP port.
you are here ~ 475
well-known ports

Arep port Is Just attutltber.


A16.. bit ttutMber that identifies Well-known TCP port numbers
for common server applications
aspecific prograttt Ott the server.
Your internet web (HTTP) server runs on port 80. That's a
standard. If you've got a Telnet server, its running on port
23. FTP? 20. POP3 mail server? 110. SMTP? 25. The Time
server sits at 37. Think of port numbers as unique identifiers.
They represent a logical connection to a particular piece of
software running on the server. That's it. You can't spin your
hardware box around and find a TCP port. For one thing,
you have 65536 of them on a server (0 - 65535). So they
obviously don't represent a place to plug in physical devices.
They're just a number representing an application. AseY"'er" l.4 ... helVe "p to b&5~b
diHf"r'etlt serve- apps 'nIIInil'\~
Without port numbers, the server would have no way of ~ per" pori:.
knowing which application a client wanted to connect to.
And since each application might have its own unique
protocol, think of the trouble you 'd have without these
identifiers. What if your web browser, for example, landed
at the POPS mail server instead of the HTTP server? The The TCPport
mail server won 't know how to parse an HTTP request! And
even if it did, the POPS server doesn't know anything about
tuU1lbers frOttl 0 to 1023
servicing the HTTP request are reserved for well-
When you write a server program. you'll include code that
tells the program which port number you want it to nul on
"known services. Don't
(you'll see how to do this in Java a little later in this chapter). use them for your own
In the Chat program we're writing in this chapter. we picked
50DD.Just because we wanted to. And because it met the
server programs!'"
criteria that it be a number between 1024 and 65535. Why
I024? Because 0 through 1023 are reserved for the well- The chat server we're
known services like the ones we just talked about, writing uses port
And if you 're writing services (server programs) to run on
a company network, you should check with the sys-admins
5000. We just }tie"ked a
to find out which ports are already taken. Your sys-admins tuU1lber between 1024
might tell you, for example, that you can't use any port
number below, say, 3000 . In any case, if you value your limbs, and 65535.
you won't assign port numbers with abandon. Unless it's
your home network. In which case youjust have to check with
your kids. 'Well, you might be able 10 use one of
these. bul the sys-adrnln where you
work will probably kill you.
476 chapter 15
networking and threads

Q: How do you know the port


number of the server program you
want to talk to 7

A.: That depends on whether the


program is one of the well-known
services. If you're trying to connect
to a well-known service, like the ones
on the opposIte page (HTIp' SMTP,
FTP,etc.) you can look these up on
the Internet (Google "Well-Known
TCP Port"). Or ask your friendly IP address is like specifying a
eighborhood sys-adrnin.
particular shopping moll, soy,
But if the program isn't one of the
"Flatirons Marketplace"
well-known services,you need to
find out from whoever Is deploying
the service. Ask him. Or her.Typically,
if someone writes a network service or number is like naming
and wants others to write clients for
it , they'll publish the lP address, port a specific store, soy,
number, and protocol for the service. "Bob's CD Shop"
~ or exampie, if you want to write a
client for a GO game server, you can
visit one of the GO server sites and
find Information about how to write a
client for that particular server.

Q: Can there ever be more than OK,you got a Socket connection .The client and the
one program running on a single server know the IP address and Tep port number for
port7 In other words, can two each other. Now what1 How do you communicate
applications on the same server have
over that connection 11n other words, how do you
the same port number7
move bits from one to the other? Imagine the kinds of

A.: Nol If you try to bl nd a prog ram


:0 a port that Is already in use,you'll
messages your chat client needs to send and receive.

get a BindException. To bind a program


:0 a port just means starting up a
server application and telling It to run
a particular port. Again, you 'll learn
~ o re about this when we get to the
Client Server
server part of this chapter.

you ar e here ~ 477


reading from a socket

To read data frotH aSocket use a


SufferedReader
To communicate over a Socket connection, you use streams.
Regular old I/O streams.just like we used in the last chapter. One
of the coolest features in java is that most of your I/O work won't
care what your high-level chain stream is actually connected to. In
other words, you can use a BufferedReader just like you did when
you were writing to a file, the difference is that the underlying
connection stream is connected to a Socket rather than a File!
L ii,n 'foU kno-.l
\-.
TM forl:. ,",""g~b-.I +.hat "000 is
o Make a Socket connection to the server
Socket chatSocket ~ new Socket("127.0.0.1", 5000);
h~t.1\OU -.I~ TOL ~ 'fou t.hat ~t:r.
/ t.\It ~ "",",ht:r ~(K oU'r

"-.. /27.0.o.J t.h


z: 'N~dsJ +f.~ I~:d~~~tubtor '11~lhoti
S~Vtt-
i$

" ~ Ulis 'oIh


bI
)
Yot. r~
I.lI t.od~ i.s... .
"")\11\9 01\.
.. .
) 'n
You
you.r tJ'bI t dnd
rt. )\d-aIOtlt~"'clth.
e Make an InputStreamReader chained to the Socket's
low-level (connection) input stream
01\ d .sjI\SI~
I

rr>e.

1L. &oH~(dReAdt:r b:> ~~ d 1 - tnt 10-.1-

e Make a BufferedReader and readI


Chai" V'C'
\"ovtSb-ta""Rea~_ w
I 1:
( \('<It! to'l\,,(tuOl\
d ( nit\-. was t\-.ai"t 'UJ,.. .\• ..l.)
AJ. ~'r()7f\ tr.( ~
S"t.Tta'" -.It 'J"'''

BufferedReader reader = new BufferedReader (stream) i


String message = reader.readLine();

buffered characters converted to characters bytes from server - ---- - -

buffered
characters I I
~chained to characte.rs ,.chained to 011010011 _ 1'+·--- :' I

BufferedReader InputStre.amRe.ader Socket's input stream r. I


Client (we. don't need to know
the. aCf\JQ1 class) Server

478 chapter 15
networking and threads

fo write data to aSocket use a


Prh1tWriter
We didn't use PrintWriter in the last chapter, we used BufferedWriter. We have
a choice here, but when you 're writing one String at a time, PrintWriter is the
standard choice. And you'll recognize the two key methods in PrintWriter,
printO and println () IJust like good 01' System.out,

o Make a Socket connection to the server


Socket chatSoeket = new Soeket("127.0 .0.1",

e Make a PrintWrlter chained to the Socket's low-level


(connection) output stream
PrintWriter writer = new PrintWrit8r(chatsocket .qetoutputStream(»;

e ~ (print) something
writer.println("messaqe to send"); ~rrl"U" a
. l ~t ClIO ~
0 ods a I\tfoI \ ,roe aT.
. 1I
.
..,\\at it. se..o.s·

writer.print("another message"); ~rri"t() cl.~"" iu


'L J o-tht "CW \I"t.·

characters bytes to server

----+~I .message..." ~
PrintWriter
I
chained to
011010011
'----_--I
Socket's output
stream (we don't need
to know the actual class)

you are here) 479


writing a client

fhe PailyAdvieeCliet1t
Before we start building the Chat app,
let's start with something a little smaller.
The Advice Guy is a server program that
offers up practical, inspirational tips
to get you through those long days of
coding.
We're building a client for The Advice
Guy program, which pulls a message
from the server each time it connects.
What are you wailing for? Who kncws
what opportunities you've missed
without this app.

The Advice Guy


o Connect
Client connects to the server and gets an
input stream from it

Client

eRead
Client reads a messQge from the server

Client A
480 chapter 15
networking and threads

PailyAdviceCliet1t code
This program makes a Socket, makes a BufferedReader (with the
help of other streams), and reads a single line from the server
application (whatever is running at port 4242).

import java .io.*;


L-_~ tlass r_.,.-L
;:,Q<o~~
is in ,o"a.nt1:.
.,}

import java .net.* ;~

public class DailyAdviceClient

InputStreamReader streamReader = new InputstreamReader(s.getlnputstream(»;


BufferedReader reader = new BufferedReader (streamReader); thain a B~~e\'"edReode\'" to
f---"" art Irty~+.streaMRe ade\'" to
the inf~t str'ea", t\'"OM the
Sotkd:..

string advice = reader .readLine(); ~ t his readL ' o .


th Ihe
System.out .println("Today you should: " + advice) ; Be sa"'e as ;~ 0'"
EXAcTL'( IS

",UeredR. d 't were ~ih~ a


Ih ot her w ea er lhaihed to a FI
reader. close () ; ~this doses AI-I- the streaMS r-
lall a B. r ds, by the 1;'
fAot-teredW" 't ''''e yOl.t
LE..
writer dOt;sh't k r. er "'ethod, the
catch(IOException ex) {
the lharal ters la
h ow
0:
lare where
"'e -tro",.
ex .printStackTrace();

public static void main (String[] args)


DailyAdviceClient client = new DailyAdviceClient();
client. go () ;

you are here . 481


socketconnecUons

Test your memory of the streams/classes for reading and writing from a
Socket.Try not to look at the opposite pagel

To read text from a Socket:


-
, .. - .

!
\

'M'iU!dra.., il'l t.h~ thaill o-f sttea....s t.he tlitl'lt. \'


Client
I.I$tS to read .f"'OM t.ht st'r'/er server

To send text to a Socket

'M"iWdraw ill the thaill o-f sttUMS the t1iblt


Client lAStS to smd ~i"5 to the ~ver

rpen your pencU - - - - - - - - - - - - - - - - - - .


Fill In the blanks:

What two pieces of Information does the client need in order to make a
Socket connection with a server?

Which TCP port numbers are reserved for'well-known services'like HTTPand FTP7

TRUE or FALSE: The range of valid TCP port numbers can be represented
by a short primitive?

482 chapter 15
networking and threads

Wrifittg a sitttple server


So what's it take to write a server application? Just a
couple of Sockets. Yes, a couple as in two. A ServerSocket,
which waits for client requests (when a client makes a
new Sockett) and a plain old Socket socket to use for
communication with the client.

How it Works:

o Server application makes a ServerSocket, on a specific port


SarverSocket serverSock: new S&rV8rSocket(4242);
This starts the server application listening ~ ~~ ~
for client requests coming in for port 4242. . ) ...
\

e Client makes a Socket connection to the server application


Socket sock = new Socket ("190 . 165. 1 . 103" , 42(2);

Clie.nt knows the IP address and port number


(published or given to him by whomever
configures the server app to be on that port)
rs::~~
.. .
. ... ~ ~
~
.
.,l
SD",,~~et.
'II'':~ ;';;; ~ '
....

e Server makes a new Socket to communicate with this client


Socket sock = serverSock.accept();
The acceptO method blocks (just sits there) while
it's waiting for a c1ie.nt Socket connection. When a
client finally tries to connect, the method returns
a plain old Socket (on a different port) that knows
how to communicate with the dient (i.e.. knows the
client's IP address and port number). The Socket is on
Cl different port than the ServerSocket, so that the

ServerSocket can go back to waiting for other clients.


you ar e here. 483
writing a server

PailyAdviceServer code
This program makes a ServerSocket and waits for client requests. When it gets
a client request (i.e. client said new Sockett) for this application) , the server
makes a new Socket connection to that client. The server makes a PrintWriter
(using the Socket's output stream) and sends a message to the client.

(Ye",e",vLeyI t.hese St.yiYl~


db
import java.io.*; weye wov-d-wYa""N 'f
import java .net.*; t.he lode editov-· e.veYe
hit. Yet.~yYI iYl t.he ",I(ldl
p ubl a' c c 1 ass D'l
aa, yAd'
va.ce Server dail'f advile lO"'CS n,. 0'" t.his atta'f r 1"1...' I) 1
O't a .:>"YlYI~. '?

String[] adviceList = {"Take smaller bites", "Go for the tight jeans. No they do NOT
make you look fat.", "One word: inappropriate", "Just for today, be honest. Tell your
boss what you *really* think", "You might want to rethink that haircut."};

public void go() (

try

PrintWriter writer = new PrintWriter(sock.getOutputStream(»;


St~ing ad~ice = ge~vice(); ~
wrJ.ter .p r J.n t l n (advJ.ce); ~ 1'I0W we ~ th Sot
writer . close () ;
System.out.println(advice);
. ~ ...ake d P ~ W.
ket lOlll'lettiol'l to the t1iel'lt to
advile 1'"11, I'"T'Uhl'" dl'ld selld it (pt"il'ltlI'lO> a Stl'"il'lQ
I ... tssa~t. tl'l we dost th Sotk-1. b J
we re dOl'lt with this ll'Itl'll:,
1. e q tta~t
catch{IOException ex) (
ex .printStackTrace();
)
} II close go

private String getAdvice() {


int random = (int) (Math.randomO * adviceList.length);
return adviceList[random] ;

public static void main(String[] args) (


DailyAdviceServer server = new DailyAdviceServer();
server.go{) ;

484 chapter 15
networking and threads

• Client and server applications communicate over a Socket


,.,JI Brain Barbell connection.
• ASocket represents a connection between two applications
How does the server know how to which may (or may not) be running on two different physical
communicate with the dlent? machines.
The client knows the IPaddress and port • A client must know the IPaddress (or domain name) and
number of the server,but how is the server rcp port number of the server application.
able to make a Socket connection with the
• Arcp port is a 16-bi1 unsigned number assigned to a
client (and make Input and output streams)? specific server application. TCP port numbers allow different
clients toconnect to the same machine but communicate
Think about how / when / where the server
with different applications running on that machine.
gets knowledge about the client.
• The port numbers from 0 through 1023 are reserved for
'well-known services' Including HTTP, FTP, SMTP, etc.
therelare~~ • Aclient connects to a server bymaking a Server socket
DUmb ~uestl9ns Socket 9 = new Socket(~127.0.0.1n, 4200);
~: The edvlce server code on the opposite • Once connected, a client can getInput and output streams
page has IJ VERY serious limitation-it looks
from the socket. These are low-level 'connection' streams.
like It can handle only one client at a tlmel
9ock.getInputstream();

.A: Yes,that's right. It can't accept a request


from a client untllit has finished with the
• To read text data from the server, create a BufferedReader,
chained to an InputStreamReader. which Ischained to the
input stream from the Socket.
current c/lent and started the next Iteration of
the infinite loop (where It sits at the acceptO • InpulStreamReader Isa 'bridge' stream that takes in
call until a request comes In, at which time It bytes and converts them totext (character) data. Irs used
makes a Socket with the new client and starts primarily to act asthe middle chain between the high-level
the process over again).
BufferedReader and the low-level Socket input stream.
• To write text data to the server, create a PrintWriter chained
Q.: Let me rephrase the problem: how can directly tothe Socket's output stream. Call the prin~) or
you make a server that can handle multiple
clients concurrently??? This would never prinUnO methods to send Strings tothe server.
work for a chat server, for Instance. • Servers use a ServerSocket that waits forclient requests on
a particular port number.
A: Ah,that's simple, really. Use separate
threads, and give each new client Socket to a
• When a ServerSocket gets a request it 'accepts' the request
bymaking a Socket connection with the client.
new thread. We're just about to learn how to
do that!

you ar e here ~ 485


a simple chat client

Writit1g a Chat Cliet1f


We'll write the Chat client application in two stages. First we'll
make a send-only version that sends messages to the server but
doesn't get to read any of the messages from other participants
(an exciting and mysterious twist to the whole chat room
concept).
Then we'll go for the full chat monty and make one that both
sends and receives chat messages.

Version One: send-only

Code outline
public class SimpleChatClientA

JTextFleld outqoing ;
PrintWrieer writer;
Socket sock ;

public void go() (


II make gui and regist8r a listener with the send button
I I call the setOpNe tworkiDg () method

private void setOpNetworking () (


II make a Socket, then malc.e a PrintWriter
II assign the PrintWriter to writer instance variable

public class SendButtonListener implements ActionLiatener


publio void actionPer£ormed(ActionEvent ev) (
II get thil text from the text field and
II send it to the server using the writer (a Prin tWri tar)
)
II close SendButtonLiatener inner class

II close outer class

486 chapler 15
networking and threads

import java.io.*;
import java.net.·;
import j avax. swing. • ;
import:. java.awt.· ;
import java .awt.event.";

publio class SimpleChatClientA


JTextField outgoing;
Pr:intWriter writer;
Socket sock;
public void go ()
JFrame frame ~ new JFrame(nLudierously Simple Chat elientH);
JPanel mainPanel = new JPanel () ;
outgoing = new JTextField(20);
JButton sendButton = new "Button ("sand") ;
sendButton.addActionListener(new SendButtonListener(»;
mainPanel.add(outgoing);
mainPanel.add(sendButton) ;
frame. getcon ten tPane () . add (Bord.erLayout. CENTER I mainPa.nel);
setUpNetworking():
frame.setSize(400,500):
frama.setViaible(true);
II close go W~'re lI.Sjh~ Iota/host so
y~ ld" ~ the tlitnt
priv~ ~id aetUpNetworkinq () { tL"an $tl"V& 011 one "'dthine

Bock = new Socket(U127.0.0.1 • u'.I'I\clk.e the Sotkd


H
5000); , -n " L
I nil IS wn(Y' .. _ ..
writer = new PrintWriter (sock .getoutputstream(»; ,..d the PY;l'Itw.,.itev (its t.dUed
System. out.println ("networking establiBhed ) : f
t.he 01.) .... ~od .,.i~ht bC~o'fe
H

CAtch (IOException ex) ( d:Oft'\ il'l ~c aff ~UP


8x.printSt&cxTrace() ; u~a~ ~

II close setUpNetworking

public class SendButtonLiBtener implements ActionListener (


public void actionPerformed(ActionEvent .v) (
try (
writer.println(outqoing.getText(»; /'Jow we cfttlodlly do the W'rit.in~.
writer.flush(); Re"'e...be__, the W'rif.t.,. is thained to
the il'l\'1"t ~Cd'" .f.,.o.... tht Sotket, se
catch (Exception ex)( whehtveY wc do cf rriPltll'lO, it ~oa
ex.printstackTrace{); oveY the )ltt.W<Wk -to the SCTVeY!
I
outgoing. setText (U") ;
outgoing.requestFocua() ;
}
II close SendButtonListener inner claas

public static void main (String' CI U'gll) (


DeW Simpl&ChatClientA () . qo () ;
)
II close oueer class

you are here ~ 487


improving the chat client

Version Two: sec:,n:d~_o:;:::;;;;;;;;;~~~~~


~~
and receive _
T~e Strllt\" sends il ftltssa5e to all
tlltllt pariitipallts. as ~ CIs tJ,e
ftlessa~t is rtl.eived by thc ~VCT.
When, a t1ieflt s.e"ds d "'tssa5c, it
does" t afPeal'" i" the il\tOfloi"5
ftleUil5e display area \Antil the
$.Crllel'" $.Cl'ods it to eVt\"yt:n.e.

IlhInk A... ~ o.,'&SU 1


---~ . .-

Big Question: HOW do you get messages from the server?


Should be easy; when you set up the networking make an input stream as well
(probably a BufferedReader). Then read messages using readl.ine/).

Blgger Question: WHEN do you get messages from the server?


Think about that. What are the options?

• Option One: Poll the server every 20 seconds


Pros: Well, it's do-able
Cons: How does the server know what you've seen and what you haven't? The server
would have to store the messages, rather thanjust doing a distribute-and-forget each time
it gets one. And why 20 seconds? A delay like this affects usability, but as you reduce the
delay, you risk hitting your server needlessly. Inefficient.

• Option Two: Read something In from the server each time the user
sends a message.
Pros: Do-able, very easy
Cons: Stupid. Why choose such an arbitrary time to check for messages? What if a user is
a lurker and doesn't send anything?

• Option Three: Read meSAages as soon as they're sent from the server
Pros: Most efficient, best usability
Cons: How do you do you do two things at the same time? Where would you put this code?
You'd need a loop somewhere that was always waiting to read from the server. But where
would that go? Once you launch the CUI, nothing happens until an event is fired by a CUI
component.
488 chapter 15
networking and threads

.In Java you really CAN


walk and chew gum at
the same time.

Multithreading In Java
Java has multiple threading bu ilt right
into the fabric of the language. And it 's a
snap to make a new thread of execution :
Thread t = new Thread() ;
You know by now that we're t. start () ;
going with option three. That's it. By creating a new Thread object,
you've launched a separate thread oj
We want something to run continuously, execution, with its very own call stack.
checking for messages from the server,
but without iruerrupting the users ability to Except fin" one problem.
interact with the CUI.'So while the user is That thread doesn't actually do anything,
happily typing new messages or scrolling so the thread "dies" virtually the instant
through the incoming messages, we it's born . When a thread dies, its new
want something behind the scenes to keep stack disappears again. End of story.
reading in new input from the server.
So we're missing one key component-
That means we finally need a new thread. the thread's job. In other words, we need
A new, separate Slack the code that you want to have run by a
We want everything we did in the Send- separate thread.
Only version (version one) to work the Multiple threading in Java means we
same way, while a new process runs along have to look at both the thread and the job
side that reads information from the that's ron by the thread. And we'll also
server and displays it in the incoming text have to look at the Thread class in the
area. java.lang package. (Remember. java.lang
Well, not quite. Unless you have multiple is the package you get imported for
processors on your computer, each new free , im plicitly, and it's where the classes
Java thread is not actually a separate most fundamental to the language live,
process running on the OS. But it almost including String and Systern.)
feels as though it is.

you are here ~ 489


threads and Thread

Java has tMultiple threads but o.,ly i\ theead is a separate


one Thread class 'Lhr'eud of execution'.
r[1 othet; words. a
We can ralk about thread with a lower-case ' t ' and Thread
with a capital 'T'. When you see thread, we're talking 1l'}Jal'alc call slack.
about a separate thread of execution . In other words,
a separate call slack. When you see Thread, think of J\'-rhrcad is a Java
the Java naming convention. What, inJava, starts with a
capital letter? Classes and interfaces. In this case. Thread
c lass that represenh
is a class in the java.lang package. A Thread object a thh!uJ.
represents a thread. oj execution; you'll create an instance of
class Thread each rime you want to start up a new thread 1'0 111ake a Lhread .
of execu tio n.
l1mkl\ a ThI\\ud.

!hread Thread

Thread
void joinO
void slartO

slatlc void sleepO

main thread another thread java.lang.Thread


started by the code class
A. thread [lower-case 't") is a separate thread of execution. Thread (capital "I") is a class that
That means a separate call slack . Every Java application represents a thread of execution.
starts up a main thread-the thread that puts the It has methods for starting a
mainO method on the bottom of the stack. TheJVM thread.joining one thread with
is responsible fo r starting the main thread (and other another, and putting a thread to
threads, as it chooses, including the garbage collection sleep. (It has more methods; these
th read ). As a programmer, you can write code to start are just th e crucial ODes we need
other threads of your own . to use now).

490 chapter 1 5
networking and threads

What does it ttteat1 to have tMore thatt


ot1e call stack?
With more than one call Slack, you get the appearance of having
multiple things happen at the same time. In reality. only a true
multiprocessor system can actually do more than one thing at a
time, but with Java threads, it can appearthat you're doing several
things simultaneously. In other words, execution can move back
and forth between stacks so rapidly that you feel as though all stacks
are executing at the same time . Remember,java is just a process
running on your underlying OS. So first,Java itselfhas to be 'the
currently executing process' on the OS. But once Java gets its
turn to execute, exactly what does theJVM run? Which bytecodes
execute? Whatever is on the top afthe currently-running stackl
And in 100 milliseconds. the currently executing code might switch
to a different method on a different stack.
One of the things a thread must do is keep track of which statement
(of which method) is currently executing on the thread's stack.
It might look something like this:

o The JVM calls the malnO method.


public static void main (String [l args) (
main thread

main() starts a new thread. The main


thread is temporarily frozen while the new t.startC)
thread starts running.
mainO
Runnable r = new MyThreadJob()j~
main thread user thread A
Thread t new Thread(~ YOl,t'1! le;l'lI~hdt
=
t. start 0 ; -this ...~~. .c.si
Dog d :: new Dog () j d ...o.,.ellt... III J

e The JVM switches between the new


thread (user thread A) and the original
x.goO
runO
main thread, until both threads complete.
main thread user thread A
you a re here. 491
launching a thread

How to launch a new thread:

o Make a Runnable object (the thread's job)


Runnable threadJob = new My~Jnnable()j

Runnable is an interface you'll learn about on the next page.


You'll write a class that implements the Runnoble interface,
and that class is where you'll define the work that a thread
will perform. In other words, the method that will be run
from the thread's new call stack

e Make a Thread object (the worker) and


give it a Runnable (the job)
Thread myThread = new Thread(threadJob) j

Pass the new Runnable object to the Thread constructor.


This tells the new Thread object which method to put on
the bottom of the new stack-the Runnable's runO method.

Q Start the Thread


myThread.start()j
rul'10
Nothing happens until you call the Thread's
startO method. That's when you go from
having just a Thread instance to having a new
thread of execution. When the new thread
starts up. it takes the Runnable object's
runO method and puts it on the bottom of
the new thread's stack.

492 chapter 15
networking and threads

Every fhread tteeds ajob to do.


AtMethod to put Ott the ttew thread stack.

Runnah]e is to a
Thread what a joh is to
a worker. ARunnahle
is the joh athread is
supposed to run.
ARunnah]e holds the
method that goes on
the bottom of the new
thread's stac"k: ru.n().

A Thread object needs a job. Ajob the thread will run when the
thread is started . That job is actually the first method that goes on ~. ts 01\\'1 ()I\e
the new thread's stack, and it must always be a method that looks ~\ . -\:.t.Yht.e de 11\ ~lYI i-tS 31'1
like this: I"e 1\""",,3 e\.II\ '10. Y~O. {R.t"'t.\~ e~YG\ess
I L..A y..,.b It. '10 00 ',s. y~'o It. '" :r
public void run (} ( "'~ I ~t. "'~ LI -t. 'fld'1.)
II code that will be run by the new thread il'l~ht.t SO l'IVt. i-t. i" ,,"3
Lhty ,/0'" \.., \
~ ~"t:\,

How does the thread know which method to put at the bottom of
the slack? Because Runnable defines a contract. Because Runnable
is an interface. A thread'sjob can be defined in any class that
implements the Runnable interface. The thread cares only that you
pass the Thread constructor an object of a class that implements
Runnable.
When you pass a Runnable to a Thread constructor, you're really
just giving the Thread a way to get to a runt) method. You're giving
the Thread itsjob to do.

you are here. 493


Runnable interlace

fo tttake ajob for your thread,


itMpletMet1t the Rut1"able iMterface

public clus MyRunnable ~I..-nt:a

public void go ()
doMore();

public void doMOre() (


SYllItem.out.prll\tln("top 0' the stack");

class ThreadTetlter {
Pass -the "ew ,,<YIN
n
R
~d t.O'I'ISb-l>l.t.o--.
nis
\:II i"std"U ;"to ~e
-tells the -l:.\-I,"~d
'boB:.o ok ~e YltW
I'C'O/

public static void main (Strll\g[] &rgs) {/ '" L d.hod to y...-t 0" -the . "'LLod ~t
wha~ "' LL ...., J s -the tlY'S-t ",n;n
ta k \" OVlCY '0/.,. ~ J
Runnable threadJob = new MyRunnab1e () ; st. · -l} ad willyUY\·
Thread myThread = _ ( ); -the "ew "c

o myThread .start() ; (

o
What do you think the output will be if you run the
ThreadTester class? (we'll find out In a few pages)
main thread new thread

494 chapter 15
networking and threads

The three states of a new thread

Thread t = new Thread(r);


\ \ / / /
NEW RUNNABLE <, RUNNING _

t. start () ;
"
/ { \"
Selected to run

"Call I
S4ly~iu

thai: to¥"
yew..?"

Thread t = new Thread(r); t.start() ; This is the state all threads lust
A Thread instance has been When you start the thread, it after! To be The Chosen One.
created but not started. moves into the runnable state. The Currently Running Thread.
In other words, there is a This means the thread IS ready Only the JVM thread scheduler
Thread object, but no thread to run andjust waiting for its can make that decision. You
of execution. Big Chance to be selected for can sometimes influence that
execution. At this point, there is decision, but you cannot force a
a new call stack for this thread. thread to move from runnable
to running. In the running
state, a thread (and ONLY this
thread) has an active call stack,
and the method on the top of
the slack is executing.

But there's more. Once the thread becomes


runnable, it can move back and forth between
runnable, running, and an additional state:
temporarily not runnable (also known as 'blocked').

you are he re ~ 495


thread states

Typical runnableJrunning loop

RUNNABLE RUNNING

~
Typically, a thread moves back and
forth between runnable and running,
as the JVM thread scheduler selects a
thread to run and then kicks it back
out so another thread gets a chance.

~
Sent bock to runnable
so another thread coo
have a chance

A thread can be made


temporarily not-runnable
TIle thread scheduler can move a RUNNABLE RUNNING
running thread into a blocked state,
for a variety of reasons. For example,
the thread might be executing code
to read from a Socket input stream,
but there isn't any data to read. The
scheduler will move the thread out
of the running state until something
becomes available. Or the executing
code might have told the thread to
put itself to sleep (sleepO). Or the
thread might be waiting because it
tried to call a method on an object,
and that object was 'locked', In that
case, the thread can't continue until
the object's lock is freed by the thread
that has it.
All of those conditions (and more)
cause a thread to become temporarily
not-runnable, sIUfi... ~ waiti"9 .feN' <ll'lOth& th.. . taa to ti.. ish,
....aib,,~ fat' data to be ilvClilablt 0'" tht sh-til"'l
wilit,,~ fo... Cl" objed;'s lock ...

496 chapter 15
networkIng and threads

fhe fhread Scheduler


The thread scheduler makes all the decisions about
who moves from runnable to running. and about when
(and under what circumstances) a thread leaves the
running state. The scheduler decides who runs, and for
how long, and where the threads go when the scheduler
decides to kick them out of the currently-running state.
You can't control the scheduler. There is no API for
calling methods on the scheduler. Most importantly,
there are no guarantees about scheduling! (There are a
few almose-guarantees. but even those are a little fuzzy.)
The bottom line is this: do not baseyour program '$
rorrectness Q1l the schedulerworking in a particular way!
The scheduler implementations are different for
differentJVM's, and even running the same program
on the same machine can give you different results.
One of the worst mistakes new Java programmers
make is to test their multi-threaded program on a
single machine, and assume the thread scheduler will
always work that way, regardless of where the program
runs.
So what does this mean for write-once-run-anywhere?
It means that to write platform-independentJava code, The"fhread
your multi-threaded program must work no matter how
the thread scheduler behaves. That means that you can't
scheduler makes all
be dependent on, for example, the scheduler making the decisions about
sure all the threads take nice, perfectly fair and equal
turns at the running state. Although highly unlikely
who runs and who
today, your program might end up running on aJVM
with a scheduler that says, ~OK thread five, you're up,
doesn't. lIe usually
and as far as I'm concerned, you can stay here until makes the threads take
you're done, when your run () method completes." turns, nicely. But
The secret to almost everything is sleep. That's
right, sleep. Putting a thread to sleep, even for a few
there's no guarantee
milliseconds. forces the currently-running thread to about that. lIe might
leave the running state, thus giving another thread a
chance to run. The thread's sleepO method does come let one thread run
with one guarantee: a sleeping thread will not become
the currently-running thread before the the length of
to its heart's content
its sleep time has expired. For example, if you tell your while the other
thread to sleep for two seconds (2,000 milliseconds),
that thread can never become the running thread again
threads 'starve'.
until sometime after the two seconds have passed.

you are here ~ 497


thread schedu ling

An example of how unpredictable the


scheduler can be...

Running this code on one machine: Produced this output:

public class MyRunnable implements Runnable


java Th~eadTestDrive
public void run()
qo() ; back in main
top 0' the stack
public void go () ~(j.va T l-~;::",adT·c~i:.DJ.--;_ '.· 'c

doMore() ;
top 0' the stack
back in main
public void dOMOre() (
java ThreadTestDrive
System .out.printin("top 0' the stack");
top 0' the stack
back in main
java Th~eadTestnrive

class ThreadTestDrive { top 0' the stack


back in main
public static void main (String[] args) (
j a va T h r e a dT e s ~ D r 1 v e
Runnable threadJob = new MyRunnable () ;
top 0' the stack
Thread myThread = new Thread (thraadJob) ;
back in main
myThread .start();
java T h r R a d TQs t D ~ ~ ~ ~

top 0' the stack

.. ... . .
back in main
Java ThreadTestDr1ve
,.
.' back in main

.. top 0' the stack

498 ch apter 15
networking and threads

How did we end up with different results?

Sometimes it runs like this:

maIn 0 sta rts the The scheduler sends The scheduler tets The new thread goes
new thread the main thread out the new thread away, because its runO
ofrunning and back run to completion, completed. The main
to runnable, so that printing out "top 0' thread once again
the new thread can the stack" becomes the running
run. thread, and prints 'back
In main"

main thread main thread new thread

time

time

y ou are he re . 499
socketconnecUons

:t1erelare~
Dumo "C.UesU9nS
Q.: I've seen examples that don't use a separate
Runnable Implementation, but Instead Just make a
subclass of Thread a nd override the Thread's runO • Athread with a lower-case 't' is a separate thread of
method. That way, you call the Thread's no--arg execution in Java.
constructor when you make the new thread;
Thread t = new Thread(); 1/ no Runnable • Every thread In Java has its own call stack.
• AThread with a capital 'T is the java.lang.Thread
A: Yes, that Is another way of making your own
thread, but think about it from an 00 perspective.
class. AThread object represents a thread of
execution.
What's the purpose of subclassing? Remember that • AThread needs ajob to do. AThread's job isan
we're talking about two different things here-the instance ofsomething that Implements the Runnable
Thread and the thread'slob. From an 00 view, those interface.
two are very separate activities, and belong in separate
classes. The only time you want to subclass/extend • The Runnable Interface has just a single method, runO.
the Thread class,Is if you are making a new and more This is the method that goes on the bottom ofthe new
specific type ofThread .ln other words, if you think of
call stack. Inother words. it isthe first method to run In
the Thread as the worker, don't extend the Thread class
unless you need more specific worker behaviors. But If
the new thread.
all you need Is a new lob to be run by a Thread/worker, • To launch a new thread, you need a Runnable to pass
then Implement Runnable In a separate,job-specific to the Thread's constructor.
(not worker-specific) class.
This is a design Issue and not a performance or • Athread IsIn the NEW state when you have
language Issue.It's perfectly legal to subclass Thread instantiated aThread object but have not yet called
and override the runO method, but It's rarely a good startO.
Idea.
• When you start a thread (by calling the Thread object's
startO method), a new stack Is created, with the
Q.: Can you reuse a Thread object? Can you give It Runnable's runO method on the bottom ofthe stack.
a new Job to do a nd then restart It by calling startO The thread isnow inthe RUNNABLE state, waiting to
agaln7 be chosen torun.

A: No. Once a thread 's runO method has completed,


the thread can never be restarted . In fact, at that
• Athread issaid 10 be RUNNING when the NM's
thread scheduler has selected it to be the currently-
running thread. On a single-processor machine, there
point the thread moves Into a state we haven't talked can be only one currently-running thread.
about-dead. In the dead state, the thread has
finished Its runO method and can never be restarted. • Sometimes a thread can be moved from the RUNNING
The Thread object might stili be on the heap, as a state to a BLOCKED (temporarily non-runnable) state.
living object that you can call other methods on (If Athread mighl be blocked because it's waiting for data
appropriate), but the Thread object has permanently from a stream. or because It has gone tosleep, or
lost its 'thread ness'. In other words, there Is no longer a
because It iswaiting for an object's lock.
separate call stack, and the Thread object Is no longer
a thread. It's Just an object, at that point, like all other • Thread scheduling Isnot guaranteed towork in any
objects. particular way, so you cannot be certain that threads
But, there are design patterns for making a pool of wlll take tums nicely. You can help influence tum-laking
threads that you can keep using to perform different by putting your threads to sleep periodically.
jobs. But you don't do It by restartlng() a dead thread.

500 chapter 15
networking and threads

Putti.,g· athread to sleep


One of the best ways to help your threads take turns is
to put them to sleep periodically. All you need to do
is call the static sleepO method, passing it the sleep
duration, in milliseconds.
Put your thread to sleep
For example:
Thread.sleep(2000);
if you want to he sure
will knock a thread out of the nmning state, and that other threads get a
keep it out of the runnable state for two seconds.
The thread can't become the running thread chance to run.
again until after at least two seconds have passed.
A bit unfortunately, the sleep method throws an
"When the thread wakes
InterruptedException, a checked exception, so all up. it always goes bac"k
calls to sleep must be wrapped in a try/catch (or
declared), So a sleep call really looks like this:
to the runnah]e state
try ( and waitS for the thread
Thread,sleep(2000) ;
catch(InterruptedException ex) ( scheduler to choose it
ax.printStackTrace() ; to run again.
Your thread ",;11 probably never be interrupted [Tom
sleep; the exception is in the API to support a thread
communication mechanism that almost nobody uses in
the Real World. But, you still have to obey the handle
or declare law, so you need to get used to wrapping your
sleepO calls in a try/catch.
Now you know that your thread won't wake up before the
specified duration, but is it possible that it will wake up
some time after the 'timer' has expired? Yes and no. It
doesn't matter, really, because when the thread wakes
up, it always goes bcuk to the rusmable stare! The thread
won't automatically wake up at the designated time and
become the currently-running thread. When a thread
wakes up, the thread is once again at the mercy of
the thread scheduler. Now, for applications that don't
require perfect timing, and that have only a few threads,
it might appear as though the thread wakes up and
resumes running right on schedule (say, after the 2000
milliseconds). But don't bet your program on it.

you are here ~ 501


using Thread.sleep()

Thi~
Usittg sleep to tttake our prograttt is wh.rt. we. WGl'It-a l.or.siskt. (Katy
0+ fYint. st.at.~enh'
",ore predictable. File Ed~ Window Help SnoozeBunon

Java ThreadTestDri ve
Remember our earlier example that kept giving us different
back in main
results each time we ran it? Look back and study the code
and the sample output. Sometimes main had to wait until the top 0' the stack
new thread finished (and printed "top o' the stack"), while .: i a v a ThreadTestDrive
other times the new thread would be sent back to runnable
before it was finished, allowing the maio thread to come back back in main
in and print out "back in main", How can we fix that? Stop top 0 ' the stack
for a moment and answer this question: "Where can you put
javu ThreadTestDriy~
a sleept) call, to make sure that "back in main" always prints
before "top 0' the stack"? back in main
We'll wait while you work out an answer (there's more than top 0' the stack
one answer that would work). java ThreadTestDrive
Figure it out? back i n main
top 0' the stack
public class MyRunnable implements Runnable ( java ThreadTestDri ve
back in main
public void run() (
go() ; top 0 ' the stack

public void go ()

Uy (
..
Thread ••leep(2000); ., ,.
catch (Ifttarrupt.eclException ex) ( . J

ex.pr1ntStackTrace();
.,
"
"

public void dOMOre() (


System. out. prinUn ("top 0' the stack");

class ThreadTestDrive (
public static void mAin (String[] arqs)
Runnable theJob - new MyRunnable();
Thread t::: new Thread(theJob);
t. start () ;
Systam.out.println(~back in main");

502 chapter 15
networking and threads

Maki.,g a.,d sfarti.,g two threads


Threads have names. You can give your threads a name of
your choosing, or you can accept their default names. But the
cool thing about names is that you can use them to tell which
thread is running. The following example starts two threads.
Each thread has the same job: run in a loop. printing the
currently-running thread 's name with each iteration.

public class RunThreads implements Runnable (


~\t i,..st;ll'tt.·
public static void main(String[J arqa) ( ..... Ma\(t O'f\t RIl'l'ol"3
RunThreads runner '" nitW RunThreads () ;
Thread alpha = new Thread (runner); ~ Mcl~ th two
Thread beta '" new Thread(runner); ~ . 'r,edtb, with tht 1,I>"t R""Ylable (the
alpha. setName ("Alpha thread"); Scl"'e Job--...,e II 1k ...~t about t.he "-two th..-t.ads
t:a
beta. 88tName ("Beta thread"); ~ and O?Ie R"""\dblt. In a ra~es).+tvJ
alpha . 8 tart () ; ~ Na",t. the tht"edds.
beta. start (); ~ start the tht"t.clds.
LL
~t.h ~vtao \fIi\\ YIlYl V\~~-J
""-'A" ~is \00f1
public void run () { . L' it. 1'0",1: e.)l.h tu"t.·
for (int i =
0; i < 25; i++) { P"r\Yl~'''~
1
'V

String threadName K Thread. currentThread () .getName();


Syatam.out.println(threadName + " is running");

File Ed~ WindOW H~p C&ntaun

Alpha thread is running


Alpha thread is running
What will happe.,? Alpha thread is running
Beta thread is running
Wlll the threads take turns? Will you see the thread names Alpha thread is running
alternating? How often will they switch? With each iteration? Beta thread is running
After five iterations? Beta thread is running
Beta thread is running
You already know the answer: we don't knowlIt's up to the
Beta thread is running
scheduler. And on your as, with your particular JVM, on
Beta thread is running
your CPU, you might get very different results.
Beta thread is running
Running under as x 10.2 (Jaguar), with five or fewer Beta thread is running
iterations, the Alpha thread runs to completion, then Beta thread is running
the Beta thread runs to completion. Very consistent. Not Beta thread is running
guaranteed. but very consistent. Beta thread is running
But when you up the loop to 25 or more iterations, things Beta thread is running
start to wobble. The Alpha thread might not get to complete Beta thread is running
all 25 iterations before the scheduler sends it back to Beta thread is running
runnable to let the Beta thread have a chance. Beta thread is running
Alpha thread is running

you a re here . 503


aren't threads wonderful?

UtM, yes. There IS a dark side.


fhreads ca., lead to co.,curre.,cy 'issues:
Concurrency issues lead to race conditions. Race conditions
lead to data corruption. Data corruption leads to fear... you
know the rest.
It all comes down to one potentially deadly scenario: two or
more threads have access to a single object's daia: In other
words, methods executing on two different stacks are both
calling, say, getters or setters on a single object on the heap.
It's a whole 'left-hand-doesn't-know-what-the-right-hand-
is-doing' thing. Two threads, without a care in the world,
humming along executing their methods, each thread
thinking that he is the One-True Thread. The only one
that matters. After all, when a thread is not running, and in
runnable (or blocked) it's essentially knocked unconscious.
When it becomes the currently-running thread again, it doesn't
know that it ever slopped.

504 chap ter 15


networking and threads

Marriage in Trouble.
Can this couple be saved?
Next, on 8 very special Dr.Steve Show

[Transcript from episode #42)

Welcome to the Dr. Steve show.


We've got a story today that's centered around the top two reasons why
couples split up-finances and sleep.
Toctaor's troubled pair, Ryan and Monica., share a bed and a.
bank account. But not for long if we can't find a solution. The
problem? The classic 'iiwo people-one bank account" th:1ng.
Here's how Monica desoribed it to me:
"RiYan and I agreed t.hat neither crus will overdraw the checkl.ng account.
So the procedure 1S, whoever wants to withdraw money must check the
balance in the account beiore rn a k1ng the withdrawal. It all seemed so
simple. But suddenly we're bouncing checks and getting hit with overdraft.
fees I
I thought it wasn't possible, I thought our procedure WBE safe. But then
this happened:

Ryan needed $50, so he checked the balance in the account,


and saw that it WW3 $100. No problem. So, he plans to
withdraw the money. But first he faI1B asleep I

And that's where I come in, while ~'s still BEleep, and
now Iwant to withdraw $100. I check the balance, and
it's $100 (because !Wan's st1ll asleep and ha.sn'tyet made
his withdrawal), so I think, no problem. So I make the
withdrawal, and agatn no problem. But then Ryan wakes up,
completes h1s withdrawal, and we're suddenly overdrawn! He didn't
even know that he fell asleep, so he just went ahead and completed his
tra.nsaot1on without checking the balance again. You've got to help us Dr.
Steve I"

Is there a solution? .Are they doomed? We can't stop Ryan from fa.lllng
asleep, but can we make sure that Monica can't get her hands on the bank
account until after he wakes up?
Take a moment and tb.1n.k about that while we go to a. commercial break.

you a re here. 505


Ryan and Monica code

The Ryatt at1d Mottica proble'lt itt code


The following example shows what can happen when two
Runnable
threads (Ryan and Monica) share a singleobject (the bank
account).
The code has two classes, BankAccount, and
MonicaAndRyanJob. The MonicaAndRyanjob class
implements Runnable, and represents the behavior that Ryan T
and Monica both have--checking the balance and making I
I
withdrawals. But of course, each thread fulls asleep in between BankAccount I
checking the balance and actually making the withdrawal. intbalance I

The MonicaAndRyanJob class has an instance variable of type gelBalance() RyanAndMonlcaJob


BankAccount., that represents their shared account. withdrawO BankAccount account
The code works like this: runO
makeWithdrawal0

• Make one Instance of RyanAndMonlcaJob.


The RyanAndMonicaJob class is the Runnable (the job to do),
and since both Monica and Ryan do the same thing (check
balance and withdraw money), we need only one instance. In the runO method, do
RyanAndMonicaJob theJob::: new RyanAndMonica.Job 0 ; exactly what Ryan and
Monica would do-check


the balance and, if
Make two threads with the same Runnable there's enough money,
(the RyanAndMonicaJ ob instance) make the withdrawal.
Thread one::: new Thread (theJob) ;
Thread two = new Thread (theJob) ;
This should protect
against overdrawing the
account.
• Name and start the threads
Except••• Ryan and
one.setName(~Ryan"l;
Monica always fall
two . setN8IJle ("Monica") ;
one .start() ; asleep ~r they
two. start 0 ; check the balance but
before they finish the
withdrawal.
• Watch both threads execute the runO method
(check the balance and make a withdrawal)
One thread represents Ryan. the other represents Monica.
Both threads continually check the balance and then make a
withdr<lwal. but only if it's safe.!
if (ACcount.get.BalanceO >= amount) (
try (
Thread. sleep (SOOl ;
I catch(InterruptedException ax) (ex.printStackTrace(); )

508 chapter 15
networking and threads

The Ryat1 at1d MOt1ica exalltple


class BankAccount { L tarts ltIith a
private int balance = 100; ~~_ _~ Tne attov.rI'; s
'oa\aY\l.e ok fI OO.
public int getBalance()
return balance;
}
public void withdraw(int amount) {
balance = balance - amount;

public class RyanAndMonicaJob implements Runnable {

private BankAccount account = new BankAccount();

public static void main (String [] args) {


RyanAndMonicaJob theJob = new RyanAndMonicaJob (); ~ frlsta .
Thread one = new Thread (theJob) ; ~ r.t1ai:e the ~"r.tldble (-ob)
Thread two = new Thread (theJob) ; +-- Make two .Lh d ~
~I-eas '.
one. setName ("Ryan") ; job. nat ' ~IVlr.g eath thl-ead th
two. setName ("Monica") ; alloLir.t . "'ear.s both thl-eads will b e ~"'e R"htldbl e
one. start () ; Ir.stahle val-iable ir. the R e alleSSl h!} the One
two. start () ; "r.tldble tlass.

tn\'"ead loo\'s t.nYO\l.~n arid t.\'"·le


s
public void run ( ) {
for (int x = 0; x < 10; x++) {
makeWithdrawl (10) ;
t
IYl t.ne yv.YlO .",e+.h ' ltIitn eat.n it.e\'"atioYl' AHe\'" t.~~
od
to make a 1tI,t.nd\'"altla 'DalaYlte oY\l.e a~aiYl to see I
if (account.getBalance() < 0) { ltIit.nd\'"altla\, 'It. t.net.ks t.ne
ltl".
System.out.println("OVerdrawn!"); t.he attOv."t. is ol/eV'dya

ehetk the attov.Ylt. bala"t.e, aYld it t.heYe~s Ylot. IS


} e"ov.~h mOrle~, we j\lSt. f\'"int. a ",essa~e. I theY~ t.e
. , . . V e n o v . h, ltIe ~o to sleef, t.hen ltIake v.? a"d t.OWIf e
pr1;rate v01d makeW1 thdrawal (1nt amount) { ~ 't.hdv-altlal, '\lSt like R'fan did.
1f (account . getBalance () >= amount) { t.he WI J
System.out.println(Thread.currentThread() .getName() + " is about to withdraw");
try {
System.out.println (Thread . currentThread() .getName() + " is going to sleep");
Thread .sleep(500);
} catch(InterruptedException ex) {ex.printStackTrace(); }
System.out.println (Thread. currentThread() .getName() + " woke up.");
account.withdraw(amount);
System.out.println (Thread. currentThread() .getName() + " completes the withdrawl");
}
else {
System.out.println("Sorry, not enough for" + Thread.currentThread() .getName(»;

We p"i ih a b"hlh of D>oiht staL L


se h l' h i ' UhoIeh\;S so we tar.
e w ae; s appehih!} as it l-"hS.
you a re he re ~ 507
!"Cyan ana MOniCa OUtput:

FlI& Edll Window Help VI£ll

Ryan is about to withdraw


Ryan is going to sleep The makeWithdrawalO method
always checks the balance
Monica woke up.
before making a withdrawal,
Monica completes the withdrawl
but stili we overdraw the
Monica is about to withdraw account.
Monica is going to sleep
Ryan woke up . Here's one scenario:
Ryan completes the withdrawl Ryan checks the balance, sees that
Ryan is about to withdraw there's enough money, and then falls
Ryan is going to sleep asleep.
Monica woke up. Meanwhile, Monica comes in and checks
Monica completes the withdrawl the balance. She, too, sees that there's
Monica is about to withdraw enough money. She has no Idea that
Ryan Is going to wake up and complete a
Monica is going to sleep
withdrawal .
Ryan woke up.
Ryan completes the withdrawl Monica falls asleep .

Ryan is about to withdraw Ryan wakes up and completes his


Ryan is going to sleep withdrawal.
Monica woke up. Monica wakes up and completes her
Monica completes the withdraw1 withdrawal. Big Probleml In between the
time when she checked the balance and
Sorry, not enough for Monica
made the withdrawal, Ryan woke up and
Sorry, not enough for Monica pulled money from the account.
Sorry, not enough for Monica
Monica's check of the account was
Sorry, not enough for Monica not valid, because Ryan had already
Sorry, not enough for Monica checked and was stili In the middle of
R~'an woke up.
making a withdrawal.

, . Ryan completes the withdrawl


Overdrawn'
Monica must be stopped from getting
Into the account until Ryan wakes up and
flnishes his transaction. And vice-versa.
Sorry, not enough for Ryan
Overdrawn!
Sorry, not enough for Ryan
Overdrawn!
Sorry, not enough for Ryan
Overdrawn!

508 chapter 15
networking and threads

They need a lock for account access!

The lock works like this:

~ There's a lock associated with the bonk


account transaction (checking the balance The bank account

f
and withdrawing money). There's only transaction is
one key, and it stays with the lock until unlocked when
somebody wants to access the account. nobody Is using
the account.

When Ryan
When Ryan wants to access the bank
wants to access
account (to check the balance and withdraw
the account, he
money), he locks the lock and puts the key
secures the lock
in his pocket. Now nobody else can access
and takes the key.
the account, since the key is gone.

Ryan keeps the key in his pocket until he


When Ryan Is
finishes the trQl\SQctlon. He has the only

f
finished, he
key, so Monica can't access the account
unlocks the lock
(or the checkbook) until Ryan unlocks the
and returns the
account and returns the key.
key. Now the key
Now, even if Ryan falls asleep ofter he is available for
checks the balance, he has a guarantee Monica (or Ryan
that the balance will be the some when he again) to access
wakes up, because he kept the key while he the account.
was asleep!

you are here ~ 509


using synchronized

We t1eed the Itt akeWithdrawal () tttethod


to rut1 as otte atomic thit1Q.
We need to make sure that once a thread enters the
makeWithdrawal() method, it must be allowed to finisb the method
before any other thread can enter.
In other words, we need to make sure that once a thread has
checked the account balance, that thread has a guarantee that it can
The synchronized
wake up and finish the withdrawal before any other thread can check the keyword means that
account balance! a thread needs a key
Use the synchronized keyword to modify a method so that only in order to access the
one thread at a time can access it synchronized code.
That's how you protect the bank accountl You don't put a lock on
the bank account itself; you lock the method that does the banking To protect your data
transaction . That way. one thread gets to complete the whole (like the bank account),
transaction, start to finish . even if that thread falls asleep in the synchronize the
middle of the method I
methods that act on
So if you don't lock the back account, then what exactly is locked? Is that data.
it the method? The Runnable object? The thread itself?
We'll look at that on the next page. In code, though, it's quite
simple-just add the synchronized modifier to your method
declaration:

private synchronized void makeWithdrawal(int amount) {


if (account.getBa1ance () >= amount) {
Syetam.out.println(Thread.current'l'hreadO .q4ItNameO +" is about to withdraw");
try (
System. out.println (Thread. currentThread () .getName() + ~ 1s going to sleepll);
Thread.s1eep(SOO) ;
} eatch(InterruptedException ex) (e.x.printStackTraoeO; I
System. out. println (Thread. ourr8ntThread () . gatName 0 + " wob up. ") ;
aocount ..withdraw (amount) ;
System. out.println (Thr8ad. currentThread 0 .qetNlUll80 + " completes the withdraw1"};
else (
System. out.print1n ("Sorry, not enough for" + Thread. currentThread () .getN~(»;

(Nou ~or 'f0'0l ph'fsil.s-s.avvy \"~ad~ : 'f~' !he t.onv~ntion of I&S;,,~ the 'oIcwl! 'at-.il.' hcY~ does 1\0-1: \"e.flut
the whol~ s..bato.-il. pard:jl.l~ t.hil\~ . ni"k /'i~, t\tJt Eil\1Wl\, whe" 'fou ha\" tl.e 'Hew-a 'ato.-it' i" t.he
1.0JIU'j(t 0+ threads or tta"sal.i;iOt\1. ~t'(, it's Mt OUR ~vtrltOl\ . l.f WE \IItl"t i.... t.haY~e, 'Wt'd appl'f
t4tisc\'lhC'r~'s Ul\l.crt<lif\t'f P\,,;l\l.ir1e -to fYttt'( ... lAt.h eVCt"ytl.i"9 relaW to t.hrc.alUJ

510 chapter 15
networking and threads

Ushtg at1 objeet~ lock


zvery object has a lock. Most of the time, the Hey, this object's
k is unlocked, and you can imagine a virtual takeMonevO method is
. sitting with it. Object locks come into play synchronized . I need to get
Iy when there are synchronized methods. this object's key before I
\n e n an object has one or more synchronized
ethods, a thread can enter a syrn:hroniz.ed
-ethod only if the thread can get the key io the
J,ject's wckJ
e locks are not per method, they
ar e per object. If an object has two
-nchron ized methods, it does not
simply mean that you can 't have two
th reads entering the same method, It
ea ns you can't have two threads entering
) of the synchronized methods.
Think about it. [fyou have multiple
methods that can potentially act on an
o bj ect 's instance variables, all those methods
need to be protected with synchronized.
The goal of synchronization is to protect Every Java object has a Iocl.
cri tical data. But remember, you don't lock the
data itself, you synchronize the methods that
AIocR has only one 'key. .
access that data .
Most of the tiJtle, the IocR is
So what happens when a thread is cranking
through its call stack (starting with the nm() unlocked and nobody cares.
method) and it suddenly hits a synchronized
method? The thread recognizes that it needs But if an ohject has
a key for that object before it can enter the
method. It looks for the key (this is all handled
synchronized methods, a
by theJVM; there's no APT in java for accessing thread can enter one of the
object locks), and if the key is available. the
thread grabs the key and enters the method .
synchronized methods ONLY
From that point forward, the thread hangs on if the "key for the object's Ioc"k
to that key like the thread's life depends on
it. The thread won ' t give up the key until it
is available. In other words.
completes the synchronized method. So while only if another thread hasn't
that thread is holding the key, no other threads
can enter any of that object's synchronized already grahbed the one "key.
methods, because the one key for that object
won 't be available.

yo u a re he re. 511
synchronization matters

N
fhe dreaded "Lost Update probleiM
H ere's another classic concurrency problem, that comes from the database world. It's
closely related to the Ryan and Monica story, but we'll use this example to illustrate a few
more points.
The lost update revolves around one process:
Step I : Get the balance in the account
int i = balance;
Step 2: Add 1 to that balance
balance =i + 1;
The trick to showing this is to force the computer to take two steps to complete the change
to the balance. In the real world, you'd do this particular move in a single statement:
balance++;
But by forcing it into two steps, the problem with a non-atomic process will become clear.
So imagine that rather than the trivial "get the balance and then add I to the current
balance" steps, the two (or more) steps in this method are much more complex, and
couldn't be done in one statement.
In the "Lost Update" problem, we have two threads, both trying to increment the balance.
class TestSync implements Runnable {

private int balance;

public void run()


for(int i = 0; i < 50; i++) {
increment 0 ;
System.out.println("balance is " + balance);

public void increment() {


int i = balance;
balance = i + l;~ H~r~'s ih~ trlAtial pari! w .
additlQ / 1- . I I
~ Il'ltr~""~ll't ih
J 1:0 whai~v~r ih I oa alll~ by ~
TIME WE READ IT ( ~ va lA~ o.f balal'll~ was AT THE
ih~ CURREAM- I . )ra h~r ihall addil'lQ / 1 h 1-.
" I va lA~ IS J 1:0 W a~V~r
public class TestSyncTest {
public static void main (String[] args) {
TestSync job = new TestSync();
Thread a = new Thread(job);
Thread b = new Thread(job) ;
a.startO;
b.startO;

512 chapter 15
networking and threads

LetJs rut1 this code...


Thread A runs for awhile
Put the value of balance into variable i.
Balance is O. so ; is now O.
Set the value of balance to the result of i + 1.
Now balance Is 1.
Put the value of balance Into variable i.
Balance Is 1, so I is now 1.
Set the value of balance to the result of I + 1.
Now balance Is 2.

Thread B runs for awhile


Put the value of balance into variable I.
Balance Is 2, so i is now 2.
Set the value of balance to the result of I + 1.
Now balance Is 3.
Put the value of balance Into variable i.
Balance Is 3, so I is now 3.

(now thread B is sent back to runnebte,


before It sets the value of balance to 4]

Thread A runs again, picking up where. it left off


Put the value of balance Into variable I.
Balance Is 3, so I is now 3.
Set the value of balance to the result of I + 1.
Now balance Is 4.
Put the value of balance Into variable I.
Balance Is 4, so I Is now 4.
Set the value of balance to the result of I + 1.
Now balance is 5.

Thread B runs again, and picks up exactly where it left offl


We lost the last updates
Set the value of balance to the result of I + 1.
that Thread A madel
Now balance Is ~ ~ II Thread B had preViously
. "·\\t~S .. done a 'read' of the value
n __ ead A",ydat.ed It. to 1:), blOt. of balance, and when B
\'\0,", B ta...e bdl.\( alia ~Ul'fea woke up, It Just kept going
to!> o.f t.he "fdat.e A....ade,
0\'\ as If It never missed a beat.
as it A's "'fdclU IIt"'~ hcll1't\'\ea.
you are here. 513
synchronizing methods

Make the ittcretttettt() tMethod atotttic.


Syttchrottize it!
Synchronizing the incrernenu) method solves the "Lost
Update" problem, because it keeps the two steps in the method Once a thread enters
as one unbreakable unit. the method, we have
to make sure that all
the steps in the method
public synchronized void increment() {
int i-balance; complete (as one
balance = i + 1; atomic process) before
} any other thread can
enter the method.

Q..: Sounds like It's a good Idea to synchronize


everything,Just to be thread-safe.

J\: Nope, it's not a good Idea. Synchronization doesn't


com e fOT free. FIrst, a synchronized method has a certai n
amount of overhead. In other words, when code hits a
synchronized method, there's going to be a performance hit
(although typically, you'd never notice It) while the matter of
HI s the key avallabl e7"Is resolved.
Second, a synchron Ized met hod can slow you r prog ram
down because synchronization restricts concurrency. In
other words, a synchronized method forces other threads to
get in line and walt their turn. This might not be a problem
In your code, but you have to consider It.
Third, and most frightening, synchronized methods can lead
to deadlockl (Seepage 516.)
A good rule of thumb Is to synchronize only the bare
minimum that should be synchronIzed. And In fact, you
can synchronize at a granularity that's even smaller than
a method. We don't use it In the book, but you can use the
synchronized keyword to synchronize at the more fine-
grained level of one or more statements, rather than at the
whole-method level.

514 chapter 15
networking and threads

• Thread A runs for awhile


Attempt to enter the incrementO method.
The method is synchronized, so get the key for this object
Put the value of balance into variable i.
Balance is 0, so i is now 0.
Set the value of balance to the result of i + 1.
Now balance is 1.
Return the key (it completed the incrementO method).
Re-enter the incrementO method and get the key.
Put the value of balance into variable i.
Balance is 1, so i is now 1.

[now thread A is sent back to runnable, but since it has not


completed the synchronized method, Thread A keeps the key]

• Thread B is selected to run

, Attempt to enter the incrementO method. The method is


synchronized, so we need to get the key.
The key is not available.

[now thread B is sent into a 'obj ect lock not available lounge]

• Thread A runs again, picking up where it left off


~ (remember, it still has the key)
.~ Set the value of balance to the result of i + 1.
Now balance is 2.
Return the key.

[now thread A is sent back to runnable , but since it


has completed the incrementO method, the thread
does NOT hold on to the key]

• Thread B is selected to run

I Attempt to enter the incrementO method. The method is


synchronized, so we need to get the key.
This time, the key IS available, get the key.
Put the value of balance into variable i.
[continues to run...]

you are here ~ 515


thread deadlock

The deadly side ofsyttchronizatiott


Be careful when you use synchronized code, because nothing
will bring your program to its kn ees like thread deadlock.
Thread deadlock happens when you have two threads, both of
which are holding a key the other thread wants. There's no way
out of this scenario, so the two threads will simply sit and wait.
And wait. And wait.
If you're familiar with databases Or other application servers,
you might recognize the problem ; databases often have a
locking mechanism somewhat like synchronization. But a
real transaction management system can sometimes deal with All it takes for
deadlock. It might assume, for example, that deadlock might deadlock are two
have occurred when two transactions are taking too long to objects and two
complete. But unlike Java, the application server can do a threads.
"transaction rollback" that returns the state of the rolled-back
transaction to where it was before the transaction (the atomic
part) began .
Java has no mechanism to handle deadlock. It won't even know
deadlock occurred. So it's up to you to design carefully. If you
find yourselfwriting much multithreaded code, you might
want to study ".Java Threads" by Scott Oaks and Henry Wong
for design tips on avoiding deadlock. One of th e most common
tips is to pay attention to the order in which YOUl' threads are
started.

A simple deadlock scenario:

Thread A enters a Thread B enters a Thread A wakes up (stlll


synchronized method synchronized method holding the (00 key)
of object foo, and gets of object bar, and gets and tries to enter a
the key." the key. if synchronized method on
I faa I bar object bar, but can't get
that key because B has
It. A goes to the waiting
Thread A goes to
sleep, holding the 1
Thread B tries to enter
a synchronized method 1 lounge, until the bar key Is
available (it never will bel)
too key. "...
, -r
of object too, but can't
get that key (bacause Thread A can't run until
A has It). B goes
it can get the bar key,
to the waiting lounge. but B is holding the bar
until the Ioo key is
key and B can't run until It
available. B keeps the
too gets the too key thai A Is
bar key. holding and ...

516 chapte r 15
networking and threads

-
• The static Thread.sleepf) method forces a thread to leave the
running state for atleast the duration passed to the sleep method.
Thread.sleep(200) puts a thread tosleep for 200 milliseconds.
• The sleepO method throws a checked exception (InterruptedExceptionl,
so all calls to sleept) must be wrapped in a try/catch. ordeclared.
• You can use sleepO tohelp make sure all threads geta chance torun,
although there's no guarantee that when a thread wakes up it'll go to the
end ofthe runnable line. Itmight for example, go right back to the front.
In most cases, appropriately-timed sleepO calls are all you need to keep
your threads SWitching nicely.
• You can name a thread using the (yet another surprise) setNameO
method. All threads get a default name, but giving them an explicl1 name
can help you keep track of threads. especially if you're debugging with
print statements.
• You can have serious problems with threads if two ormore threads have
access tothe same object on the heap.
• Two ormore threads accessing the same object can lead to data
corruption if one thread, for example, leaves the running slate while stili
inthe middle ofmanipulating an object'scritical state.
• To make your objects thread-safe, decide which statements should be
treated as one atomic process. In other words, decJde which methods
must run 10 completion before another thread enters the same method
on the same object.
• Use the keyword synchronized tomodify amethod declaration,
when you want toprevent two threads from entering that method.
• Every object has a single lock, with a single key forthat lock. Most ofthe
time we don't care about that lock; locks come into play only when an
object has synchronized methods.
• When a thread attempts to enter a synchronized method, the thread
must get the key for the object (the object whose method the thread
Is trying torun). If the key Is not available (because another thread
already has it), the thread goes Into a kind ofwaiting lounge. until ttre key
becomes available .
• Even Ifan objecl has more than one synchronized method, there isstill
only one key. Once any thread has entered a synchronized method on
that object, no thread can enter any other synchronized method on the
same object This restriction lets you protect your data by synchronizing
any method that manipulates the data.

you are here ~ 517


final chat clie nt

New and itltproved SitltpleChafClienf


Way back near the beginning of this chapter, we built the SimpleChatClient that could send
outgoing messages to the server but couldn't receive anything. Remember? That's how we
got onto this whole thread topic in the first place, because we needed a way to do two things
at once: send messages to the server (in teracting with the GUI) while simultaneously reading
incoming messages from the server, displaying them in the scrolling text area.
import java.io.*; Yes, there really IS an
import java.net.*; end to this thapter.
import java.util.*; Blott not yet...
import javax.swing.*;
import java .awt.*;
import java.awt.event.*;

public class SimpleChatClient

JTextArea incoming;
JTextField outgoing;
BufferedReader reader;
PrintWriter writer;
Socket sock;

public static void main (String[] args) {


SimpleChatClient client = new SimpleChatClient();
client. go 0 ;

public void go ()

JFrame frame new JFrame(~Ludicrously Simple Chat Client");


JPanel mainPanel = new JPanel() ;
incoming = new JTextArea(lS,SO);
incoming.setLineWrap(true);
incoming.setwrapStyleWord(true) ;
incoming.setEditable(false);
JScrollPane qScroller = new JScrollPane(incoming) ;
qScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL SCROLLBAR ALMAYS) ;
qScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
outgoing = new JTextField(20);
JButton sendButton = new JButton(~Send");
sendButton.addActionListener(new SendButtonListener(»;
mainPanel. add (qScroller) ; We're startin~ a th
mainPanel.add(outgoing); / lotSinli a hew ' nlew read,
Rlothnabl Inner
it +
(- b)t: ass as
. 1 dd (dB ) s. J
maJ.nPane . a sen utton; ,;he
setUpNetworking () ; thl"ead. Th e ,o~ th~
s. f' e l"ead s Job IS
l;O l"ead 1'rOft> the stl"vel"'s
SOlk~t streaft>, disrlayih~
any 11,~Oft>ih~ ft>essa~es in the
frame .getContentPane 0 . add (BorderLayout . CENTER, mainPanel); Sll"o In~ teXt area.
frame.setSize(400,SOO);
frame .setVisible(true);

ii close g o

518 ch apter 15
networking and threads

private void setUpNetworking() {

tty {
sock = new Socket("127.0.0.1 H , 5000);
:J:nputStreamReader streamReillder =
new InputStreamRaader(sock.getInputStream();
reader ~ new BufferedReader(streamReader);
writer = new PrintWriter(sock.getoutputStream(); tn· t
Systam.out.prinUn ("networking established") ; I • ~e sot.Krt to ~et. e \,lSil\~ 'dYl'
catch(IOException ex) ( Wt.'rc 14 1: { strca".s. We ""crt. alyea '1 cr
ax. prin tStackTrAce () ; alld 0Il-lf" stY to strUi to 1:.ht. ~ J

) t.M. oJ:.YI't. J sb-u'" so


ea.", tnt. il\flot
I I close setUpNet:working \,,,rt f\CI'fl we'r( ,v.1;J ~Yc.ld ea.. . ~et.
r
J

that the
W\ts53¥S ",'r0W\ ~
I'L
he ~t.Y.

public class SendButtonListener implements ActionLietener


public void actionPerfo~(ActionEventev) {
try (
writer.prinUn(outgoing.getText(» ;
writer.llush() ;

cateh(Exception ex) (
ex.printStackTr8ce() ;
}
outgoing.setText("");
outgoing.requestFocus() ;
}
II close inner cl~ss

lex.priilt:StaCJC'1'rac. n ;}

II close outer class

you are here. 519


chat server code

_
.
.IJ ,
Readj-"a"e
Cade .
fhe really really sltttple Chat Server
You can use this server code for both versions of the Chat Client, Every possible
disclaimer ever disclaimed is in effect here. To keep the code stripped down to the
bare essentials, we took out a lot of parts that you'd need to make this a real server.
In other words, it works, but there are at least a hundred ways to break it. If you
want a Really Good Sharpen Your Pencil for after you 've finished this book, come
back and make this server code more robust.
Another possible Sharpen Your Pencil, that you could do right now, is to annotate
this code yourself. You'll understand it much better if you work out what's
happening than if we explained it to you. Then again, this is Ready-bake code,
so you really don't have (0 understand it at all. It's here just to support the two
versions of the Chat Client.

import java.io.*;
import java.net.*;
import java.util.* ;

public class VerySimpleChatServer

ArrayList clientOUtputStreams;

public claS8 ClientBandler implements Runnable (


BufferedReader reader;
Soc:ket sock;

public: ClientBandler (Socket clientSocket) {


try (
sock = clientSocket;
InputStreamReader isReader :: new InputStreamReader (sock . getlnputStream () ) ;
reader:: new BufferedReader (isRl!!lader) ;

• catch(Exception ex) (ex .printStackTrace();)


) II close constructor

public void run () {


String message;
try (
while «(message = reader.readLine(» !a null)
System.out.println( "raad " + message) ;
tellEveryone(message);

• II close while
catch(Excaption ex) (ex .printStackTr4l:e();)
) 1 / close run
II close inner class

520 chapter 15
networtOng and threads

public static void main (String[] args)


new VerySimpleChatServer().go();

public void ge() (


clientOutputSt.reams ;; Dew ArrayList 0 ;
try (
ServerSocket serverSock;; new SarverSocket(5000);

wh.i.le(true) (
Socket clientsocltet = servarSoclt. aCC8pt () ;
Pr1.ntwrlter writer"" new PrintWriter(clientSoaket .qetoutputStream();
clientOutputst.relUD8. add (writer) ;

Thread t = new Thread(new ClientHandler(clientsoOket»;


t. start () ;
System.out .pr1.ntln("get a connection H ) i

catch (Exception ex) (


ax.printStackTrace();


II close go

public void tel~one(Str1.ngmessage)

Iterator it = cliantoutputStreama.iterator();
while(it.hasNaxt(» (
try (
PrintWriter writer ;; (Printwrlter) it.naxtO;
writer .println(message) i
wri tar .fluBh () ;
catch (Exception ex) {
ex.printstacltTrace();

II end while

II close tellEveryooe
I close class

you are here. 521


synchronlzaUon questions

:t1erel~~
DumlJ ~uesti9ns
Q.: What about protecting static Q.: Why don't you just synchronize
variable state 7 If you have static all the getters and setters from the
methods that change the static variable class with the data you're trying to
state, can you stili use synchronization 7 protect? Like, why couldn't we have
synchronlzed Just the checkBalanceO

A.: Yesl Remember that static


methods run against the classand not
and wlthdrawO methods from class
BankAccount. Instead of synchronizing
the makeWlthdrawalO method from
against an Individual instance ofthe class. the Runnable's class?
So you might wonder whose object's lock
would be used on a static method? After
all, there might not even be any instances
of that class. Fortunately, Just as each
A: Actua lIy, we should have
synchronized those methods, to prevent
object has Its own lock- each loaded class other threads from accessing those
has a lock. That means that If you have methods In other ways.We didn't bother,
three Dog objects on your heap, you have because our example didn't have any
a total of four Dog -related locks.Three other code accessing the account.
belonging to the three Dog Instances,
But synchronizing the getters
and one belonging to the Dog class Itself.
and setters (or in this casethe
When you synchronize a static method,
checkBalanceO and wlthdrawO) isn't
Java uses the lock of the class itself. So If
enough . Remember, the point of
you synchronize two static methods In a
synchronization Is to make a speciflc
single class,a thread will need the class
section of code work ATOMICALLY. In
lock to enter either of the methods.
other words, It 's not Just the individ ual
methods we care about, It's methods
Q..: What are thread prlorltlesll'Ye that require more than one step to
completel Think about lt.jf we had not
heard that's a way you can control
scheduling. synchronized the makeWlthdrawalO
method, Ryan would have checked the
balance (by call ing the synchronized
A.: Thread priorities might help
you Influence the scheduler, but they
checkBalanceOl, and then Immediately
exited the method and returned the keyl
stili don't offer any guarantee. Thread Of course he would grab the key again,
priorities are numerical values that tell after he wakes up, so that he can call
the scheduler (If It cares) how Important a the synchronized withdrawO method,
thread Is to you . In general, the scheduler but this still leaves us with the same
will kick a lower priority thread out of the problem we had before synchronizationl
running state If a higher priority thread Ryan can check the balance, go to sleep,
suddenly becomes runnable , But...one and Monica can come in and also check
more time, say It with me now,"there the balance before Ryan has a chance to
Is no guarantee.» We recommend that wakes up and completes his withdrawal.
you use priorities only if you want to
So synchron izing all the accessmethods
Infl uence performance,but never, ever
Is probably a good Idea, to prevent
rely on them for program correctness.
other threads from getting in, but you
stili need to synchronize the methods
that have statements that must execute
as one atomic unit.

522 chapter 15
networking and threads

Code Kitchen

Cvber BeatBox

( Start )
( Stop )
( Tempo Up )
( Tempo Down )
( sendlt )

dance beat

Andy: groove #2

Chris: groove2 revls&d


Nigel: dance beat

This is the last version ol the BeatBox!


It connects to a simple MusicServer so that you can
send and receive heat patterns witlt other cUen ts.
The code is really long, so tite complete listing is
arluaUy in AppenJix A.

you are here. 523


exercise: Code Magnets

Code Magnets
A work ing Java program Is scrambled up on the fridge. Can
you add the code snippets on the next page to the empty
classes below, to make a working Java program that pro-
duces the output listed ? Some of the curly braces fell on the
floor and they were too small to pick up, so feel free to add as
many of those as you needl

public class TestThreads { class ThreadOne

class Accum {
class ThreadTwo

Bonus Question: Why do you think we used the


mod ifiers we did In the Accum class?

524 chapter 15
networking and threads

Code Magnets, continued..


system.out.printlo(Utwo u+a.getCount())i
Thread one ~ new Thread(tl)i

ThreadTwO t2 new ThreadTWO()i


} oatoh(InterruptedExceptiOn ex) { }

return counte icounter += add:

:::- new Th implements Runnable (


read(t2);

Accum a Accum.getAccum():

} catch(InterruptedException ex) { }
public static Accum getAccurn() {

new Accurn( ) i
private static Accurn a

private int co unter 0:


public void

a.updatecounter(l);

forti n t x=O: x < 99. implements Runnable (


I X++) (

a.updateCounter(lOOO)i
public int return a;
getCount() (
System.out.printl O("one "+a
.getCount(»;

public static void main(String (I args) (


for(int x=o; x < 98' two.start()i
, x++) (

public void runt) ( private Accum() { } Thr e adOne tl = new ThreadO ne():

you are here ~ 525


exercise solutions

pUblic clasa TestThreada {


pUblic static void main(String [] args) {
ThreadOne tl '" new ThreadOne()j
ThreadTwo t2 '" new ThreadTwo();
Thread one ~ new Thread(tl);
Thread two c new Thread(t2);
one.start() ;
two.start() ,
Threads from two different classes are updating

/,~~ il sUb/')i~".u
} the same object in a third class, because both
} threads are accessing a single instance of Accum.
J t.\ass to.t.t........ The line of code:

class Accum { private static Accum a = new Accum(); creates a


private static Accum a =: new AccUDI ( ) ; static instance of Accum (remember static means
private int counter =: OJ one per class), and the private constructor in
Accum means that no one else con makean Accum
private Accurn() { } r-- to. rri"~ ~~ object. These two techniques (private constructor
and static getter method) used together, create
public static Accurn getAccum() { what's known as a 'Singleton' - an 00 pattern to
return a; restrict the number of instances of an object
} that can exist in an application. (Usually, there's
just a single instance of a Singleton-hence the
public void updateCounter(int add) { name), but you can use the pattern to restrict the
counter += add; instance creation in whatever way you choose.)
}

public int getCount() {


return counterj
}
class ThreadTwo implements Runnable {
} Accum a = Accum.getAccum()j
public void run() {
class ThreadOne implements Runnable {
for(int x=:O; x < 99; x++) {
Accum a =: Accum.getAccum()j
a.updateCounter(l)j
public void run() { try {
for(int xeO; x < 98; x++) { Thread.sleep(50);
a.updateCounter(lOOO); } catch(InterruptedException ex) { }
try { }

Thread.sleep(50)j System,out.println(~two u+a.qetCount())j


} catch(InterruptedException ex) { } }
}
}
system.out.println(None u+a.getCount())j
}
}

526 chapter 15
networking and threads


Near-miss at the Airlock

This morning's meeting was focused on the control systems for the orbiter's airlocks.
As the final constructionphases were nearing their end, the number of spacewalks was
scheduled to increase dramatically, and trafficwas high both in and out of the ship's
airlocks. "Good morning Sarah", said Tom, "Your timing is perfect, we're just starting
the detailed design review."

"As you all know", said Tom, "Each airlock is outfittedwith space-hardened GUI
terminals, both inside and out Whenever spacewalkers are entering or exiting the orbiter
they will use these terminals to initiatethe airlock sequences." Sarah nodded,"Tom can
you tell us what the method sequences are for entry and exit?" Tom rose, and floated to the
whiteboard., "First, here's the exit sequence method's pseudocode", Tom quickly wrote on the
board
orbiterAirlockExitSequence()
verifyPortalStatus();
pressurizeAirlock();
openlnnerHatch();
confinnAirlockOccupied () ;
closelnnerHatch() ;
decompressAirlock();
openOuterHatch();
confirmAi r lockVaca ted () ;

closeOuterHatch();

"To ensure that the sequence is not interrupted, we have synchronizedall of the
methods called by the orbiterAirlockExitSequence() method", Tom explained. "We'd hate to
see a returningspacewalker inadvertently catch a buddy with his space pants down!"

Everyone chuckled as Tom erased the whiteboard, but something didn't feel right
to Sarah and it finally clicked as Tom began to write the entry sequence pseudocode on the
whiteboard, "Wait a minute Tom!", cried Sarah. ''1 think we've got a big flaw in the ex.it
sequence design, let's go back and revisit it, it could be critical!"

Why did Sarahstop the meeting? What didshe suspect?


you are her e ~ 527
puzzle answers

• What did Sarah know?

Sarah realized that in order to ensure that the entire exit


sequence would run without interruption the
orbi terAi r lockExi tSequence ( ) method needed to
be synchronized. As the design stood, it would be possible
for a returning spacewalker to interrupt the Exit Sequencel
The Exit Sequence thread couldn't be interrupted in the
middle of any of the lower level method calls, but it could be
interrupted in between those calls. Sarah knew that the entire
sequence should be run as one atomic unit, and if the a rbi t
erAirlockExitSequence ( ) method was synchronized, it
could not be interrupted at any point.

528 chapter 15
16 collections and generics

Data
structures

Sorting is a snap in Java. You have all the tools for collect ing and manipulating

your data without having to write your own sort algorithms (unless you're reading this right
now sitting in your Computer Science 101 class,in which case, trust us-you are SO going to be
writing sort code while the rest of us Just call a method In the Java API). The Java Collections
Framework has a data structure that should work for virtually anything you'll ever need to do.

Want to keep a list that you can easily keep adding to? Want to find something by name?Want
to create a list that automatically takes out all the duplicates? Sort your co-workers by the
number of times they've stabbed you in the back? Sort your pets by number of tricks learned?
It 's all here...

t his is a new chapter 529


sorting a list

fracki"Q SOt1g popularity 0., your jukebox


Congratulations on your new j ob----managing the automated
jukebox system at Lou's Diner. There's no Java inside the
jukebox itself, but each time someone plays a song, the
song data is appended to a simple text file.
Your job is to manage the data to track song popularity,
generate reports, and manipulate the playlists, You're not
writing the entire ap~ome of the other software developer/
waiters are involved as well. but you're responsible for managing
and sorting the data inside the java app. And since Lou has a thing
against databases, this is strictly an in-memory data collection. All
you get is the file the jukebox keeps adding to. Your job is to take it
from there.
You've already figured out how to read and parse the file, and so far
you've been storing the data in an ArrayList.

SongLlst. txt
Challenge #1
Pink Moon/Nick Drake Sort the songs in alphabetical order
Somersault/Zero 7
You have a list of songs in a file. where each line
Shiv& Moon/Prem Joshua
represents one song, and the title and artist are
Circles/BT
separated with a forward slash. So it should be simple
Deep Channel/Afro Celts
to parse the line, and put all the songs in an ArrayList.
Passenger/Headmix
Listen/Tahiti 80 Your boss cares only about the song titles, so for now
you can simply make a list thatjust has the song titles.
But you can see that the list is not in alphabetical
order... what can you do?
You know that with an Arrayl.ist, the elements are
kept in the order in which they were inserted into the
list, 50 putting them in an ArrayList won't take care of
alphabetizing them, unless... maybe there's a sortj)
method in the ArrayList class?

530 chapter 16
collections with generics

Here's what you have so far; without the sort:


impo4t java.util.*;
import java.io.*;

pUblic class Jukeboxl

ArrayList<String> songList : new ArrayList<String>() i

public static void main (String () args 1 I


new Jukeboxl() . ge ( ) ;

public void go() I ~


getSongs();
System.out.println(songList);

. 1: Y'tilO the t 'lle il"d


Not.hi,,~ syet."lill he.. . e..J~oo ~a-- eat" \il'le·
void gatSonqa () t.a\\ -\:.he ilod$of..~O '"
try {
File file new File("SongList.txt H ) ;
BufferedReader reader = new BufferedReader(new FileReader(file»:
String line = null;
whi Le « line= r e ade r , readLine () ! = null) (
addSong(line);

catch(Exception ex) (
ex.printStackTrace();
The tiddSon
Ci...d j th 1 "'eiJ..od \\/orh .

void addSong(Strinq lineToParse) I


String (1 tokens = lineToParse. split ("/") ;
r (J... -J.. Ln. e I/O thdpU
~"t; Ild$
JIISf likl! i~1! /.I "

"'eih;..tt
both th tifl....-- yOk b... k
pieCes (MOu) lotS' I! ill! tlnd i1r-t.i:tJ
"\5 tht! spliiO
"i'l<lz.-
}itle
two
songList.add(tokens[Ol);

<:
%j av a Jukebox!
[Pink Moon, Somersault,
Shiva Moon, Circles ,
Deep Channel, Passenge r ,
Listen}

you are here. 531


ArrayList API

~ut the ArrayList class does NOr have asartO tMethod!


When you look in Arrayl.isr, there doesn't seem to be any method related to sorting.
NaJking up the inheritance hierarchy didn't help either-it's clear that y()U can't call a sort
nethod on the ArrayList.

~ -C;. -::T~A;ii'iVUit (Jiiii 2 Pli"tfOOii sr 5:0)


~i:i)11 ern +lf~ hItP:1/JavLSun.rom/J1n/ l.S.O'docs/&pl/lncltx.hlml

••
• ... 1• ..,., AW..I.1a.aC~
!IDt>nu t .n.<l lf.1UlI
lhil lUI ~. iIl£ spedIDI
. ,r- - ---- ----- ----==:::::====--i

........ .& regu....... ( l...rl t. IcgaJ ..r:u s.._, at. lA:ItlWl


.. , . ~>es fltJa> !hi> USl all ~ ~ dcm<lll

~7l.-f
I; I ftlW.1.a. ~ • .L1&WRL l!UIt,Ulor , •
.-...
chap ter 16
collections with generics

r do see a collection class


celled TruSe.t... and the docs
sCI>! that it keeps your data
sorted. r wonder if r should be
using a TreeSet inste.ad of an
ArrayList ...

o
o

ArrayLisf is.!Q1the ot1ly collectiot1


Although ArrayList is the one you'll use most often,
there are others for special occasions. Some of the key .
collection classes include: D 't 'NcKY'f C1nOl>t b-'tl~
Of' ~ese oth~ Ol'Ies
t.o \eClyY\
~ TreeSet ...~e o~il~ a \iH:le C1~'
,1._
'\I 0 il'l-to
yiaht "0... · We ~c

Keeps the elements sorted and prevents duplicates.

.. HashMap
Let's you store and access elements as namelvalue pairs.

~ L1nkedLlst
Designed togive better performance when you insert ordelete
elements from the middle ofthe collection. (In practice, an
ArrayUst isstill usually what you want.)

~ HashSet
Prevents duplicates inthe collection, and given an element, can
find that element in the collection qulcldy.

~ L1nkedHashMap
Like a regular HashMap, except it can remember the order in
which elements (name/value pairs) were Inserted, orit can be
configured to remember the order In which elements were last
accessed.

you are here ~ 533


Collectlons.sortO

You could use a freeSet...


Or you could use the Coliectiotts.sortCl tttethod
lfyou put all the Strings (the song titles) into a TreeSet instead of
an ArrayList, the Strings would automatically land in the right place,
alphabetically sorted. Whenever you printed the list, the elements would
always come out in alphabetical order.
And that's great when you need a set (we'll lava.utll.collections
talk about sets in a few minutes) or when
public static void copy{Ust destination. List source)
you know that the list must au.vays stay
sorted alphabetically. public static Ust emptyUst()
On the other hand, if you don't need the public static void flll(List IIstToFill, Object objToFillltWrth)
list to stay sorted. TreeSet might be more public static Int trequency(Collection c, Object 0)
expensive than you need-every time you
insert into a Treeset; the TreeSet has to take public static void reverse{Ust list)
the time to figure out where in 1M tree the new public static void rotate(Ust list, lnt distance)
element must go. With ArrayList, inserts can
be blindingly fast because the new element public static void shuffle(Ust list)
just goes in at the end. public static ~ sOrt{L\st listV
. ;~. II". Ohiect oIdVal, Object newVal)
public static boole

/I many more met


Q: But you CAN add something to an .ij",,,,,,,... !here IS a sor!() Meihod I-
ArrayList at a specific Index Instead of just at -~

the end-there's an overloaded addll method 1ft !he Collet-t;ofts tlass. I! hkes
that takes an Int along with the element to add a Lis!' and'Slftte ArrayList
So wouldn'fft be slower than Inserting at the end1
+
i"'ple_e...i.s !he Lis! .....t er ate,

A: Yes, It's slower to insert something in an ArrayLlst


somewhere other than at the end. So using the 0 verloaded
ArrayLis! IS-A Lis!. Thanks
!o polyMorphisM, y~ tan pass a...
add(lndex, element) method doesn't work as qui ckly as calling
~rayList to a Me!hod d ,
the add(element)-which puts the added eleme nt at the end. to ta et ared
But most of the time you use ArrayLists, you won 't need to put Ice List
something at a specific Index.

Q: I see there's a L1nkedllst class, so wouldn't that be better for


doing Inserts somewhere In the middle1 At least if I remember my Data
Structures class from college...

A: Yes, good spot. The LinkedLlst can be quicker when you Insert or
remove something from the middle, but for most applications, the difference
between middle inserts Into a Linkedllst and ArrayList is usually not enough
to care about unless you're dealing with a huge number of elements. We'll
look more at L1nkedLlst In a few minutes.

534 chapter 16
collectlons with generics

Addit1g Coliectiot1s.sortU to the Jukebox code


impo r t j a va . u t i l . * ;
import java . i o . T ;

pub l i c c l a s s J u keb oxl The Collections.sortO


ArrayList<String> songList = new ArrayList<String>(); lllethod sorts a list of
pub lic s t a t i c vo i d ma i n (St ri ng [] a r gs) (
StriPgs alphabetically.
ne w Jukebox 1 ( ) . go ();

pub lic voi d got) r


ge r- Song s () ; 1t.aVt. CoI\et:b~
System. out . p ri n t l n (s o n g Li st ) ; ~ ~~~et\<'odl ~e" Y'f\,,~-\;.h~
Collections. sort (songList) ; \' L , "T"ne ~[t.ot>d ~,,,t.
,5<. a~'''' \ J I
System.out.println (songList) ; ~ 'IS ,,, i\,,~'oebt.a\ cJt"~t:'t'.

vo i d getsongs ()
t ry (
Fi l e ll e ne w Fi l e (" Son gLi s t . t x t H
) ;

BufferedRea de r r e a de r = new Bu f f e r e dReade r (ne w FileReade r (file » ;


S t r i ng li n e - n u l l;
wh il e ( (li ne- r e a d e r r e adt.L n e t ) l
i !=' null) (
a ddSong (1 i ne ) ;

ca tc h (Exce p tion ex) (


ex.printS a c kTr a c e ( ) ;

voi d addSong(String lineToParse) (


tr i ng l ] to ke n s = l i n e ToPa r s e . s p l i t( " /H ) ;
songList .r.tdd (toke n.s [O ] ) ;

%j ava Jukeboxl

[Pink Moon , Somersault, Shiva Moon, Circles, Deep •,


Channel , Passenger , Listen)

(Circles, Deep Channel, Listen, Passenger, Pink


Moon , Shiva Moon, Somersault]

you are here ~ 535


sorting your own objects

Jut now you Meed SOMQ objects,


not just shttple Stri"Qs.
Now your boss wants actual Song class instances in the list, notjust SongUstM0r2. txt
Strings, so that each Song can have more data. The new jukebox
device outputs more information, so this time the file will have four
pieces (tokens) instead ofjust two. Pink Moon/Nick Drake/5/80
Somersault/Zero 7/4/84
The Song class is really simple, with only one interesting feature- Shiva Moon/Prem Joshua/6/120
the overridden toStringO method. Remember, the toString() Circles/BT/5/110
method is defined in class Object, so every class inJava inherits the Deep Channel/Afro Celts/4/120
method. And since the taStringO method is called on an object Passenger/Headmix/4/l00
when it's printed (System,out.println (an Object) ), you should Listen/Tahiti 80/5/90
override it to print something more readable than the default
unique identifier code. When you print a list. the toStringO
method will be called on each object.

class Song (
String title;
String artist;
String rating;
f
String bpmi

Song(String t, String a, String r, String b) (


title = t;
artist =' a; The va~i.ables a.-t all sd. i"
rating = r; the l.or\strl.ll.i« wher> the
bpm = b r "
I\ew ~,,~ is l.~eated,

pUblic String getTitle()


return title;

public String getArtist()


return artist;

public String getRating(}


return rating;

public String getBpm()


return bpm;

public String toString ()


return title;

536 chapter 16
collections with generics

Changing the Jukebox code to use Songs


instead of Strings
Your code changes only a little-the file I/O code is the same,
and the parsing is the same (String.splitf) ). except this time
there will be Jour tokens for each song/line, and all four will be
used to create a new Song object. And of course the ArrayList
will be of type <Song> instead of <String>.

impor t j ava . ut i l . * ; L A.rra'JL.ist cJ SoY\~


impo rt jav a.i o.*; Chan~e ~ an f\ J 'Stv:ln~.
objetts Instead
publi c c l a s s JUkebOX ~ ~

ArrayList<Song> songList = new ArrayList<Song>();


pu bl i c stati c v o i d mai n( Str i n g[ ] ar g s) (
ne w J u keb ox3() . g o ( ) ;
}
pu b l i c void ge() {
g e tSo n gs() ;
Sy st e m. o u t . p ri nt ln( s o n g Li s t) ;
Col lec t i o n s .sor t(so n g Li s t ) ;
S y s tem . out .pr i nt l n (s ongLis t ) ;
}
vo id getSongs ()
try {
Fi le fil e new Fil e{" Song Li s t . t xt H ) ;
BufferedReader r e ade r = ne vi Bu ffe r e d Re ade r (n e w FileRead er (fil e ) ) ;
S t r i n g line = nu l l ;
wh il e « Li ne > r e a d e r . re a dLine ()) ! ~o null) (
a d d Song (line ) ;

catch (Exce p ti o n e x)
e x .pr i ntStackTrac e ( ) ;

v o id addSeng(String lineTeParse) {
St ri n g [ ] t okens = lineTo Pa r s e . spl it(" /" );

Song nextSonq = new Sonq(tokens[O] , tokens[l], tokens [2] , tokens[3]);


songList.add(nextSong);

you are here ~ 537


Collections.s 0 rtO

It WOt1~t cotMpiIe!
Something's wrong... the Collections class clearly shows there's a
sort/) method, that takes a List.
ArrayList is-a List, because ArrayList implements the List interface,
so... it should work .
But it doesn't!
The compiler says it can't find a sort method that takes an
Arrayl.istc'Songo, so maybe it doesn 't like an Arrayl.ist of Song
objects? It didn't mind an ArrayList<String>. so what's the
important difference between Song and String? What's the
difference that's making the compiler fail?

%javac Jukebox3.java
JukeboK3 .java:15 : cannot find symbol
symbol method sort(java .util.ArrayList<Song»
location: class java.util .Collections
Collections.sort(songList);

1 error

And of course yOll probably already asked yourself, "What would it


be sorting onr How would the sort method even know what made
one Song greater or less than another Song? Obviously if you want
the song's title to be the value that determines how the songs are
sorted, you'll need some way to tell the sort method that it needs
to use the title and not, say, the beats per minute.
We'll get into aU that a few pages from now, but first, let's find out
why the compiler won 't even let us pass a Song ArrayList to the
sortt) method .

538 c ha pte r 16
collections with generics

WID I have no idea how to


read the method declaration
on this. It says that sortO
takes a List~T) . but what is
n And what is that big thing
before the return type?

o
o

fhe sortO tMethod declaratiot'

sort
public: at.4t~ fUl.teDd: eome:rllbl&<? auper T>";>Oid .o~ HlStl
Sorts the specified list into ascending order. according to the nalJITal ordering of its elements. All
elements in the list mu.st implement the Comparable interface. Furthermore. all elements in the list
must be mullllllJy comparab~ (that is, el.cOIIlpareTo I82) must not throw a ClaasC4st.E>l:c:eption
for any elements &1 and 82 in the list).

From the API docs (looking up the java.util.Collections class. and scrolling to the sortt)
method), it looks like the sortt) method is declared... strangely. Or at least different from
anything we've seen so far.
That's because the sortO method (along with other things in the whole collection framework in
Java) makes heavy use of generics. Anytime you see something with angle brackets inJava source
code or documentation, it means generics-a feature added to Java 5.0. So it looks like we'll
have to learn how to interpret the documentation before we can figure out why we were able to
sort String objects in an Arrayl.ist, but not an ArrayList of Song objects.

you are here ~ 539


generic types

&et1erics ",eat1s ",ore type.. safety


We'lljust say it right here-virtually all of the code you writethat deals
with generics will becollection-related code. Although generics can be used
in other ways, the main point of generics is to let you write type-safe
collections. In other words, code that makes the compiler stop you
from putting a Dog into a list of Ducks.
Before generics (which means before Java 5.0), the compiler could
not care less what you put into a collection, because all collection
implementations were declared to hold type Object. You could put
anything in any ArrayList; it was like all ArrayLists were declared as
ArrayList<Object>.
wIth generics. you can
create type-safe collections
where more probleltlS are
caught at compile-time
inStead of runtil1le.
wIthout generics. the
ArrayList
compiler would happily let
~ ~ ~ ~

••••
And come OUT as a reference oftype Object
you put a Pumplin into an
ArrayLiSt that was supposed
to hold only Cat objects.
WITH generics
Objects go IN as a reference to
only Fish objects

ArrayList<Fish>

And come out as a reference oftype Fish

540 ch apter 16
collections with generics

Learning generics
Of the dozens of things you could learn about generics, there are
really only three that matter to most programmers:

• Creating instances of generified classes (like ArrayList)


new ArrayList<Song>()
When you make an ArrayList, you have to tell it the type
of objects you'll allow in the list,just as you do with plain
old arrays.

• Declaring and assigning variables of generic types


List<Song> songList =
How does polymorphism really work with generic new ArrayList<Song>()
types? If you have an ArrayList<Animal> reference
variable, can you assign an ArrayList<Dog> to it? What
about a List<Animal> reference? Can you assign an
ArrayList<Animal> to it? You'll see ...

• Declaring (and invoking) methods that take generic types


If you have a method that takes as a parameter, say, an void foo(List<Song> list)
ArrayList of Animal objects, what does that really mean?
Can you also pass it an ArrayList of Dog objects? We'll x.foo(songList)
look at some subtle and tricky polymorphism issues that
are very different from the way you write methods that
take plain old arrays.
(This is actually the same point as #2 , but that shows you
how important we think it is.)

Q.: But don't I also need to learn how to create my OWN generic
dasses? What if Iwant to make a class type that lets people
instantiating the class decide the type of things that class will use?

A.: You probably won't do much of that. Think about it-the API
designers made an entire library of collections classes covering most of
the data structures you'd need, and virtually the only type of classesthat
really need to be generic are collection classes. In other words, classes
designed to hold other elements, and you want programmers using it to
specify what type those elements are when they declare and instantiate
the collection class.
Yes, it is possible that you might want to create generic classes, but that's
the exception, so we won't cover it here. (But you'll figure it out from the
things we do cover, anyway.)

you are here ~ 541


generic classes

Using generic CLASSES


Since ArrayList is our most-used generified type, we'll
start by looking at its documentation. They two key areas
to look at in a generified class are:
Thinl of "E" as a stand-in for
1) The class declaration "-the type of elem.ent you want
3) The method declarations that let you add elements this collection to hold and
return." (E is for Elenent.)
Understanding ArrayList documentation
- -
(Or, what's the true meaning of "E"?)

.:
public class ArrayList<E> extends AbstractList<E> implements List<E> .. , {

The t'tfe (the lJal~ of <f.»


bet.oMes the t'fVe of the List
il'ltel""kat.e as well.

II more code

The "E" represents the type used to create an instance


of ArrayList. When you see an "E" in the ArrayList
documentation, you can do a mental find/replace to
exchange it for whatever <type> you use to instantiate
ArrayList.
So, new ArrayList<Song> means that "E" becomes "Song" ,
in any method or variable declaration that uses "E".

542 chapte r 16
collections with generics

Usit1Q type parattteters with ArrayList

THIS code:
ArrayList<String> thisList = new

Means ArrayLlst:
... {

public boolean addlE 0)


/ / more code

Is treated by the complier as:


public class ArrayList<Strinq> extends AbstractList<Strinq> . .. {

public boolean add(Strinq 0)


/ / more code

In other words, the ~E~ is replaced by the realtype (also called the type parameter)
that you use when you create the Arrayl.ist, And that's why the add 0 method
for ArrayList won't let you add anything except objects of a reference type that's
compatible with the type of ~E". So if you make an ArrayList<:String>, the add 0
method suddenly becomes add(String 0). !fyou make the ArrayList of type Dog,
suddenly the addt) method becomes add(Dog 0).

Q: Is"E"the only thing you can put there18ecause the docs for sort used "1'':'•••

A: You can use anything that's a legal Java Identifier. That means anything that you
could use for a method or variable name will work as a type parameter. But the conven-
tion Is to use a single letter (so that's what you should use), and a further convention IS to
use MT" unless you're specIfically wrltl ng a collection class,where you'd use ME" to repre-
sent the "type of the Element the collection will hold"

you are here ) 543


generic methods

A generic class means that the class declaration includes a type


parameter. A generic method means that the method declaration
uses a type parameter in its signature,
You can use type parameters in a method in several different ways:

• Using a type parameter defined Inthe class declaration


public class ArrayList<E> extends AbstractList<E> ... (
public boolean addlE 0) \/OII"~
" - . . / t- ......" ~ fh ~E»
tllr~dy b t bl d:fi"td :~;tl~:rhet.4~ it's
When you declare a type parameter for the class, you tht lltlU.
can simply use that type any place that you'd use a
real class or interface type . The type declared in the
method argument is essentially replaced with the type
you use when you instantiate the class,

public <T --
Using a type parameter that was NOT defined Inthe class declaration

~
extends Animal> void t&keThing(ArrayList<T> list)

If the class itself doesn't use a type parameter, you can still »&t we~
specify one for a method, by declaring it in a really unusual
rr ...." ~<T:> be
~rliel" i" the ...efh ~~ we ~1~hOA
(but available) space-before the return type, This method says od dtlJdrd~
that T can be "any type of Animal",

544 chapter 16
collections with generics

Wait ... that can't be right. If you can


take a list of Animol, why don't you
just SAY that? What's wrong with just
toke ThIng{AtTayUst~ Animal;) list)?

HereJs where It gets weird...


This:
public <T extends Animal> void takeThing(ArrayList<T> list)

Is NOT the same as this:


public void takeThing(ArrayList<Animal> list)

Both are legal, but they're diffmmtl


The first one, where <T extends Animal> is part of the method
declaration. means that any Arrayl.ist declared ofa type that is
Animal, or one of Animal's subtypes (like Dog or Cat), is legal.
So you could invoke the top method using an ArrayList<Dog>,
ArrayList<Cat>, or ArrayList<Animal>.
But... the one on the bottom, where the method argument is
(Arr.tyList<Animal> list) means that only an Arr.tyList<Animal>
is legal. In other words, while the first version takes an Arrayl.isr
of any type that is a type of Animal (Animal, Dog, Cat, etc.),
the second version takes Qnly an Arrayl.Jst of type Animal. Not
ArrayList<Dog>, or ArrayList<Cat> but only ArrayList<Animal>.
And yes, it does appear to violate the point of polymorphism.
but it will become clear when we revisit this in detail at the end
of the chapter. For now, remember that we're only looking at
this because we're still trying to figure out how to sortO that
SongList, and that led us into looking at the API for the soru)
method, which had this strange generic type declaration.
For now, all you need to krww is that the synt.ax of the top uersion
is legal, and that it means you can pass in a ArrayList object
1'nstantiated as Animal or any Animal subtype.

And now back to our sortt) method...

you are here. 545


sorting a Song

This still doesn't


expla in why the soM method
failed on an ArrayList of Songs
but worked for an ArrayList of
Strings...

Remember where we were...

i mpo r t java.util .*;


import java.io.*:

public class Jukebox3 (


ArrayList<Song> songList = new ArrayList<Song>() i
pUblic static void main{Stri ng{ ) args) (
new Jukebox3{) .go();
I
pUblic void go() (
getSongs();
Sys t em. ou t. pr i nt l n (s ong Li s t );

System.out.println(songList);
}
void getSongs ()
try (
File file new File("SongList.txt H ) ;
Buf feredReader r e ade r = new BufferedReader (new FileReader (file) );
String line ~ null;
while ((line= reader.readLine{» != null) (
addSong{line);
I
catch (£xception ex) (
ex.printStackTra ce();
)
void addSong(String lineToParse) (
String!) tokens = lineToParse.split( "/");
Song nextSong = new Song (tokens [01 , tokens[l], tokans[2] , tokens[3]);
songList .add(nextSong);

546 chapter 16
collections with generics

Revisiti.,g the sortt) tltethod


So here we are, trying to read the sortt) method docs to find
out why it was OK to sort a list of Strings, but not a
list of Song obj ects. And it looks like the answer is' '' L... ~ ~ OoVi i,;;;;;;.. $( ·
L :.1.-"~"""lIHJ'/""""I_"I"" /''''' __1 ':01

The sortO method can take only lists


of Comparable objects.

Song is NOT a subtype of


Comparable, so you cannot sorto
the list of Songs.

At least not yet.•.

public static <T extends Comparable<? super T» void sort(List<T> list)


----~--- J
~~..« e th:s part. to'r ..ow. Bt.t
Yov. c.dl'l fau i~Of\ly a L.ist. (.I:ir
,f y~ loa" t.. it j lI.Si "'tel I'IS slObtYfe ~ list, [ikt: AwayLlsV
thai the type para",c1:.tY .f« t.hat ~ a fara"'eW-iud t'ifc
eo",parablc "'t.jt be o-f type T thdt "e'llUNis Co""yarablt:".
o'r one o-f T's st.pertyptsJ ·

Urn... I just checked the docs for


String. and String doesn't EXTEND
Comparable--it IMPLEMENTS it.
CDmparable is an Interlace. So it's nonsense
to say <T extends Comparable> ,

public final claS9 String extends Object implements Serializable,


Comparable<String>, CharSequence

you are here. 547


the sortt) method

N
't1 get1erics, "extet1ds ttteat1S
"extet1ds ~ itttpletttet1ts
N

The Java engineers had to give you a way to put a constraint


on a parameterized type, so that you can restrict it to, say, only
subclasses of Animal. But you also need to constrain a type to In generics, the "keyword
allow only classes that implement a particular interface. So
here's a situation where we need one kind of syntax to work
"extends" really means "is-a",
for both situations-inheritance and implementation. In other
words, that works for both extends and implements.
and wor"ks for B01lI classes
And the winning word was... extends. But it really means "is-a", and interfaces.
and works regardless of whether the type on the right is an
interface or a class.
COMrarable is an in-ttr.fate, so this
R~l...l...y reads, "T Ml.tSt be a t'tre t,hat
iMrleMents the COMrarable in-ttrfate .

~
public static <T extends Comparable<? super T» void sort(List<T> list)

J'
It doesn't Mat-tt\'" whether the thil'l~ on the ri~ht is
a t1ass 0\'" il'l-tt\'"+ate... '101#. still sa'l "e~-ttnds" .

Q.: Why didn't they just make a new keyword,"is"?

A: Adding a new keyword to the language is a REALLY big deal because


it risks breaking Java code you wrote in an earlier version. Think about
it-you might be using a variable "is" (which we do use in this book to repre-
sent input streams). And since you're not allowed to use keywords as identi-
fiers in your code, that means any earlier code that used the keyword before
it was a reserved word, would break. So whenever there's a chance for the
Sun engineers to reuse an existing keyword, as they did here with "extends';
they'll usually choose that. But sometimes they don't have a choice ...
A few (very few) new keywords have been added to the language, such
as assert in Java 1.4 and enum in Java 5.0 (we look at enum in the appen-
dix) . And this does break people's code, however you sometimes have the
option of compiling and running a newer version of Java so that it behaves
as though it were an older one. You do this by passing a special flag to the
compiler or JVM at the command-line, that says/Yeah, yeah, I KNOWthis is
. Java 1.4, but please pretend it's really 1.3,because I'm using a variable in my
code named assertthat I wrote back when you guys said it would OKI#$%':
(To see if you have a flag available, type javac (for the compiler) or java (for
the JVM) at the command-line, without anything else after it, and you should
see a list of available options. You'll learn more about these flags in the chap-
ter on deployment.}

548 chapter 16
collections with generics

Fittally we kttow whatl wrottQ...


The SOtt<l class tteeds to hMplelMettt COlMparable
We can pass the ArrayList<Song> to the sortt) method only if the The big question is: what
Song class implements Comparable. since that's the way the sortt) makes one song less than,
method was declared. A quick check of the API docs shows the equal to, or greater than
Comparable interface is really simple. with only one method to anofher song?
implement
You can't Implement the
java.lang.Comparable Comparable Interface until you
make that decision.
public interface COIIIp&rahle<T>
int compareTo(T O)i

nyour pencil -------,


And the method documentation for compare'Io() says
Write In your idea and pseudo code (or
better, REAL code) for Implementing the
compareToO method In a way that will
Returns: sortf) the SOl'\g objects by title.
a neqative integer, zero, or a
positive integer as this object Hint: If you 're on the right track, it should
1s 1&88 than, 8qlUll to, or greater take less than 3 lines of codel
than the Sp8cl1ied object.

It looks like the compareToO method will be called on one


Song object, passing that Song a reference to a different
Song. The Song running the compareToO method has to
figure out if the Song it was passed should be sorted higher,
lower, or the same in the list.
Your bigjob now is to decide what makes one song greater
than another, and then implement the compareToO method
to reflect that. A negative number (any negative number)
means the Song you were passed is greater than the Song
running the method. Returning a positive number says
that the Song running the method is greater than the Song
passed to the compareToO method. Returning zero means
the Songs are equal (at least for the purpose of sorting... it
doesn't necessarily mean they're the same object) . You might,
for example. have two Songs with the same title.
(Which brings up a whole different can ofwonns we'Il look
at later...)

you are here ~ 549


the Comparable interface

fhe "eYl, itltproved, cotltparable SO"Q class


We decided we want to son by title, so we implement the corn pareTo ()
method to compare the title of the Song passed to the method against
the title of the song on which the compareToO method was invoked.
In other words, the song running the method has to decide how its
title compares to the title of the method parameter.
Hmmrn... we know that the String class must know about alphabetical
order, because the sortj) method worked on a list of Strings. We know
String has a compareTaO method. 80 why not just call it? That way, we
can simply let one title String compare itself to another, and we don't
have to write the comparing/alphabetizing algorithm!
IAsv.ally t.~~se ,.,..;tt,h...\lIt't't sfetl.f'ii~ the t'fYe t1a-t
t~e i "le... e"h,,~ dciss tal> be (.Oft\ra--ed a~"'IJI,S+"

class Song implements Comparable<Song> { This ecihS that. ~,,~ objed:.s ta" be t.OMr a-- ed -to
String ti tIe; ot.hel" ~~ obje t.b, f~ t~e r~--fose tJ sorti~.
String artist;
String rating; , - - - The soortO ",dhod ~ds a So,,~ to i.e-ya--e T of.)
String bpm; .J..,. -to see how that ~~ t.o...ya__ es to t~ Sol'l~ O'/'l
whith the ...dhoa was ,,,yoked.
public int compareTo(Song s) {
return title.compareTo(s.getTitle(»;
)

Sonq(String t, String a, String r, String b) (


title = t;
artist = a;
rating =
r;
bpm =b;

public String getTitle()


return ti tie;

public String getArtist()


return artist;
%java Jukebox3
public String getRating()
return rating : (Pink Moon, Somersault, Shiva Moon, Circles, Deep
Channel, Passenger, Listen]
public String getBpm () {
return bpm; [Circles, Deep Channel, Listen, Passenger, Pink
Moon, Shiva Moon, Somersault]
public String toString()
return title;

550 chapter 16
collections w ith generics

We catt sortthe list, but... That's not good enough.


There's a new problem-Lou wants two different views of the song list, Sometimes r want it to sort
one by song title and one by artist ! by artist instead of title.
But when you make a collection element comparable (by having it
impl ement Comparable), you get only one chance to implement the
compareToO method. So what can you do?
The horrible way would be to use a flag variable in the Song class,
and then do an if test in compare'Ior) and give a different result
depending on whether the flag is set to use title or artist for the
comparison.
But that's an awful and brittle solution, and there 's something much
better. Something built into the API for just this purpose-when you
want to SOrt the same thing in more than one way.

Look at the Collections class API again. There's a


second sortO method-and it takes a Comparator.

. _- Collections Oava 2 Platform SE 5.0) ----. _.


~
--
flle:IIIUsers/kathyIPublic/docs/apl/lndex.hlml 0.. Google J
s Jellyvis lon. Inc Collect ion s ...form SE 5.0) Caffelnated ...d Brain Day Brand Noise DIva Marketing »
static 8LngletoAKaP(K key, V value) ,....

---
<X,V> ~<K.V>
Returns an immutable map, mapping only the ~
:oJ
-1 specified key to the specified value.

,-- - sarlO ~~od is o'Jev-\oad -to ed


~per
lllGtic ~(Li5t<T>

void
list)
Sorts the specified list into ascending order,
according to the 1UJlUTal ordering of its elements.
The . \\ d a cO"'yayat.o--·
bke SOft'et\oi,,,~ U e r>
\ llt;~
v
BOrt. (List<T> list, COlnD8f"lftor<? super T> ~
c;nrte ~
induced by me
.- list according to the ~.
. 1--, '-
..-
r---
...
~I

Note -to se\~ : ~.,~~e OIo't ~ -to


- <II

t.o-- t,nat Un
\ tit / w.av.t a Cotr-yaYd
~ ncl o'I"dfY tnt sanOJ b~
WW'y~t a
. wd ~ ttlt-oO
aM:.isl ,"s
)
L -
you are here. 551
the Comparator interface

Ushtg a custOtlt Cotltparafor


Java.util.Comparator
An element in a list can compare itselfto another of
its own type in only one way. using its compareTo(} public interface Comparator<T>
method. But a Comparator is external to the element int compare(T aI, T 02);
type you're comparing-it's a separate class. So you can
make as many of these as you like! Waut to compare
songs by artist? Make an Artis tCompara to r. Sort by beats
per minute? Make a BPMCornparator.
Then all you need to do is call the overloaded sortt)
method that takes the List and the Comparator that will
help the sortt) method put things in order.
The sortO method that takes a Comparator will use the If you pass aeomparator to the
Comparator instead of the element's own compareTo(}
method, when it puts the elements in order. In other sortO method. the sort order is
words, if your sortt) method gets a Comparator, it won't
even call the compareToO method of the elements
determined by the comparator
in the list. The sortf) method will instead invoke the rather than the elements own
compareO method on the Comparator.
So, the rules are:
compareToO method.
~ Invoking the one-argument sort(L1st 0) method
means the list elemenfs compareToO method
detennlnes the order. So the elements Inthe list
MUST Implement the Comparable Interface.

~ Invoking sort(Llst 0, Comparator c)means the


list elemenfs compareToO method will NOT be
called, and the Comparators compare{) method
will be used Instead. That means the elements
Inthe list doNOT need to Implement the
Comparable Interface.

Q.: So does this mean that If you have a class that Q.: But why doesn't ~very class Implli!ment Comparable1
doesn't Implement Comparable, and you don't have the
source code, you could stili put the things In order by
creating 8 Comparator7 A: Do you really believe that everything can be ordered?
If you have element types that Just don't lend themselves to

A: any kind of natural orderIng, then you'd be misleading other


That's right. The other option (if It's posslble) would be programmers If you implement Comparable. And you aren't
to subclass the element and make the subclass implement taking a huge risk by not Implementing Comparable, since
Comparable. a programmer can compare anything in any way that he
chooses using his own custom Comparator.

552 chapter 16
collections with generics

UpdatiMQ the Jukebox to use a COlMparafor


We did three new things in this code:
1) Created an inner class that implements Comparator (and thus the rompare()
method that does the work previously done by romjJrue'Ib()).
2) Made an instance of the Comparator inner class.
3) Called the overloaded sortt) method. giving it both the song list and the
instance of the Comparator inner class.
Note: we also updated the Song class tcString() method to print both the song
title and the artist (It prints title: artist regardless of how the list is sorted.)

i mp o r t java .util. ";


imporc java.io.·;

public class JukeboxS (


ArrayList<Song> songList = new ArrayList <Song>();
public static void main(String[ ] args) {
new Jukebox5 () .go();

class Artistcompare implements Comparator<Song>


public int campare(Song one, Song twO) (
return one. qatArtist () . compareTo (two. g8tArtist (» ;
~
ni~ bet.OI'/I!1
i} Sh-i",~ (tne artirt)

pUblic void got) {


getSongs();
System.out.pr intln(songLi s t);
Collections.sort( songList);
System.out.println(songL ist);
~ Make a~ i~Ylt.t: ~ the
ArtistCompare artistCompare:: new ArtistCompare () ; C--y.lrat.m- IMer t.lau.
Collections. sort (songList, artisbCompare);

System.out .println(SongLi s t J ;

void getSongs() {
II rIo code here Note: we've made sort-by-title the default sort. by
keeping the compareToO method In Song use the
titles. But another way to design this would be to
void addSong(String l ineTo Parse} { Implement both the title sorting and artist sorting as
II parse line an d add co song list inner Com pa rater classes, and not have Song Implement
Comparable at all.That means we'd always use the two-
arg version of Collections .sortl).

you are here ~ 553


collectJons exercise

import
public class SortMountains {
LinkedList'- - - - - - - mtn new LinkedList, ()i
class NameCompare
public int cOmpare(MouDtain one, Mountain two) {
{
Reverse Engineer
return Assume this code eXiStS in
II Single !1le. Your joh is
}
class HeightCompare {
to nil in the hlankS So the
pubLi.c int compare (Mountain one, Mountain two) { the program will create the
return ( ); output shawn.
}
} Note : answers are at the end of
public static void main(String [J args) { the chapter,
new SortMountain().go():
}
public void got) {
mtn.add(new Mountain(ULongs", 14255»;
mtn.add(new Mountain(UElbert", 14433»i
mtn.add(new Mountain(nMarOOn M , 14156»i
mtn.add(new Mountain(UCastle", 14265»;
System.out.println(U a s entered:\n" + mtn);
NarneCornpare nc = new NarneCompare();

System.out.println(uby narne:\nn + mtn);


HeightCompare he = new HeightCompare();

System.out.println(nby height:\nn + mtn)i


}
}

class Mountain {

Output:

File EdH WIndow Hel ThlsOne'sFor8ob


%java SortMountains
{
as entered:
[Longs 14255, Elbert 14433, Maroon 14156, castle 14265]
}
by name:
{ lCastle 14265, Elbert 14433, Longs 14255, Maroon 14156)
by height:
} [Elbert 14433, Castle 14265, Longs 14255, Maroon 14156]
}

554 chapter 16
collections with generics

~ your penCil fiTI-in-the-blanks


For each of the questions below, fill in the blank
with one of the words from the "possible answers"
list, to correctly answer the question. Answers are
at the end of the chapter.

Possible Answers:
Comparator,
Comparable,
compareTo( ),
compare( ),
yes,
no
Given the following compilable statement:

Collections.sort(myArrayList);

1. What must the class of the objects stored in myArrayList implement?

2. What method must the class of the objects stored in myAr r a y Li s t implement? _
3. Can the class of the objects stored in myArra yLi st implement both
Comparat or AND Compa rable?

Given the following compilable statement:

Collections . sort (myArrayList, myCompare);

4. Can the class ofthe objects stored in myArra yList implement Comparable?

5. Can the class ofthe objects stored in myArrayList implement Comp a r a t o r ?

6. Must the class of the objects stored in myArrayList implement Comparable? _

7. Must the class of the objects stored in myArrayList implement Comparator? _

8. What must the class of the myCompare object implement?


9. What method must the class of the myCompare object implement?

you are here ~ 555


dealing with duplicates

Uh"'oh. fhe sorting all works, but now we have duplicates...


The sorting works great, now we know how to son on both title (using the Song object's
compareToO method) and artist (using the Comparator's compare 0 method) . But there's
a new problem we didn't notice with a test sample of the jukebox text file-the sorted list
containsduplicates.
It appears that the diner jukeboxjust keeps writing to the file regardless of whether the
same song has already been played (and thus written) to the text file. The SongListMore.txt
jukebox text file is a complete record of every song that was played, and might contain the
same song multiple times.

SongllstMore. txt

Pink Moon/Nick Drake/5/80


Somersault /Zero 7/4/84
Shiva Moon/Prem Joshua/6/120
Circles/BT/5/110
Deep Channel/Afro Celts/4/120
Passenger/Headmix/4/100
Listen/Tahiti 80/5/90
Listen/Tahiti 80/5/90
Listen/Tahiti 80/5/90
Clrcles/BT/5/110

556 ch ap ter 16
collections with generics

-
We t1eed aSet it1stead of a List
From the Collection API, we find three main interfaces, List, Set, and
Map. ArrayList is a List, but it looks like Set is exactly what we need.

~ LIST· when sequence matters


Collections that know about Index posfflon.
Usts know where something isin the list You
can have more than one element referencing List
the same objeel

~ SET· when uniqueness matters


Collections that do notaI/ow duplicates.
Sets know whether something isalready in the collection.
You can never have more than one element referencing
the same object (or more than one element referencing
two objects that are considered equal-we'lIlook atwhat
object equality means ina moment).
Set

~ MAp· when finding somethIng bykey matters


Collections that use key-value pairs.
Maps know the value associated with a given key. You
can have two keys that reference the same value, but you
cannot have duplicate keys. Although keys are typically
String names (so that you can make name/value property
lists, for example), a key can be any object. Map

you are her e ~ 557


the collections API

The Collectiot1 API (part of it)


Notice that the Map interface doesn't
actually extend the Collection interface,
but Map is still considered part of the
"Collection Framework" (also known
as the "Collection APr) . So Maps are
Collection
still collections, even though they don 't
(interface)
includejava.utilCollection in their
inheritance tree.
(Note: this is not the complete
collection API; there are other
/'
Set List
classes and interfaces, but (interface)
these are the ones we care
(Interface)
I
most about)
/' ,,
.",, II-
I
I
I
I
,
I
.
-r;
I
l\'"
,
\

\
I
r., ,
,
" ,,
SortedSet ,,
r
,,
\ ,
I ,
\ ,,
(Interface) , I
I I
I ,
,
,, ,,
I \ \
I
" ,,
, I I
I
,, ,,
I ,
I I

,,
\
I
I
, I
I
,
, "

TreeSet LinkedHashSet HashSet ArrayList LlnkedLlst Vector

.-------- KEy-------.
T
.T.,
extends Ma~l dOY\'+' ~'ll.u"d '(\"00>\
,, implements
b..+.
jiIVel...·h l.Collet -!:.i Ol'l,
"thl'f)ve lVII tol'llidll"ld
Map to b~ ~il..-t of the "
implementation class

interface
(Interface)
-r;
, 1\' ....,,,
I "tolled:.iOl'1 ~\'"el ... twetrk
i" Java. ~o a Ma~ is
still Ye{~ed to ell a
,, ,
I

\
, ,, tolled:.iol'\'
I ,,
SortedMap , I
,,
\
\ ,,
r ,,
(Interface) ,, ,
I
,
. I
, I
,,
I
,,
,,
,,
' ,
,•
/
/ I

II
/ \

TreeMap HashMap LinkedHashMap • Hashtable

"'-----.". I

558 chapter 16
collections with generics

Using a HashSet instead of ArrayList


We added on to the Jukebox to put the songs in a HashSet. (Note: we left out some
of the Jukebox code, but you can copy it from earlier versions. And to make it easier
to read the output, we went back [Q the earlier version of the Song's toStringO
method, so that it prints only the title instead of title and artist.)

i mp o r t j a v a . ut i l . ~ ;
: mp o r t j a v a . i o . * ;

ub l i c c las s J u ke b o x 6 {
Ar rayL i st <Song > s on g Li s t = n e w ArrayList <So ng > (l ; ~

I I ma i n me t h o d e c . ~

p ub li c v o i d g o () ( L L . A... d L: +.
We die!..'+. t.ha)\~e ~d$ofI~(), so I+' s1:.i1l y"Vl 1;he $O,,~ ," a" -- y LS
g e t S o n g s();~

S y s t e m. o u t . p r i n t l n (s o n g Li s t );
~~e we t.__eah a "ew l1asl-.Sct
Col l e c t i o n . s o r ( s o ng Li s t ) ;
V',wameW-iz.ed t.D hold .so..~
Sys t e m. ou t . p r i n t l n (s o n g Li s t );

HashSet<Song> songSet = new HashSet<Song>();


songSet.addA11(songList);
System.out.println(songSBt);
)

II ge t So ng s () an d a d d Son g () methods

A~ te-- ~iYl~
t.\-Ie A----a'fLi!l
Ch'j -title).

AHe.. ~\l.Ui",~ it.


into a }lash&t.
a"a Y'"i,,-tiYl~ tnt:
~a1~ (we dia",'t
The &f. didr/f. help!! (A"d it. lost. ih soV't. o...de... eall sor\:.O a~a;n) .
we y"t t.ne list iYlto a
We still have all ih~ dl.lplitaus! ",ne"
\1as~t.1 blat. we'll WcifY'I a~t.
that tm~ latey··J

you are here) 559


object equality

What tttakes two objects equal? If two objects foo and bar are
equal, foo.equa's(bar' must be
First . we have to ask-what makes two Song references 'rue, and both foo and bar must
duplicates? They must be considered equal. Is it simply two return the same value from
hashCode(J. For a Set to treat
references to the very same object, or is it two separate objects
two objects as duplicates, you
that both have the same Lilli? must override the hashCodeO
This brings up a key issue: reference equality vs. object equality. and equals() methods inherited
from class Object, so that you
can make two different objects
). Reference equality be viewed as equal.
Two references, one object onthe heap,
Two references tIlat refer tothe same object on
the heap are equal. Period. Ifyou call the hashCodeQ method on
both references. you'll get tile same result Ifyou don't override tile
hashCode() method, tile default behavior (remember, you inherited
this from class Object) isthat each objecl will gel a unique number
(most versions ofJava assign a hashcode based on the objecfs
memory address on the heap, so no two objects will have the same
hashcode).
Ifyou want toknow iftwo references are really referring to the same
object. use the == operator. which (remember) compares the bits in Song
the variables. Ifboth references point to the same object. the bits will if (faa -- bar) {
be Identical. II both references are referring
II to the same object on the heap

). Object equality
Two references, twoobjects onthe heap, but
the objects are considered meaningfully equivalent
Ifyou want to treat two different Song objects as equal (for
example if you decided thaI two Songs are the same if they have
matching title variables), you must override both the hashCodeO
and equalsO methods inherited from class ObjecL
As we said above, ifyou don Yoverride hashCodeO, the defauh
behavior (from Object) is to give each object a unique hashcode
value. So you must override hashCodeO to be sure that two
equivalent objects return tile same hashcode. But you must also Song
override equalsO so that ifyou call non either object. passing in
the other object, always returns tnn.
if (foo.equa18(bar) && foo.bashCode() . . bar.hashCode(»)
II both references are referring to either a
II a single object , or to two objects that are equal

560 chapter 16
collections with generics

How a HashSet checks for duplicates: hashCode() at'd equals()


When you put an object into a Hashset, it uses the HashSet finds a matching hashcode for two objects-
object's hashcode value to determine where to put one you're inserting and one already in the set-the
the object in the Set. But it also compares the object's HashSet will then call ooe of the object's equalsr)
hash code to the hashcode of all the other objects in methods to see if these hashcode-matched objects
the Hash Set, and if there's no matching hash code, really are equal.
the HashSet assumes that this new object is not a And if they're equal, the HashSet knows that the
duplicate. object you're attempting to add is a duplicate of
In other words, if the hashcodes are differen t, the something in the Set, so the add doesn't happen .
HashSet assumes there's no way the objects can be You don't get an exception, but the HashSer's add 0
equal! method returns a boolean to tell you (if you care)
So you must override hashCode 0 to make sure the whether the new object was added. So if the addO
objects have the same value. method returns false, you know the new object was a
duplicate of something already in the set,
But two objects with the same hashCodeO might not
be equal (more on this on the next page). so if the

I need to know
if your hashcode
values are the same.

Your hashcodes
are the some, but ore
you REALLY equal? eqUaJs( bar)

you are here ~ 561


overriding hashCodeO and equalst)

The So.,g class with overridde.,


hashCodeU a.,d equals()
class Song impl e me n t s Co rnp e r eb Le-cSon q> {
Sex-i og t i d e ;
Stri ng art is t ;
St.ri ng rating;
Stri ng bpm;
. t.h t. Btl, is a S-\:.vincy
public boolean equals (Object aSong) ( The qR~AT neWS IS a -Jd, n eQl>d\~O
L . \la~e ell' O~t.Y""IO \
Song s :: (Song) aSong i el\'lei S't... \,,~s 'II to do is aslt. one
return getTi tle () . equals (s . getTi tie ( ) ) il;;--' ",ct,hod. ,S:' all ~~t.t. ot.heY ~n~' ~ ·btl,·
'H,
title it It s t.'\"<i

public int hashCode () ( Sa... e dec'll h~e th Sh'


re turn ti tIe. hashCode () ~ hashCodd) ... dhod e IP\~ d,,~ has a" oV~idde"
l.dJli,,~ hdShCodeO ~"S~t~t'~"
fh: SA
and ',\lId/SO are l<..lil'l
jNtyeb..n. the: res14H:. of
e· ~ le how h~shCodeO
public Lrrt comp a r e To (Song s ) ( 9 ME IlUit...te var-Ic'lbk
r e t u r n t i t l e . c omp a reTo (s . get Ti t l e ( » ) ;

Song(Str i ng t, String a, St ri ng r , St.ring b ) I


titl e = t;
ar t i s t = a ; Now it wot"k.s! No dvplit.ates when wt.
r a t i ng = r ; fYi"f. -i -the Itas~t. BI.<-t we did,,' t
bpm = b ; zall sortO a~in, and when we pllt
the AyrayList into t.he ltashSd., -the
Itas~d: didn'+, fr-e~ve the sort ~deY.
p ublic St ri ng ge t Ti t l e ( )
r e t u r n t.i t l e ;

publ i c Str in g ge t Ar t i s t ( J
r e t u r n a r t i st.;

pUbl i c St r i ng getRacing()
r e t uxn r a tin g;

pu bl i c St r ing ge t Bp m( ) {
r t u r n bp m;

pu b lic St r i ng t oString(j
r e t u r n t i t.l e;

562 chapter 16
collections w ith generics

tbere1EU"er\l? 0
O umo ~uesfj9n8

Q: How come hashcodes can be the same


even Ifobjects aren't equal7

A..: Hash5ets use hashcodes to store the ele-


ments in a way that makes it much faster to access.
If you try to find an object in an ArrayList by giving
the ArrayList a copy of the object (as opposed to
an index value), the ArrayList has to start searchIng
from the beginning, looking at each element in
the list to see if it matches. But a Hash5et can find
an object much more quickly, because it uses the
hashcode as a kind of label on the "bucket''where
It stored the element. So If you say, "I want you
to find an object in the set that's exactly like this
one ..." the Hash5et gets the hashcode value from
the copy of t he Song you give it (say, 742), and
then the HashSet says, MOh, I know exactly where
the object with hashcode 11742 is stored ...: and it
goes right to the #742 bucket.
This isn't the whole story you get in a computer
science class,but it 's enough for you to use Hash-
Sets effectively. In reality, developing a good hash-
code algorithm is the subject of many a PhD thesis,
and more than we want to cover In this book .
The point Is that hashcodes can be the same
without necessarily guaranteeing that the objects
are equal, because the -hashing algorithm" used In
the hashCode() method might happen to return
the same value for multiple objects. And yes,that
means that multiple objects would all/and in the
same bucket In the HashSet (because each bucket
represents a single hashcode value), but that 's not
the end of the world. It might mean that the Hash-
Set is Just a little less efficient (or that it's filled
with an extremely large number of elements), but
if the HashSet finds more than one object in the
same hashcode bucket, the HashSet will simply
use the equalsO method to see If there's a perfect
match . In other words, hashcode values are some-
times used to narrow down the search,but to find
the one exact match, the HashSet still has to take
all the objects in that one bucket (the bucket for
all objects with the same hashcode) and then call
equalsO on them to see if the object it's looking for
is In that bucket.

yo u are here ~ 563


TreeSets and sorting

At1d if we wat1t the set to stay


sorted, we've got TreeSet -
TreeSet is similar to HashSet in that it prevents duplicates. But it also keeps the list sorted. It works
just like the sortt) method in that if you make a TreeSet using the set's no-arg constructor, the
TreeSet uses each object's compareToO method for the sort. But you have the option of passing
a Comparator to the TreeSet constructor, to have the TreeSet use that instead. The downside to
TreeSet is that if you don't need sorting, you're still paying for it with a small performance hit. But
you'll probably find that the hit is almost impossible to notice for most apps.

imp o rt jav a . ut il. * ;


imp o r t j av a . io . *;
pu blic cla ss JukeboxS {
Arra yLis t <So ng> songLis t ne w Ar ra yLi s t <Son g > () ;
i nt val ;

publ i c s t a t i c vo i d main (St r ing [ ] a r gs ) {


new Jukebox8 () . go ();

L' L ad ~ \tashSet.
L' L - T YeeSe" IYlSU; +.0
p ublic v oid go () { IYlstaYl-i,au; a T eSet tOYlstylOt I Y
get Songs () ; Ca\\iYl~ the Ylo-a;? Y\ he SoYlC?J o'ojett s
System .out.pri nt l n (s ongL i s t) ; ( WleaYlS the;)tWl:th~e ~OY the soYt;.
Co l l e c t i ons . s o r t (songLi st) ; t.OWIyayeT L_ )
Y
System . ou t . p r int l n (songLis t) ; t.O"'\d halle yClsselAJ 'IYI a Co",yClYClW '
TreeSet<Song> songSet = new TreeSet<Song>(); (We
songSet.addA11(songList);~
Sy s t.em, out . println (songSe t ) ; ~e 'al'l aAdd all the SOI'l~s .froll\ the l+ashSet
lASlh~ ~d~ ,110. (Or we 'olAld have added t he
SOI'l~S Il'Id1v1d"'1l1y lASil'\~ sOI'\~et.add() ' lASt
vo i d ge t Songs () { the way we added SOI'l~S t;, the Arra~List.)
tr y {
Fil e file = new Fi le (" Song ListMore .tx t ") ;
Buf fe r e dRea de r r e a de r = new Buf fer e dRea de r (ne w FileRe a de r (file »;
String l i ne = null ;
wh i l e ( (l i ne= r e a der .re adLi ne ( » != nul l) {
addSong (li ne) ;

c a t ch( Exc e pt i on ex ) {
e x . p r i nt St a c kTr a c e () ;

vo i d a ddSong (String line ToPa rse ) {


Stri ng[ ] to ke ns = line ToPars e . s p lit (" /" ) ;
Song n ex tS on g = ne w Son g (t okens[ O] , t o ke ns [ l ], to ke ns [2] , t ok e ns [3 ] ) ;
s on gList . a dd (ne xtSong ) ;
collections with generics

What you MUSf kttow about freeSet...


TreeSet looks easy, but make sure you really understand what you need to
do to use it. We thought it was so important that we made it an exercise so
you'd have to think about it. Do NOT turn the page until you've done this .
We mean it.

V your pencil import java.util.-;

public class TestTree {


Look at this code. public static void main (String[] arqs) (
ReadIt carefully, then new TestTree() .go():
answer the questions
below. (Note: there
are no syntax errors public void go() {
In this code.) Book bi = new Book ("Bow cats Work") ;
Book b2 new Book ("Remix your Body") ;
Book b3 = new Book("Finding Emo");

TreeSet<Book> tree = new TreeSet<Book>() ;


tree . add (hl) ;
tree . add (b2) ;
tree. add (1:13) :
Systam.out.println(tree):

class Book (
String title;
public Book(String t) {
title = t;

1).What Is the result when you compile this code?

2). If It compiles, what Is the result when you run the TestTree class7

3).lf there is a problem (either compile-time or runtime) with this code, how would you fix It7

you are here ~ 565


how TreeSets sort

freeSet elettte.,ts MUSf be cotttparable


Tre eSet can't read the programmer's mind to figure out how the
object's should be sorted. You have to tell the TreeSet how.

To use a TreeSet, one of these


things must be true:
)- The elements in
the list must be of a type that
implements Comparable

The Book class on the previous c las s Boo k implements Comparable


page didn't implement Comparable, so it String title;
wouldn't work atruntime. Think about it, the publ i c Bo ok(S tring t ) {
poor TreeSet's sole purpose in life istokeep t itle = t ;
your elements sorted, and once again-ithad }

no idea how to sort Book objects! Itdoesn't fail public int compareTo(Object b)
atcompile-time, because the TreeSet addO Book book = (Book) b;
return (title.compareTo(book.title»;
method doesn't take a Comparable type,The
TreeSet addO method takes whatever type
you used when you created the TreeSet. In
other words, ifyou say new TreeSet<Book>O
the addO method isessentially add{Book). And
there's no requirement that the Book class
implement Comparable! But itfails atruntime
when you add the second element tothe set.
That's the first time the set tries to call one of
the object's compareToO methods and... can't.

OR public class BookCompare implements Comparator<Book>{


)- You use the TreeSet's public int compare(Book one, Book two) {
overloaded constructor return (one.title.compareTo(two.title» ;
that takes a Comparator

TreeSet works a lotlike the sortO cla s s Te s t {


method-you have a choice ofusing the publi c vo id go ( ) {
element'scompareToO method, assuming Bo ok b l new Boo k(" How Cats Work") ;
Boo k b 2 = n e w Book ("Remix y our Body " };
the element type implemented the
Boo k b 3 = new Bo ok("Fi nd i n g Emo");
Comparable interface, OR you can use BookCompare bCompare = new BookCompare();
a custom Comparator that knows how TreeSet<Book> tree = new TreeSet<Book>(bCompare);
tosort the elements in the set. To use a tree . add(new Book( "How Cats Work" ) ;
custom Comparator, you call the TreeSet tree . add(new Bo ok( "Fi n d ing Emo" );
constructor that takes a Comparator. t r e e . a d d (ne w Bo o k ("Remi x your Body" ) ;
System .out .pr i nt l n(tree) ;

566 chaptert fl
collections with generics

We~ve See" Lists and Sets~ "OW we~11 use a Map


Lists and Sets are great, but sometimes a Map is the best collection (nor Collection
with a capital "Cn-remember that Maps are part of Java collections but they don't
implement the Collection interface) .
Imagine you want a collection that acts like a property list, where you give it a name
and it gives you back the value associated with that name. Although keys will often be
Strings, they can be any Java object (or, through autoboxing, a primitive) .

Each element in a Map is actually


TWO objects-a !!ey and a value.
You can have duplicate values, but
NOT duplicate keys.
Map

Map example
import java.util.~;

pUblic cl ass Te stMap

publ ic s t at i c void mai n(S t r i ng [ a r gs ) {

BashMap<String, Integer> scores = new Ba.ahMap<String, Integer> 0 ;

scores.put ("Kathy" / 42); A - - Use Plot() j'f>$~Cld 0+ ddO r


t", 343)·""""
scores. P U t ( " Be r , -L 1_1.
11; WI<l.1 t.WO ClrQIo"" bCl (k J ClndInow
) o-t l.Olor1e
scores .pu t( " Sk y 1 er " , 420) ; J en ~y,va~ .

s ys t e m. ou t . p r i nt ln (s co r es ) ; ~
Sy s t em . ou t. p r i n t Ln (scores. get ("Bert") l; The dO 1\ 1.
~ ""e~od wkes a key, (ll<d
t'etuhlS the val~ (in this ~S(:, an h"~9t\").

you are here 567


generic types

Fit1all't back to get1erics


If a method argument is an array
Remember earlier in the chapter we talked about how methods of Animals, it will also take an
that take arguments with generic types can be ... weird. And we array of any Animal subtype.
mean weird In the polymorphic sense. If things start to feel
strange here.just keep going-It takes a few pages to really tell In other words, if a method is
the whole story. declared as:

We'll start with a reminder on how array arguments work, void loo(AnimalU a) { }
polymorphically, and then look at doing the same thing with
generic lists. The code below compiles and runs without errors: Assuming Dog extends Animal,
you are free to call both:
Here's how It works with regular arrays:
loo(anAnimalArray);
foo(aDogArraY)i
import java.util .*;

pUblic class TestGenericsl (


public static void main (String(] args)
new TestGenericsl() . go () ;

public void got) {


Animal[] animals ~ (new Dog() I new Cat(), new Dog()};
Dog[] dogs: (new Dog(), new Dog(), new Dog()};~
takeAnimals (animals) ; D~tlat'"e ,a"d tl'"~t.e a D~ attay,
takeAnimals (dogs) ; <, Call takeAr,i"'<llsO, l.lSi,,~ boih t.hat holds 0,.,1~ Do¥ (the t.o",~il~t'"
~ an-a'! t'lfes 41 at'"~lohe,.,ts, .. wo,,'t. Itt yo... "",-1:. a Cat. i,.,) ,

public void takeAnimals (Animal {]


for (Animal a: animals) (
a.eat () i
} »:.:

abstract class Anima..l (


void eat{) (
System .out.printin ("animal eating");

)
class Dog extends Animal
void bark() ( )
I
class Cat extends Animal
void meow() { }

568 chapter 16
collections with generics

Using polYtMorphic argulMenfs at'd generics


So we saw how the whole thing worked with arrays, but will it work
the same way when we switch from an array to an ArrayList? Sounds
reasonable, doesn't it?
First, let's try it with only the Animal Arrayl.ist. We made just a few
changes to the go 0 method:

Passing In just ArrayList<Anlmal>

public void gel) t


ArrayLis t<Animal> animals = new ArrayLis t<Anima.l> () j
anima ls.add(new Dog());
an i mal s. add (new Cat (»); ~ We hdve t.o add Ol'\e af. d ti .... e sinte theyc's
animals. add (new Dog () ) ; ShoYUkt S'ft'Ul)( like thet"c is .for drTay lY~or..

takeAnimals (animals) ; <-- This. is t.he Sdme lode' e""cr


~•
'"
.,j.
l'IO'N
1,,,
{;.nc Cllli...als"
v.)Ylelbl, Yetm t.o illl An-ayLisi ilUwd o-f an-ely.

~ublic void takaAnimals(ArrayList<Animal> animals) (


for (Animal a: animals) (
a. eat () ;
I

Complies and runs just fine

you are here ~ 569


polymorphism and generics

~ut will it work with ArrayList<~og)?


Because of polymorphism. the compiler let us pass a Dog array
to a method with an Animal array argument. No problem. And
an ArrayList<Animal> can be passed to a method with an
ArrayList<AnimaI> argument. So the big question is, will the
ArrayList<Animal> argument accept an ArrayList<Dog>? If it works
with arrays, shouldn't it work here too?

Passing in just ArrayList<Dog>

pu bli c void go () (
Ar r a y Lis t <An i ma l > an i ma l s n e w Ar r a yLi st "An i ma l > {) ;
a n i ma ls . a d d (n e w Dog {) ) ;
a n i mals . a d d (ne w Ca t {) ) ;
a n i ma l s.a dd {new Dog {) ) ;
t a k eAn i ma l s (an i ma ls); ...~
- W'now
k .1h I
1: if inc w~ked. .fine.

ArrayList<Dog> dogs = new ArrayList<Dog>() ;


dogs. add (new Dog () ) ; A1ak, a Doc ltr'rayList. d d L
dogs. add (new Dog () ) i - J " pill; d tOlAr1e d~ ill.
takeAnimals (dogs) ; ~ Will this w I. .Lh .1
Qt"1<; now 1: a~ we thd~ed
.f...o... dl\ drYay to dll A-r.-dyList?

public v o id takeAnimals(ArrayList<Animal> animals) (


fo r (An i ma l a: animals) (
a . eat();
l

When we compile It:

%java TestGenerics3

TestGenerics3.java:21: takeAnimals(java.util.
ArrayList<Animal» in TestGenerics3 cannot be applied to It looked so ri~ht,
(java.util.ArrayList<Dog» bitt went so \t,fr"on~...
takeAnimals(dogs);

1 error

570 chapter 16
collections with generics

And rm supposed to be OK with this? That


totally screws my animal simulation where the
veterinary program takes a list of any type of
animal. so that a dog kennel can send a list of dogs,
and a cat kennel can send a list of cats... now
you're saying I can't do that if I use collections
instead of arrays?

What could happet1 if it were allowed...


Imagine the compiler let yOIl get away with that, It let you pass an
ArrayList<Dop to a method declared as:

publ i c void takeAnimals (ArrayList<Animal> animals) (


for (Animal a: animals) (
a.eat();

There's nothing in that method that woks harmful, right? After all,
the whol e point of polymorphism is that anything an Animal can
do (in this case, the eatj) method), a Dog can do as well. So what's
the problem with having the method call eat() on each ofthe Dog
references?
Nothing. Nothing at all.
There's nothing wrong with that code. But imagine thiscode instead:

public void takeAnimals (ArrayList<Animal> a nimals) (


animals. add (new Cat () ) ;.1 \J.k II We Jl.\S"(.
~ Ties..
. L k a C<1"(.L·ITl wnCl"(.
L
s"(.1ol.
L L

Mj~ht be a D~-ol'lly ArrClyList-

So that's the problem. There's certainly nothing wrong with adding a


Cat to an ArrayList<An.imal>. and that's the whole point of having an
ArrayList of a supertype like Animal-so that you can put all types of
animals in a single Animal Arrayl.ist.
But if you passed a Dog Arrayl.ist-s-one meanllO hold ONLY Dogs-
to this method that take s an Animal Arrayl.ist, then suddenly you'd
end lip with a Cat in the Dog list. The compiler knows that if it lets
you pass a Dog ArrayList into the method like that, someone could,
at runtime, add a Cat to your Dog list . So instead. the compiler just
won't let you take the risk .
Ifyou declare a method to take ArrayList<AnimaJ> it can take ONLY an
ArrayLiskAnimal>, not ArrayList<.Dog> or ArrcryLi.rt<Cat>.
you are he re ~ 571
arrays vs, ArrayUsls

Wait a minute ... if this is why they won't Ie.t


you pass a Dog ArrayList into a method that
takes an Animal ArrayList-to stop you from
possibly putting a Cat in what was actually a Dog list.
then why does it work with arrays? Don't you have
the same problem with arraysl Can't you still add
a Cat object to a Dog[) ?

Array types are checked again at


...runtime, but collection type checks
happen only when you compile
-
Let 's say you do add a Cat to an array declared as Dog[l (an array that
was passed into a method argument declared as Animal[], which is a
perfectly legal assignment for arrays) .

public void got) {


Dog[] dogs: {new Dog() , new Dog(). new Dog()}:
takaAnima1s(d~

public void takeAniJDals (Animal [1 animals) (


animals [0] =
new cat();
~ W~ pvt. a PI(W Celt. il'lto d D~ arra~. The
tc,..piley allowed it, beta\l1( it kl'lows that
't01A ",i~ht. have passed a Cdt. an"ely cfr Al'Iill'lal
arra't to the ,..et.hod, so to th~ to",pile\'" it
was possible that. -Chis was O~.

It compiles, but when we run it:

Whew! At. leost the


JVNl stopftd it.

572 chapter 16
Wouldn't it be dreamy if there were
a way to still use polymorphic collection
types as method arguments, so that my
veterinary program could take Dog lists
and Cat Iist$? That way I could loop through
the lists and call their immunizeO method,
but it would still have to be safe so that you
couldn't add a Cat in to the Dog list. But I
guess that's just a fantasy...
generic wildcards

Wildcards to the rescue


It looks unusual, but there is a way to create a method argument that
can accept an ArrayList of any Animal subtype. The simplest way is to
use a wildcard-added to theJava language explicitly for this reason.

public void takeAnirnals (ArrayLiot<? extends Animal> animals) I


for/Animal a: animals)
a .eat o .
(

<.. Re.... e.... bey, t.he keywoyd ([I!')(.te~ds"

-
here ""ear..s ei-chey t'llUl'Ids OR
·I ....ple"'e"ts dt~el'ldi,,~ 0" t.he
So now you're wondering, "What's the diffcrenc? Don't you have tyye. ~ i~ you wa"t. to take
the same problem as before? The method above isn't doing
al'l AttayList ot t'tfes that
anything dangerous-a-calling a method any Animal subtype is
guaranteed to have-but can't someone still change this to add a i",~le",el'lt t.he Pd:. il'lUy~atel
Cat to the animals list, even though it's really an ArrayLisL<DOg>? yov.' d detlaye it as:
And since it's not checked again at runtime, how is this any
different from declaring it without the wildcard?" /tr-.,.ayList<? ~ul'lds Pd:>
And you'd be right for wondering. The answer is NO. When you
use the wildcard <?> in your declaration, the compiler won 't let
you do anything that adds to the listl

574 chapte r 16
collections with generics

Alternate syntax for doing the salMe thing


You probably remember that when we looked at the sortf ) method,
it used a generic type, but with an unusual format where the type
parameter was declared before the return type. It's just a different way
of declaring the type parameter, but the results are the same:

This:
public <T extends Animal> void takeThing(ArrayList<T> list)

Does the same thing as this:


public void takeThing(ArrayList<? extends Animal> list)

:t1ere1lU"EH-? 0
D UU}lJ ~uestI9ns

Q: If they both do the same thing, why would you use


one over the other?

A.: It all depends on whether you want to use "T" some-


where else. For example, what if you want the method to
have two arguments-both of which are lists of a type that
extend Animal? In that case, it's more efficient to just declare
the type parameter once:

public <T extends Animal> void takeThing(ArrayList<T> one, ArrayList<T> two )

Instead of typing:

public void takeThing(ArrayList<? extends Animal> one,


ArrayList<? extends Animal> two )

you are here ~ 575


be the complier .exerci se

BE the ~omri1er, advan~eJ


Your job Is to play complier and determine which of
these statements would compile. But some of thls
code wasn't covered in the chapter, so you need to
work out the answers based on what you DID learn,
applying the rrules" to these new situations. In
some cases, you might have to guess, but the
point is to come up with a reasonable answer
based on what you know so far.
(Note: assume that this code is within a legal class and
method.)

Compiles?

[JArrayList<Doq> dogsl : new ArrayList<Animal>()i

o ArrayList<Animal> animalsl = new ArrayList<DO<J> () i

o List<.Ani.mal> list = new ArrayList<Anima.l> () i

o ArrayList<Dog> dogs = new ArrayList<Doq> () ;

o ArrayList<Animal> animals = dogs i

o List<Dog> dogList : dogs i

o ArrayList<Object> objects = new ArrayList<Object>();

o List<Object> objList = objects;

o ArrayList<Object> objs = new ArrayList<oog>0 ;

576 chapter 16
collectlons with generics

import java. util. * ; &lUfion 1;tl the ~everge


public class SortMountains { Engineer" sh.arren ~reise,
LinkedList( Mountain> mtn new LinkedList(Mountain> ();
class NarneCompare Implements Comparator <Mountain> {
public lnt compare(Mountain one, Mountain two) {
return one.name. compareTo(two. name):

}
class BeightCompare Implements Comparator <Mountain> {
public int compare(Mountain one, Mountain two) {
return (two. height - one. height) ;

}
public static void main(String [) args) ( ~ . "na"
D"\c! 'to\> "of)l.t "'"~ ~,;.~"
e ;)")I;," ;,
;~ D~C~NDIN~ .se~lIC>l.t? "
new SortHountain().go():
}
public void go() {
mtn.add(new Mountain(ULongs U, 14255»:
mtn.add(new Mountain(UElbert'", 14433);
mtn.add(new Mountain(UMaroon u , 14156»;
mtn.add(new Mountain(UCastle 14265»:
U
,

System.out.print1n(Uas entered:\n'" + mtn);


NarneCompare nc = new NarneCompare();
Collectlons.sort(mtn. nc).
System.out.println(Uby name:\n'" + mtn);
HeightCompare hc = new HeightCompare()i
Collectlons.sort(mtn, he);
Systern.out.prlnt1n(Uby height:\n H + mtn);
}
}

::lass Mountain {
String name: Output:
Int height;
FlIe Edit Window Hel 1l1lsOne'sFor8ob
'l;java Sortl'buntains
Mountaln(String n, Int h) {
as entered:
name = n; [Longs 14255, Elbert 14433. Maroon 14156, Castle 14265)
height = hi by nan'e:
}
[Castle 14265, Elbert 14433, Longs 14255, Maroon 14156]
public String toString( ) { by height:
return name + .. .. + height; (Elbert 14433, Castle 14265, Longs 14255, Maroon 14156)
}

you are here. 577


f111-in-the-blank solution

Possible Answers:
Comparator,
Comparable,
compareTo( )J
compare( ),
yes,
no

Given the following compilable statement:

Collections.sort(myArrayList);

L What must the class of the objects stared in myArrayList implement? Comparable
2. What method must the class of the objects stored in myArrayList implement? compareTo( )
3. Can the class of the objects stored in myArrayList implement both
Comparator AND Comparable? yes
---"------

Given the following cornpilable statement:

Collections .sort(myArrayList, myCompare) i

4. Can the class of the objects stored in myArrayList implement Comparable?---'V'-e_S _

5. Can the class of the objects stored in myArr ayLis t implement Campara tor?--'y'-e5 _

6. Must the class of the objects stored in myArrayLis t implement Comparable? no


- - -- -- -
7. Must the class of the objects stored in myArrayList implement Compa r a t.o rj', ---!..lnox- _
8. What must the class of the myCompare object implement? Comporator
9. What method must the class of the myCompare object implement? comparee)

578 chapter 16
collections with generics

Compiles?

[JArrayList<oog> dogsl = new ArrayList<AnimAl>();

o ArrayList<Animal> anim&ld ::: new ArrayList<Doq> () ;

)if List<Animal> list ::: new ArrayList<Anima.l> () j

o ArrayList<Dog> dogs ::: new ArrayList<Doq> () ;

o ArrayList<Animal> animals = dogs;

J!I List<Dog> dogList = dogs;


~ArraYList<Object> objects = new ArrayList<Object>();

~ List<Object> ObjList = objects;

o ArrayList<Object> objs = new ArrayList<Dog>() ;

you are here ~ 579


17 package, jars and deployment

Release Your Code

It's time to let go. You wrote your code. You tested your code. You refined your code.

You told everyone you know that if you never saw a line of code again, that'd be fine. But in the

end, you've created a work of art. The thing actually runsl But now what? How do you give It to

end users? What exactly do you give to end users? What if you don't even know who your end

users are? In these final two chapters , we'll explore how to organize, package, and deploy your

Java code.We'll look at local, semi-local, and remote deployment options Including executable

jars, JavaWeb Start, RMI, and Servlets.ln this chapter, we'll spend most of our time on organizing

and packaging your code-things you'll need to know regardless of your ultimate deployment

choice. In the final chapter, we'll finish with one of the coolest things you can do In Java. Relax.

Releasing your code Is not saying goodbye. There's always maintenance...

this Is a new ch apt er 581


Java deployment

Peployi"Q your applieatio"


What exactly is a Java application? In other words,
once you're done with development, what is it that you
deliver? Chances are, your end-users don't have a system
identical to yours. More importantly, they don't have your
application. So now it's time to get your program in shape
AJava program is a bunch
for deployment into The Outside World. In this chapter,
we'll look at local deployments, including Executable Jars
of classes. That's the
and the part-local/'part-remote technology called java Web output of your development.
Start. In the next chapter, we'll look at the more remote
deployment options, including RMI and Servlets, The real 'f,Uestion is what
Deployment options to do with those classes
when you're done.
Executable
Jar
100% Local Combination 100% Remote
CD Local
The entire application runs on the
end-user's computer, as a stand-alone,
probably GU!, program, deployed as
an executable JAR (we'll look at JAR
in a few pages.)
What are the advantages and
I1i'\ Combination of local and remote disadvantages of delivering your
~ Java program asa local,stand-
The application is distributed with a
client portion running on the user's alone application running on
local system, connected to a server the end-user's computer?
where other parts of the application
are running. What arethe advantages and
disadvantages of delivering your
Java program as web-based
@ Remote system where the userInteracts
The entire Java application runs on a with a web browser, and the
server system, with the client accessing Java code runs as servlets on the
the system through some non-Java server?
means, probably a web browser.
But before we really get into the whole deployment thing,
let's take a step back and look at what bappens when you've
finished programming your app and you simply want to pull
out the class files to give them to an end-user. What's really
in that working directory?

682 chapter 17
package, jars and deployment

ItMagitte this scettario...


Bob's happily at work on the final pieces of his cool new
Java program. After weeks of being in the "I'mjust-
one-compile-away" mode, this time he's really
done. The program is a fairly sophisticated
CUI app. but since the bulk of it is Swing
code. he's made only nine classes of his
own.
At last, it's time to deliver the program to the
client. He figures all he has to do is copy the
nine class files. since the client already has
the Java API installed. He starts by doing an
1s on the directory where all his files are ...

e o
o
Whoa! Something strange has happened. Instead of 18
files (nine source code files and nine compiled class
files), he sees 31 files, many of which have very strange
names like:
Accoun t$FileListener.class
Chart$SaveListener.class
and on it goes. He had completely forgotten
that the compiler has to generate class files
for all those inner class CUI event listeners
he made. and that 's what all the strangely-
named classes are.
Now he has to carefully extract all the class
files he needs. If he leaves even one of them OUI,
his program won't work. But it's tricky since he
doesn't want to accidentally send the client
one of his source code files, yet everything is
in the same directory in one big mess.

you are here ~ 583


organizing your classes

Separate source code at'd class files


A single directory with a pile of source code and class files is a
mess. It turns out, Bob should have been organizing his files But r thought I didn't have
from the beginning, keeping the source code and compiled a choice about putting the closs
code separate. In other words, making sure his compiled class
files in with the source files.
When you compile, they just go
files didn 't land in the same directory as his source code. there. so what do I do?
1M key is a combination ofdirectury stTudure organizatUm and the
-d compiler option.

There are dozens of ways you can organize your files, and your
company might have a specific way they want you to do it. We
recommend an organizational scheme that's become almost
standard. though .
With this scheme, you create a project directory, and inside
that you create a directory called source and a directory called
classes. You start by saving your source code (java files) into
the source directory. Then the trick is to compile your code
in such a way that the output (the .class files) ends up in the
classesdirectory.
And there's a nice compiler flag, -d, that lets you do that.

Compiling with the -d (directory) flag

%cd Mypr~je~t/s~urce
%javac -d .. /classes
)'\
tells -tht lo"'pi/tr to lot. tht
lo"'piled lode (llats. ~, )
. to th " .oFi es
t;. , t tla1S.ts: di~ettory
ab Ohe dired:A'ry lop clnd
bellk dow" a6:JG'i n 1'ro",
(' I.
Ole
lLlrrent w(l\"k;l'I~ dil'tttory.

By using the -d flag, you get to decide which directory the


compiled code lands in, rather than accepting the default of /r
class files landing in the same directory as the source code. r
To compile all the Java files in the source directory, use: tilroo..YOWl'
htt't
....ai"O

OIl"
%javac -d .. /c1asses *. java ::~;~:ooo'o
lno 10 0

'\. ~. iava tompi 1es AL L oto \O •


"'.'"
..J t: Ll. lUOJOIO
Running your code SOLl~t' -tiles; ill VI' """010\
t\ort"tfl+' dirtt~ MyApp.class MyApp.Java
~cd MyProject/classes (~It1h-ii,,~ noU: c~cr'tl:.hi~ in -lhis lhapicr il1.l_U thilt t},e
%j ava Mini rlOlI ~Ol.lr pr03r-<I", frOlol tUh"c..t ~kin~ dil"Clky (i.e. the ~.~) ij in 'f()l.J.r dilSSf'il!:.h. If '10<>
tht tldues' di'rtltory. have e.... pl,t'fJy sd:. il daSSf'.1th tl\~;t"(ln"'tl\t vill",able. be tcr-bin
that it tor.t.ai"s the "," )
584 chapter 17
package, jars and deployment

Put your Java itt aJAR


-
AJAR file is a Java ARchive . It's based on the pkzip file format, and it lets you bundle
all your classes so that instead of presenting your client with 28 class files, you hand
over just a singleJAR file. lfyou're familiar with the tar command on UNIX , you'll
recognize the jar tool commands. (Note: when we sayJAR in all caps, we're referring
to the archive jilt. When we use lowercase, we're referring to the ja-r tool you use to
create JAR files.)
The question is, what does the client Mwith theJAR? How do you get it to run?
You make th e JAR executable.
An executableJAR means the end-user doesn't have to pull the class files out before
running the program. The user can run the app while the class files are still in the
JAR. The trick is to create a manifest file, that goes in the JAR and holds information
about the files in theJAR. To make aJAR executable. the manifest must tell theJVM
whuh. class has the main() method!

Making an executable JAR

• Make sure all of your class files are in


the classes directory
We're going to refine this in a few pages, but
for now. keep all your class files sitting in the
directory named 'classes'.

MyApp.dass

• Create a manifest. txt file that states


which class has the malnO method
Make Q text file named manifest.txt that has a
one line:
dO\'l' t ,,~t t\lt .t.lass
Main-Class: MyApp 0(- on tht ",d
Press the return key after typing the Main-
Class line, or your manifest may not work
correctly. Put the manifest file into the "closses" manifesLtxt
directory.


manifesLtxt
Run the Jar tool to create a JAR file
that contains everything in the classes
directory plus the manifest.
I

%cd MiniProject/class8s
no SO\O.. tt.
'jar -cvmf .manifest.txt appl.jar *.class
toOt Cja~d)
OR
'jar -cvmf manifest.txt appl.jar MyApp.class
in the "JAR
CIflPl .Jar

you are here) 585


executable JAR

Most 100% local Java


arrs are deployed as
100% Local Combination 100% Remote executable JAR files.
RUt1t1it1g (executi.,g) the JAR
JaVli (thejVM) is capable of loading a class from aJAR, and calling
the main () method of that class. In fact, the entire application can
stay in the JAR Once the ball is rolling (i.e., the main () method
starts running), theJVM doesn't care where your classes come
from, as long as it can find them. And one of the places thejVM
looks is within any JAR tiles in the classpath . U it can seea JAR, the
JVM will look in th3tJAR when it needs to find and load a class.

r:
l
~(:':r-':"'-:_:~. ,.: l"'l

0
appl .jar
. ' . ~ -"

Depending on how your operating system is configured, you


might even be able to simply double-click theJAR file to launch
it. This works on most flavors of Windows, and Mac OS X. You
can usually make this happen by selecting the JAR and telling
the OS to "Open with ...~ (or whatever the equivalent is on your
operating system) .

- - - - - - - - - - Dffin~~estiQns
Q: Why can't I Just JAR up an entire directory? Q: What did you jU5t say?

A.: The JVM looks inside the JARand expects to find


what It needs right there. It won't go digging Into other
A: You can't put your class flies Into some arbitrary
directory and JARthem up that way . But If your classes
directories, unless the class Is part of a package, and even belong to packages, you can JARup the entire package
then the JVM looks only In the directories that match the directory structure. In fact, you must. We'll explain all this on
package statement7 the next page, so you can relax.

586 chapter 17
package, jars and deployment

Put your classes itt packages!


So you've written some nicely reusable class files, and you 've
posted them in your internal development library for other
prognmmers to use. While basking in the glow of having
just delivered some of the (in your humble opinion) best
examples of 00 ever conceived. you get a phone call. A
frantic one. Two of your classes have the same name as
the classes Fred just delivered to the library. And all hell is
breaking loose out there, as naming collisions and ambiguities
bring development to its knees.
And all because you didn't use packages! Well, you did use
packages, in the sense of using classes in the Java API that are,
of course, in packages. But you didn't put your own classes
into packages, and in the Real World, that's Really Bad. Package stnJcture of the J QVQ API for:
We're going to modify the organizational structure from the java.text NumberFormat
previous pages.just a little, to put classes into a package. and
to JAR the entire package. Pay very close attention to the java.ut i I.ArrayList
subtle and picky details. Even the tiniest deviation can stop
java.awt.fJowLayout
your code from compiling and/or running.
java.awt.event.ActionEvent
Packages prevettf class ttattte co"fllcts java.net.Socket
Although packages aren'tjust for preventing name collisions,
java
that's a key feature. You might write a class named Customer
and a class named Account and a class named ShoppingCan.
And what do you know, half of all developers working in text~et
enterprise e-comrnerce have probably written classes with
those names. In an 00 world, that's just dangerous. If part of NumberFormat
• /
uti!
a~
/'"
the point of 00 is to write reusable components, developers
need to be able to piece together components from a :~':It ~
I
eventSocket
'"

variety of sources, and build something new out of them. ~:'~:: \


Your components have to be able to 'play well with others', AnayUsl Flowlayout
including those you didn't write or even know about,
Remember way back in chapter 6 when we discussed how
a package name is like the full name ofa class, technically ActionEvent
known as the fully-qualified name. Class Arra yList is really
java.utiLArrayList, ]Button is really javax.swingJButton, and What does tkls picture look like to
Socket is really java. net. Socket. Notice that two of those classes, you? Doesn't It look Q whole lot like
ArrayList and Socket, both have java as their "first name". a directory hlercrc.hyi
In other words. the first pan of their fully-qualified names
is "java". Think of a hierarchy when you think of package
structures, and organize your classes accordingly.

you are here ~ 587


package narnlnq

pachges can prevent name


confhcts. but only if you
choose a raclage name
that's gtlaranteed to he
unicrue, The hest way to
Prevettfittg package ttalMe cottflicts do that is to preface your
Putting your class in a package reduces the chances of naming pachges with your reverse
conflicts with other classes, but what's to stop two programmers
from coming up with identical pa~kage names? In other words, domain name.
what's to stop two programmers, each with a class named Account,
from putting the class in a package named shopping.customers? com.headfirstbooks.Book
Both classes, in that case, would still have the same name: ~f' e
pallc.j~( J\o}",c \.. t..\6~ ,..6""
shopping.customers.Acwunt
Sun strongly suggests a package naming convention that greatly
reduces that risk-prepend every class with your reverse domain
name. Remember, domain names are guaranteed to be unique.
TWo different guxs can be named Bartholomew Simpson, but rwo
different domains cannot be named doh.com.

Reverse domain package names

588 chapter 1 7
package, jars and deployment

_put your class in a package:


You _~!i.t put a class
se a package name into a directory
're using com.headflrstjava as our
pie. The class name is PackageExercise, structure that matches
se t he fully-qualified name of the class is now:
.headfirstjavQ. PackageExercise. the package hierarchy.

Q package statement in your class


be the first statement in the source
file, above any import statements. There
we only one package statement per source
file, so all classes In Q SOlJrce tile must
- the same package. That includes inner
es, of course.

import javax.swing.*i

public class PackageExercise {


II life-altering code here

com
Set Up a matching directory structure
: - s not enough to say your class is in a package,
ler e ly putting a package statement in
code. Your class isn't truly in a package
-jl you put the class in a matching directory
ture. So , if the fully-qualified class name heacfflrstjava
. om.hea dfirst java.Pac kageE xerc ise, you
put the PackageExercise source code in a
tory named neadflrstjaVQ, which must be in
..'rectory named com.
: - . possible to compile without doing that, but lOUOl
lOUOl
LorI""
l'\l.N ......
U, \ _.'"
us-it's not worth the other problems IOIO\ C-o ~le
lOlOlD)
.-
~ ct'-t4 ,.
010 101
'II have. Keep your source code in a directory 11)\01111
6<:1 . a~dl
do'l 6-1 .tlp
\Ol~lal0
t ur e that matches the package structure, I~OI(1U1 .0 •

. you'll avoid 0 ton of painful headaches down PackageExerclse.class PackageExerclse.Java


- road.

Set up a matching directory structure for


both the source and classes trees.

you are here. 589


compile and run with packages

Cotttpilittg at'd ruttttinQ with packages


When your class is in a package, it's a little trickier to compile and
run. The main issue is that both the compiler and]VM have to be
capable of f nding your class and all of the other classes it uses.
For the classes in the core API, that's never a problem. Java always
knows where its own stuffis. But for your classes, the solution
of compiling from the same directory where the source files are
simply won't work (or at least not reliably). We guano tee, though,
that if you follow the structure we describe on this page, you'll be
successful. There are other ways to do it, but this is the one we've
found the most reliable and the easiest to stick to.

Compiling with the -d (directory) flag


sta '" tht ~yt.f diytt~'t! Do NO! ~dJ Oo...m
%cd MyProject/source ~ il\J tht. dirtt,1:.t*-y ...,h~t tht. jd~il tIlt IS,

%javac -d .. /01a8s8s
.>
urJs tAe loto.pHer it> t t.h
.to",piled lode (tlau ll:s) e
'~it> .the tI~ dirtt.ky,
~he rillhi patkd e
sfr~ Yes. it k_~
To compile all the java files in the com.headfirstjava
package, use:
%javac -d .. /classes cam/beadfirstjava/*.java

to...piles ev(;'ry / ' (


.file ' 1. · . SOlorte . \Ava>
'I' UlIS d,ret.U>ry .r:

Running your code com com

%cd MyProject/classes

%java cam.headfirstjava.PackaqeExeroise
headf1f$f/8 heacffl

IOIlOl.
10 no J'
0110
001 10
001 01

PackagaExercl8&.class PackageExe~S8~ava

590 chapter 17
package, jars and deployment

fhe . . dflag is eve" cooler tha" we said


Compiling with the -d £lag is wonderful because not only does it
let you send your compiled class files into a directory other than ~: Itried to cd Into the
the one where the source file is, but it also knows to pllt the class directory where my main class
into the correct directory structure for the package the class is in. was, but now the JVM says It can't
find my c1assl But It's rightTHERE
But it gets even better! In the current directoryl
Let's say that you have a nice
directory structure all set up for your
source code. But you haven't set A: Once your class is in a
package, you can't call it by its
up a matching directory structure
'short' name. You MUST specify,
for your classes directory. Not a at the command -line, the fully-
problem! Compiling with qualified name of the class whose
-d tells the compiler to not mainO method you want to run.
just put your classes into But since the fully-qualified name
correct directory tree, but to 'ld Includes the package structure,
the directories if they don't Java insists that the class be in a
matching directory structure. So if
at the command-line you say:
com %java com.foo.Book
the JVM will look in its current
di rectory (and the rest of Its
classpath), for a directory named
"corn: It will not look for a class
named Boole. until It has found
a directory nomed "com" with a
directory Inside named ufoo': On Iy
then will the JVM accept that its
found the correct Book class. If it
finds a Book class anywhere else,
it assumes the class isn't in the
PackageExercrse.java
right structure, even if it isl The
JVM won't for example, look back
up the directory tree to saY,"Oh,1
can see that above us is a directory
The -d flag tells the complier, named com, so this must be the
right package..."
"Put the class into Its package
directory structure, using the
class specKled after the -d as
the root directory. But... If the
directories aren't there, create
them first and then put the class
In the right place!"

you ar e here ~ 591


JARs and packages

Makit1g at1 executable JAR with packages


When your class is in a package, the package directory structure
must be inside theJAR! You can't just pop your classes in the
JAR the waywe did pre-packages. And you must be sure that you
don't include any other directories above your package. The
first directory of your package (usually com) must be the first
directory within the JAR! If you were to accidentally include the
directory above the package (e.g. the "classes" directory), theJAR
wouldn't work correctly.

Making an executable ,JAR

• Make sure all of your class files are


within the correct package structure,
under the classes directory.
toll 0'
10UII '

IhelldtIn:tfM• . ... ·· ~ll:


",0\

• Create a manifest. txt file that states


which class has the mainO method,
and be sure to use the fully-qualified
class namel
Make 0 text file named manifest.txt that has a
·,umanl1ast.lxt
single line:
Main-Class: com.headfirstjava.PackaqaExercise

Put the manifest tile into the classes directory

• Run the Jar tool to create aJAR file


that contains the package directories
plus the manifest
The only thing you need to include is the 'com'
directory, and the entire package (and all classes) t.~ is ~t, I

will go into the JAR. AI\ '1~ ~"~...oAI1 ~d "Iou II


_I
t.0fP' o,y tot V'" I '. t.
. 1
'Sed MyProject/claasea .t ~et. tvt,......f\:),i\l,~ '" I. pcdcEx.jor . . . . . . . .

592
%jar -cvm£

chapter 17
manifest.txt packEx.jar
-
com PaclalgeExerclM.dua
package, jars and deployment

So where did the tMat1ifest file go?


Why don't we look inside theJAR and find out? From the
command-line, the jar tool can do more thanjust create and run a
JAR You can extract the contents of aJAR (just like 'unzipping' or
'unrarring') .
Imagine you've put the packExjar into a directory named Skyler;

jar commands for listing and extracting

G) List the contents of aJAR


% jar

'.

McrA./NF I
-' com ~

_I
headflrstjavl

MANIFEST.MF
IO\ Ul
LO lib '
~ \I t:l
00\ 1~
00 \ 01
@ Extract the contents of Q JAR (l.e. unJar)
% cd Skyler PackageExerclse.c1ass
% jar -xf packEx.jar
META-INF stands for 'meta
information'. The jar tool creates
the META-INF directory as
well as the MANIFEST.MF file.
Tt also takes the contents of
your manifest file, and puts it
into the MANIFEST.MF file . So,
your manifest file doesn't go into
MANIFEST.MF the JAR, but the contents of it
are put into the 'real' manifest
(MANIFEST.MF).

yo u are her e ~ 593


organizing your classes

Given the package/directory structure In this


picture,figure out what you should type at the
command-line to compile, ru n, create a JAR, and
execute a JAR. Assume we're using the standard
where the package dIrectory structure starts just
below source and classes .In other words, the source
and classes directories are not part of the package.

manlfesttxt
Compile:
%cd source
%javac _
COWl COWl

Run:
1CIUO
lO UO'J '
%cd _
• U •

..,
_lO
.. %java _
Foot.class Foof.java

C~Qte Q JAR
%cd _

,-----------------
Execute aJAR
'cd _

%_---------------
Bonus question: What's wrong with the package name?

594 chap ter 17


package, jars and deployment

Q.: What happens If you try • Organize your project so that your source code and class files are not in
to run an uec:utable JAR. and the same directory.
the end-user doesn't have Java
Installed? • Astandard organization structure is to create a project directory, and then
put a source directory and a classes directory inside the project directory.

A: Nothing will run, since


without a JVM,Java code can't
• Organizing your classes into packages prevents naming collisions with
other classes. if you prepend your reverse domain name on to the front of
run. The end-user must have Java
a class name.
Installed. • To put a class inapackage, put apackage statement atthe top ofthe
source code file, before any import statements:
Q: How can I g@t Java pac:kage com. wi cJcedlysmart;
installed on the end-user's • To be inapackage, a class must be in a directory structure thet exactly
machine? matches the package structure. For a class, com.wlckedlysmarlFoo.
Ideally, you can create a custom the Foo class must be in a directory named wickedlysmart. which Is in a
Installer and distribute It along directory named com.
with your application. Several
companies offer Installer pro- • To make your compiled dass land inthe correct package directory
grams ranging from simple to structure under the classes directory, use the -d compiler flag:
ext remely powerlu I. An In staIler % cd source
program could, for example, de- % javac-d .. / claues aom/wicJcedlysmart/l1'oo. java
tect whether or not the end-user
has an approproprlate version • To run your code, cd to the classes directory, and give the fully-quallfied
of Java Installed, and If not, name ofyour class:
Install and conflgure Java before .. cd classes
Installing your application. % java com.wickedlyamart.l1'oo
Instalishleld,lnstaIlAnywhere,
and DeployDlrector all offer Java • You can bundle your classes into JAR (Java ARchive) flies. JAR isbased
Installer solutions. on the pkzip fonnal.
Another cool thing about some • You can make an executable JAR file byputting amanifest Into the JAR
of the Installer programs Is that that states which class has the malnO method. To create amanifest file,
you can even make a deploy-
make a text file with an entry like the following (for example):
ment CD-ROM that Includes
Main-Class: com.wicJcedlysmart.FOO
installers for all major Java
platforms, so...one CD to rule • Be sure you hitthe return key atter typing the Main-elass line, oryour
them all. If the user's running on manifest file may not work.
Solarls, for example, the Solarls
verslo n of Java is insta lied. On • To create a JAR file. type:
Windows, the Windows, ver- jar -cvfm manifest. txt MyJar. jar com
slon, etc. If you have the bud get,
this is by far the easiest way for • The entire package directory structure (and only the directories matching
your end-users to get the right the package) must be Immediately Inside the JAR file.
version of Java Installed and
• To run an executable JAR file, type:
conflgured.
java -jar MyJar . jar

you are here. 595


wouldn't it be dreamy...

596 chapler 17
package, jars and deployment

Executable
Jar

100% Local
---
Web Start

100% Remote
End-users launch aJava
Web Start app by clicling
Java Web Start
on a lin1 in a Web
With Java Web Start (JWS), your application is launched for the
first time from a Web browser (get it? Web Starf) but it runs as a page. But once the apr
stand-alone application (well, almost), without the constraints of the
browser. And once it's downloaded to the end-user's machine (which downloads. it runs outside
happens the first time the user accesses the browser link that starts
the download), it stays there.
the browser, just like any
Java Web Start is, among other things, a small Java program that lives other stand-alone Java
on the client machine and works much like a browser plug-in (the
way, say, Adobe Acrobat Reader opens when your browser gets a .pdf
application. In fact, a
file) . ThisJava program is called the Java Web Start 'helper app',
and its key purpose is to manage the downloading, updating, and
Java Web Start app is just
launching (executing) of yOUTJWS apps, an executable JAR that's
WhenJWS downloads your application (an executableJAR), it
invokes the main 0 method for your app. After that, the end-user can
distributed over the Web.
launch your application directory from the JWS helper app without
having to go back through the Web page link.
But that's not the best part. The amazing thing aboutJWS is its
ability to detect when even a small part of application (say, a single
class file) has changed on the server, and-without any end-user
intervention-download and integrate the updated code.
There's still an issue , of course, like how does the end-user getJava
and java Web Start? They need both-Java to run the app, andJava
Web Stan (a small Java application itself) to handle retrieving and
launching the app. But even tluu has been solved. You can set things
up so that if your end-users don't haveJWS. they can download
it from Sun . And if they do have JWS, but their version ofJava is
out-of-date (because you've specified in yourJWS app that you
need a specific version ofJava), the Java 2 Standard Edition can be
downloaded to the end-user machine.
Best of all, it's simple to use. You can serve up aJWS app much like
any other type of Web resource such as a plain old HTML page or a
JPEG image. You set up a Web (HTML) page with a link to your JWS
application, and you're in business.
In the end, yourJWS application isn't much more than an
executable JAR that end-users can download from the Web.
you are he re ~ 597
Java Web Start

How .Java Web Start works


Web br-o'NSt"r
G) The client clicks on a Web page link
to your JWS application (0 .jnlp file). -give me MyApp.jnlp"

The Web page link


<a href="MyApp. jnlp">Clic:k</a>

® The Web server (HTTP) gets the


. request and sends back a .Jnlp file
(this Is NOT the JAR) .
The .jnlp file is an XML document that
states the name of the application's
executable JAR file,

Java Web Start (a small 'helper app'


on the client) is started up by the -give me MyApp.jar"
browser. The JWS helper app reads
the .jnlp file, and asks the server for
the MyApp.jar file.

@ The Web server 'serves ' up the


requested .jar file.

Java Web Start gets the JAR and


starts the oppUcation by calling the
specified malnO method (just like an
executable JAR).
Next time the user wants to run this opp. he can --
open the Java Web Start application and from
there launch your app. without even being online.

598 c hap te r 17
package, jars and deployment

The .j"lp file


To make aJava Web Start app, you need to Jnlp (Java Network
Launch Protocol) file that describes your application. This is the
file the JWS app reads and uses to find yourJAR and launch th e
app (by calling theJAR's main 0 method) , A jnlp file is a simple ,
XML document that has several different things you can put in, . ~ -t~e 'yoat:
but as a minimum, it should look like this: ~ ye ~o~ s~et.l l~e seY"e~·
~ L~~ 'IS O'f\
, G10ase
, -tal"'s 'II
:\:,a.n- s'\- :t so 'lie'ye v51'f\~10
<?:xml version="l.O" encoding="ut£-B"?> \~e (.0 e y'fle S \ot.a\~OS I \" yOV' 'lie
J 'II~eye 'f~\Ii -tnls O'f\ o'J'y ytsS
"\1,1.0.0. . -tn\S 'fIO~\G
,.f ' e -\:.tS-\:."'V'~L .1, ado L L sey"eY ,
v' eY ~ \oo~va"," ev 'fIev "
<J'nlp spec="0.2 1.0"
codebase=''http://l27.0.0.1/~kathy''
r -t~e \oc.a S oy\ o'J'Y ·l~~:;o.\~s...a..t-(.o'"
s-tayt,a~~ /1,.rIl'fl,'fIIi.
sO'l'
"~-t-\:.r
t· ~th
. . L \ tio'f\ ot the jtllf ~ile rt:la'ove e
hre£="MyApp. jnlp"> ~ ThiS IS "he ~a I showS that MyAyyjnly is
todebase.. T~,'s e14d':Yd~ ttor'f ot the web seYller, not
allailable Itl "he YOO" lye
tlested itl so",e othey diYet~'f-

<information>
<title>kathy App</title>
<vendor>Wickedly Smart</vendor>
<homepaqe hre£="index.html"/>
<description>Head First WebS tart demo</description>
<icon hre£="kathys.qi£"/>
.
<o£fline-allowed/>>/
~
. This ",eanS the lOSer tan Yl/in 'f0l/il'" r
.
n1
ya", withollt
ted ~ the internet. -t he lOSer I~
. ottl' e
\n ,
</in£ormation> ~t:~::;~~e a\Atomatit-l/ifdahn~ teahye wont work.

<resources> This says that YOI/il'" al'l' needs lIel'"sion 1.3


<j2se version="l. 3+" /> ~ ot Jalla, oY ~reate\".
<jar hre£="MyApp . jar" /> ~ n
< / resources>
e tlatl'le 0+
oiher JAo ,.
t:
eXef·l<tah/ JAo/ y;
" 1"; es as w /I 1.L 1.e " . 010 tI'Iip'hi h
ever. SOlltld d . e • <;nat: hold .I. ave
s an ItI'Ia~es llSed b Outer (. asses 0\'"
YYOll\" apr.
<application-desc main-class="HelloWebStart"/>
</jnlp> ~ This is like the tI'Iainfest Main-Class ent\"'1'" it says
whith zlass in the JAR has the llIairD llIethod.

you are here . 599


deploying with JWS

Steps for making and deploying


a Java Web Start app
Make an executable JAR
for your application. 0
MyApp.Jar

~ Write a .Jnlp file .

MyApp.jnlp

® Place your JAR and .jnlp


files on your Web server.

@) Add a new mime type to your Web server.


application/x-java-jnlp-nle

This causes the server to send the .jnlp file with the
correct header, so that when the browser receives
the Jnlp file it knows what it is and knows to start
the JWS helper app.

..........
~
I~

Create Q Web page with a link


to your .jnlp file ~--:

<HTML> MyJWSApp.hbnl
<BODY>
<8 href= '~App2.jnlpH>Launch My Application</a>
<I BODY>
</HTML>

600 chapler 17
package, jars and deployment,

,.
LOOk at the sequence of events below, and 2.
p Iacethem in the order In which they
occur In a JWS application.
3.

__-~--:::;':::-;;;-v !heWeb server sends a JAR 4.


\he Web browser starts up lileto!he JWS helper app
theJWS helper app
5,
the Web server sends the JWS helper app invokes
tiJe to the browser the JAR's malnO method
6.
user dicks a Web page Itn er requests a .jnlpfile
from the Web server
7.

dlim~estJons , - - BULlO POINTS -


Q.: How IsJava Web Start dl~rent from an applet1 • Java Web Start technology lets you deploy a
stand-alone client application from the Web.

A: Applets can't live outside of a Web browser. An applet is


downloaded from the Web as part of a Web page rather than
• Java Web Start includes a 'helper app' that must
be installed on the client (along with Java).
simply from a Web page. In other words, to the browser, the applet
IsJust like a JPEG or any other resource. The browser uses either a
• AJava Web Start (JWS) app has two pieces:
Java plug-In or the browser's own built-In Java (far less common an executable JAR and a .jnlp file.
today) to run the applet. Applets don't have the same level of
functionality for things such as automatic updating, and they must
• A .jnlp file is a simple XML document that
describes your JWS application. It includes
always be launched from the browser. With JWS applications, once
they're downloaded from the Web, the user doesn't even have to tags for specifying the name and location ofthe
be usIng a browser to relaunch the application locally. Instead, JAR, and the name ofthe class with the mainO
the user can start up the JWS helper app, and use It to launch the method.
already-downloaded application again.
• When a browser gets a .jnlp file from the server
(because the user clicked on a link tothe .jnlp
Q..: What are the security restrictions of JWS1 file), the browser starts upthe JWS helper app.

• The JWS helper app reads the .jnlp file and


A: JWS apps have several limitations Including being
restricted from reading and writing to the user's hard drive. But...
requests the executable JAR from the Web
server.
JWS has Its own API with a special open and save dialog box so
that, with the user's permission, your app can save and read Its • When the JWS gets the JAR, it invokes the
own flies In a speclaI, restricted area of th e user's drive. mainO method (specified in the .jnlp file).

you a re he re ~ 601
exercise: True or False

We explored packaging, deployment, and JWS


in this chapter. Your job is to decide whether
each of the following statements is true or false.

1. The Java compiler has a flag, -d, that lets you decide where your .class files should go .

2. AJAR is a standard directory where your .class files should reside.

3. When creating a Java Archive you must create a file called jar.mf.

4. The supporting file in a Java Archive declares which class has the main() method.

5. JAR files must be unzipped before the jVM can use the classes inside.

6. At the command line, Java Archives are invoked using the -arch flag.

7. Package structures are meaningfully represented using hierarchies.

8. Using your company's domain name is not recommended when naming packages.

9. Different classes within a source file can belong to different packages.

10. When compiling classes in a package, the -p flag is highly recommended.

11. When compiling classes in a package, the full name must mirror the directory tree.

12. Judicious use of the -d flag can help to assure that there are no typos in your class tree.

13. Extracting aJAR with packages will create a directory called meta-info

14. Extracting aJAR with packages will create a file called manifest.mf.

15. TheJWS helper app always runs in conjunction with a browser.

16. JWS applications require a .nlp (Network Launch Protocol) file to work properly.

17. AJWS's main method is specified in itsJAR file.

602 chapter 17
package, jars and deployment

~U1Il1Ilar)'-Or~ss 7-.0

Anything in the book


Isfair game for this
onel

Aaoss Down
6. Won'ttravel 26. Mine is unique 1. Pushy widgets 16.Who's allowed 30. 110 cleanup
9. Don't split me 27. GUl's target 2. __ of my desire 19. Efficiency expert 31. MUll-nap
10. Release-able 29. Java team 3. 'Abandoned'moniker 20. Early exit 34. Trig method
11. Got the key 30. Factory 4. A chunk 21. Commonwrapper 36. Encaps method
12. VOgang 32. Fora while 5. Math not trlg 23. Yes or no 38. JNLP format
15. Flatten 33. Atomic It 8 6. Be brave 24. Java jackets 39.VB's final
17. Encapsulated returner 35. Good asnew 7. Arrangewell 26. Not behavior 40. Java branch
18. Shipthis one 37. Pairsevent 8. Swing slang 28. Socket's suite
21 . MakeIt so 41. Wheredo I start 11. I/O canals
22. I/O sieve 42 A little firewall 13.Organized release
25. Diskleaf 14. Not for an instance

you are here ~ 603


exercise solutions

,.
2.

3. the Web server sends a.jnlp


file 10 the browser

4. the Web browser starts up


the JWS helper app

\ \he NJS helper app requests


5. '\ lheJARfl\e

6. I the Web server sends a JAR


Lli/e 10 the JWS helper app
I
7.
I
the JWS helper app Invokes
the JAR's mal nO method
I
True 1. The Java compiler has a flag, -d, that lets you decide where your .class files should go.
False 2. AJAR is a standard directory where your .class files shouJd reside.
False 3. When creating a Java Archive you must create a file called jar.mf,
True 4. The supporting file in aJava Archive declares which class has the mainO method.
False 5. JAR files must be unzipped before thejVM can use the classes inside.
False 6. At the command line, Java Archives are invoked using the -arch flag.
True 7. Package structures are meaningfully represented using hierarchies.
False 8. Using your company's domain name is not recommended when naming packages.
False 9. Different classes within a source file can belong to different packages.
False 10. When compiling classes in a package, the -p flag is highly recommended.
True II. When compiling classes in a package. the full name must mirror the directory tree.
True 12. Judicious use of the -d flag can help to assure that there are no typos in your tree.
True 13. Extracting aJAR with packages will create a directory called meta-inf,
True 14. Extracting aJAR with packages will create a file called manifestmf.
False 15. TheJWS helper app always runs in conjunction with a browser.
False 16. ]WS applications require a .nlp (Network Launch Protocol) file to work properly.
False 17. A]WS 's main method is specified in itsJAR file.

604 chap t er 1 7
~UtIltIlary-Or~55 t. O

you are here ~ 605


18 remote deployment w it h RMI

Distributed
Computing

Being remote doesn't have to be a bad thing. Sure, things areeasieT when

all the parts of your application are in one place, in one heap, with one JVM to rule them all. But

that's not always possible. Or desirable. What If your application handles powerful computations,

but the end-users are on a wimpy little Java-enabled device? What if your app needs data

from a database, but for security reasons, only code on your server can access the database?

ImagIne a big e-commerce back-end, that has to run within a transaction-management system?

Sometimes, part of your app must run on a server, while another part (usually a client) must

run on a different machine. In this chapter, we'll learn to use Java'samazingly sImple Remote

Method Invocation (RMI) technology. We'll also take a quick peek at Servlets, Enterprise Java

Beans (EJB) ,and JInl, and look at the ways In wh Ich EJB and J Inl depend on RMI. We'll end the

book by writi ng one of the coolest thi ng s you can make In Java,a universal servicebrowser.

th is is a new ch apter 807


how many heaps?

.. RMlapp

100% Local Combination

Method calls are always betweeK


two objects OK the sattte heap.
So far in this book, every method we've invoked has been on
an object running in the same virtual machine as the caller.
In other words, the calling object and the callee (the object
we're invoking the method on) live on the same heap.

class Foo {
void go ()
Bar b = new Bar();
b.doStuff() j

public static void main (String [] args) (


Faa f = new Foa()j In most applications, when one object
f .go () ;
calls a method on another, both objects
are on the same heap. In other words,
both are running within the same JVM.

In the code above, we know that the Foo instance


referenced byfand the Bar object referenced by bare
both on the same heap, run by the sameJVM. Remember,
the jVM is responsible for stuffing bits into the reference
variable that represent how to get to an object on the heap.
TheJVM always knows where each object is, and how La
get to it. But the JVM Can know about references on only
its own heap! You can 't, for example, have aJVM running
on one machine knowing about the heap space ofaJVM
running on a different machine. In fact, aJVM running on
one machine can't know anything about a differentjVM
running on the same machine. It makes no difference if
theJVMs are on the same or different physical machines;
it matters only that the twoJVMs are, well, two different
invocations of the JVM.

608 cha pte r 18


remote deployment with RMI

What ifyou wattt to ittvoke 8 'Method Ott


att object rutttthtg Ott another tH8chitte?
We know how to get information from one machine to another-
with Sockets and I/O. We open a Socket connection to another
machine, and get an Ourputfitream and write some data to it.
But what if we actually want to call a method on something running
in another machine... another JVM? Of course we could always build
our own protocol, and when you send data to a ServerSocket the
server could parse it, figure out what you meant, do the work, and
send back the result on another stream. What a paia, though. Think
how much nicer it would be to just get a reference to the object on ~ ~t.1 lovtS
the other machine, and call a method. yO-.lC"hl, ~I.. ... ~n 'b\C)
t.o t....I»'t.n "V'
~ t.O\t.~abo'f\S~. .....
Imagine two computers...
~
I
__'--'- ~
JVM

r ---'
CJ~r.=a~~~..::::15
L-' '--- I CJ l-J C-.l L-J L..J L--o;
'I - -" l . . \l · U

Little Big
Big has something Little wants.
C~ute-l0~er.
Little wants to send some data to Big, so that Big can do the
heavy ~ruting.
Little wants simply to call a method...
double doCalcUsingDatahase(CalcNumbers numbers)

and get Lack the result.


But how can Little get a relerence to an object on Big?
you are here' 609
two objects, two heaps

Object AI rut,.1i.,g 0., Little, wa.,ts to call


a tttethod 0., Object ~ ru.,.,it1g Ot1 Jig.
The question is, how do we get an object on one machine
(which means a different heap/]VM) to call a method on
another machine?

doCalcUsi ngDatabase.O
~~~

return value

~
- - ~ e-. .,,~-
.- ...... '- .
-.11 _'--
, -,

Jut you can't do that.


Well, not directly anyway. You can't get a reference to
something on another heap. If you say:
Dog d = ???
Whatever d is referencing must be in the same heap space as
the code running the statement,
But imagine you want to design something that will use
Sockets and I/O to communicate your intention (a method
invocation on an object running on another machine), yet
still feel as though you were making a local method call.
In other words. you want to cause a method invocation on a
remote object (i.e., an object in a heap somewhere else) J but
with code that lets you pretend that you're invoking a method
on a local object. The ease ofa plain old everyday method
call, but the power of remote method invocation. That's our
goal.
That's what RM1 (Remote Method Invocation) gives you!
But let 's step back and imagine how you would design R.i\1I if
you were doing it yourself. Understanding what you'd have to
build yourself will help you learn how RMl works .

610 chapter 18
remote deployment with RMI

A design for remote method calls


Create four things: server, client,
server helper, client helper

• Create client and server apps. The server app is the


remote service that has an object with the method
that the client wants to invoke.

Client heap

Create client and server 'helpers'. They'll handle 011


the low-level networking and I/O details so your client
ond service can pretend like they're in the same heap.

Server heap

you are he re> 611


client and server helpers

fhe role of the 'helpers"


The 'helpers' are the objects that actually do the communicating.
They make it possible for the client to ad as though its calling a
method on a local object. In fact, it is. The client calls a method on
the client helper, as if the clienthelper were the actual service. The client
Your client object gets to
helper is a frrorj for the Real Thing. act llke it's making remote
In other words, the client object thinks it's calling a method on
the remote service, because the client helper is pretendingto be
method calls. But what
th e service obj eel. Pretendingto be the thingwith the met/wd the client it's r!!llY doing is calling
wants 10 call!
But the client helper isn't really the remote service. Although the
methods on a heap-local
client helper ruts like it (because it has the same method that the
service is advertising), the client helper doesn't have any of the
'proxY object that handles
actual method logic the client is expecting. Instead, the client all the low-level details of
helper contacts the server, transfers information about the method
call (e.g., name of the method, arguments, etc .) , and waits for a Sockets and streams.
return from the server.
On the server side, the service helper receives the request from
the client helper (through a Socket connection), unpacks the
information about the call, and then invokes the real method on
the real service object. So to the service object, the call is local. It's
coming from the service helper, not a remote client.
The service helper gets the return value from the service. packs it
up, and ships it back (over a Socket's output stream) to the client
helper. The client helper unpacks the information and returns the
value to the client object.

Server heap

612 chapte r 18
remote deployment with RMI

How the method call happens


• Client object calls doBigThingO on the client helper object

Se~r heap

• Client helper packages up information about the call


(arguments, method name, etc.) and ships it over the
network to the service helper .

Client heap I
"client wonts to call a method"
Server heap

• Service helper unpacks the information from the client helper,


finds out which method to call (and on which object) and

- -
invokes the real method on the real service ob] ect.

I
Client heap "client wants to coli a method"

you are here ~ 613


RMI helper objects

Java RMI gives you the cliet1t at1d


service helper objects!
In Java, RMJ builds the client and service helper They throw exceptions allover the place.
objects for you, and it even knows how to make the
So, the client does have to acknowledge the risk. The
client helper look like th e Real Service. In other
client has to acknowledge that when it calls a remote
words. RMI knows how to give the client helper
method. even though to the client it's just a local call
object the same methods you want to call on the
to the proxy/helper object, the call ultimaJely involves
remote service.
Sockets and streams. The client's original call is local,
Plus, RMI provides all the runtime infrastructure to but the pro"]' turns it into a remote call. A remote call
make it work, including a lookup service so that the JUSt means a method that's invoked on an object on
client can find and get the client helper (the proxy another JVM. HQ11J the information about that call
for the Real Service). gets transferred from oneJVM to another depends
With RMI. you don 't write any of the networking on the protocol used by the helper objects.
or I/O code yourself. The client gets to call remote With RMI. you have a choice of protocols: JRMP or
methods (i.e. the ones the Real Service has) just IIOP,JRMP is RMJ's 'native' protocol, the one made
like normal method calls on objects running in the just for Java-ta-Java remote calls . nop, on the other
client's own 10ca1JVM. hand. is the protocol for CORBA (Common Object
Request Broker Architecture), and lets you make
Almost.
remote calls on things which aren't necessarily Java
There is one difference between RMI calls and local objects. CORBA is usually much more painful than
(normal) method calls. Remember that even though RMI, because if you don't have Java on both ends,
to the client it looks like the method call is local, there's an awful lot of translation and conversion that
the client helper sends the method call across the has to happen.
network. So there is networking and I/O . And what
But thankfully, all we care about isJava-to-Java, so
do we know about networking and I/O methods?
we're sticking with plain old. remarkably easy RMl.
They're risky!

In RMI, the client helper is a 'stub'


and the server helper is a 'skeleton'.

Client heap Server heap


..

614 chapter 18
remote deployment with RMI

Making the Remote Service


This is an overview of the five steps for making the remote
service (that runs on the server). Don't worry, each step is
Server D!!
explained in detail over the next few pages.

Step one:
Make a Remote Interface
The remote interface defines the methods
that a client can call remotely. It's what
the client will use as the polymorphic class
type for your service. Both the Stub and
actual service will implement this!

Step two:
Make a Remote Implementation
This is the class that does the Real Work.
It has the real implementation of the
remote methods defined in the remote
interface. It's the object that the client
~~~~~~.

Step three:
Generate the stubs and skeletons using rmic
These are the client and server 'helpers' .
You don't have to create these classes or ever
look at the source code that generates them. MyRemotelmpl_Stub.class
It's all handled automatically when you
101101 -
run the rmic tool that ships with yourJava Jtl 1...10'
ebOt."II
development kit, HI
001 Ol

MyRemotelmpLSkel.class
Step four:
Start the RMI registry (rmiregistry)
The nniregistry is Ji ke the white pages of a
phone book. It 's where the user goes to gel
the proxy (the client stubv'helper object).

Step five:
Start the remote service
You have to get the service object up and running.
Your service implementation class instantiates an
instance of the service and registers it with the RMI
registry. Registering it makes the service available for
clients.
you are he re . 615
a remote interface

Step one: Make a Remote Interface

MyRemote.java
Extend java.rmLRemote
Remote is a 'mar ker ' interface, which means it has no methods. It has
special meaning for RMI, though, so you must follow this rule. Notice
that we say 'extends' here. One interface is allowed to extend another
interface.

public interface MyRemote

Declare that all methods throw a RemoteException


The remote interface is the one the client uses as the polymorphic type
for the service. In other words, the client invokes methods on something
that implements the remote interface. That something is the stub, of
course, and since the stub is doing networking and I/O, all kinds of Bad
Things can happen. The client has to acknowledge the risks by handling
or declaring the remote exceptions. If the methods in an interface
declare exceptions, any code calling methods on a reference of that type
(the interface type) must handle or declare the exceptions.
t , ~ . . ' av,H'",i
import java. rmi . * ; ~ th~ R~",oh '"n;c;Y ate'S ,,, J '

public interface MyRemote extends Remote {


public String sayHello() throws
}

Be sure arguments and return values are primitives or Serializable


Arguments and return values of a remote method must be either primitive
or Serializable, Think about it. Any argument to a remote method has to
be packaged up and shipped across the network, and that's done through
Serialization. Same thing with return values. If you use primitives, Strings,
and the majority of types in the API (including arrays and collections),
you'll be fine. If you are passing around your own types ,just be sure that
you make your classes implement Serializable.

public sayHello() throws RemoteException;

" ' - This r-et;...rn vc1/~e ~onna


is be shirred
over ~he wire +\'"0'" the serve\" batk to
the ~"ent, so it lrIl.tSt be Se\"ializable.
That s how ar~s and \"et~rn valf.tt:s ad:;
ratka~ed ~r and Sent , J
remote deployment with RMI

Step two: Make a Remote Implementation


-- 1
~ ....... ";i _

- 0

• Implement the Remote interface MyRemotelmpl.java


Your service has to implement the remote interface-the one
with the methods your client is going to call.
public class MyRemoteImpl extends UnicastRemoteObject {
public String sayHello() { ~
return "Server says, 'Hey'''; Th~ t~n-riler will n-ake SlAre that
} rIA lie In-r1en-el'lteo all the n-ethods
/ / more code in class t~.om the intel-fate '/OIA ir..r1er..el'lt. Il'I
} IS tase, there s ol'lly Ohe.

• Extend UnicastRemoteObject
In order to work as a remote service object, your object needs some
functionality related to 'being remote'. The simplest way is to extend
UnicastRemoteObject (from the java.rmi.server package) and let that
class (your superclass) do the work for you.
public class MyRemoteImpl implements MyRemote {

• Write a no-arg constructor that declares a RemoteException


Your new superclass, UnicastRemoteObject, has one little problem-its
constructor throws a RemoteException. The only way to deal with this is
to declare a constructor for your remote implementation,just so that you
have a place to declare the RemoteException. Remember, when a class is
instantiated, its superclass constructor is always called. If your superclass
constructor throws an exception, you have no choice but to declare that L thO 'l'l
y'our constructor also throws an exception. ,/o\A dOl'l't halle to yv-".al'l~ I:i ~
- 1 t toY- YoIA JV-S" l'Ie..~
P ubl i c U.rRemoteImpl ( ) the t.01'lS rv.t., ~hat "OIAr slAfert.lass
6"6:t wa" to det. are " I L,
t.~trv.t.tor throws al'l euefvOTI.

• Register the service with the RMI registry


Now that you've got a remote service, you have to make it available to
remote clients. You do this by instantiating it and putting it into the RMI
registry (which must be running or this line of code fails). When you
register the implementation object, the RMI system actually puts the stub in
the registry, since that's what the client really needs. Register your service
using the static rebind() method ofthejava.rmi.Naming class. . M",e (that t.I\el'ts tal' ~t
try ( q\ve ~o\Ar serv.lt.et~ ~\str~) al'd re~\ster It
Remote service = new RemoteI 1 () ; ~ \otnit.R~IIl'Ire~\:t:;. W'hel'l ~o\A b.\"dthe the
wltn e . t. RMI sways t.he serv,u o'r
~ .,- servit.e obJe~_, Lhe stlAb \l' the re~istr~·
'---'" stlAb al'd flA';> "
you are here. 617
Step three: generate stubs and skeletons

G) Run rmic on the remote implementation class


(not the remote: Interface)
The rrnic tool, that comes with the java software
development kit, takes a service implementation and
creates two new classes. the stub and the skeleton.
It uses a naming convention that is the name of
your remote implementation, with either _Stub or
MyRemotelmpl_Stub.class
_Skeleton added to the end . There are other options
with rmic, including not generating skeletons, lClnO).
10 liO I
o U 6
seeing what the source code for these classes looked 001 \ 0
OO~ 0)

like, and even using llOP as the protocol. The way


we're doing it here is the way you'll usually do it. MyRemotelmpCSkel.class
The classes will land in the current directory (i.e.
whatever you did a cd to). Remember, rmic must
be able to see your implementation class, so you'll
probably run rmic from the directory where your
remote implementation is. (We're deliberately not
using packages here, to make it simpler. In the Real
World, you'll need to account for package directory
structures and fully-qualified names).

Step four: run rmiregistry

(1) Bring up a terminal and start the rmlre:gistry.


Be sure you start it from a directory that has access
to your classes. The simplest way is to start it from
your 'classes' directory.

Step five: start the service

CD Bring up another terminal and start your service


This might be from a main 0 method in your remote
implementation class. or from a separate launcher class.
In this simple example. we put the starter code in the
implementation class, in a main method that instantiates
the object and registers it with RMl registry.

618 chapter 18
remote deployment with RMI

Complete code for the server side

The Remote interface:

The Remote service (the implementation):

public MyReIDoteImpl () throws RemoteException { I


<c>
public static void main (String[] args) (

try (
MyRemote service =new MyR8moteImpl();~
Naming.rebind("Remote Hella H I service);
catch (Exception ex) { ~ M.ike the rt....oU ob· t
'r"'irt4ish-y'd· 1., :Je~"1.~e" b"'d
I , I

ex.printStacltTrace () ; itb to -the


J\d"'t
J _I"~ Ult S'td{;H':. N·
e9;su ..- it:. lA"d .
yOIA l- t.
'''?,..... e i"dO. The
"ted to look it. "d · 1., t"r r~ he 1I<1"'e tliel'lts '011/1
--r tr. Ule r"" re9'shy

you ar e here ~ 619


getting the stub

How does the client getthe stub~?


The client has co get the stub object, since that's the thing the
client will call methods on. And that's where the RMI registry
comes in. The client does a 'lookup', like going to the white pages
ofa phone book, and essentially says, "Here's a name, and I'd like
the stub that goes with that name."
loolcllpO is a statit l\'ltihod o-t
the Na",i~ tlass

~Remote)
\t
Naming.lookup("rmi://127.0.0 .1/Remote Bello");
l' ~
\ '1011 hil'lt to t..ut it. to tht 'f0\l.'" host. l\il",e 0'" /P
i"u...tate, siYlle t.he loolc'-r addytsS ~oes heye
...ethod ret.'-Yl'I$ t'ffe Objett..

Server

• Client does Q lookup on the RMI registry


Naminq.lookup("rm1://127.0.0.1/Ramot:8 Bello");

• RMI registry returns the stub object


(as the return value of the lookup method) and RMI
deserializes the stub automatically, You MUST have
the stub class (that rmic generated for you) on the
client or the stub won 't be deserialized,

• Client Invokes Q method on the stub, as


though the stub IS the real service
620 chapter 18
remote deployment wit h RMI

How does the client get the stub class?


Now we get to the interesting question. Somehow, someway, the
client must have the stub class (that you gene rated earlier using
rmic) at the time the client does the lookup, or else the stub won 't
be deserialized on the client and the whole thing blows up. In a
simple system, you can simply h and-deliver th e stub class to the
client.
There's a much cooler way, though, although it's beyond the
scop e of this book. But just in case you're interested, the cooler
way is called "dynamic class downloading". With dynamic class
downloading, a stub obj ect (or really any Serialized object) is
'stamped' with a URL that tells the RMI system on the client
where to find the class file for that object. Then, in th e process of
deserializing an object, ifRMI can't find the class locally, it uses
that URL to do an HTTP Get to retrieve the class file. So you 'd
need a simple Web server to serve up class files, and you'd also
need to change some security parameters on the client. There are
a few other tricky issues with dynamic class downloading, but that's
the overview.

Complete client code

~ The Na... ih9 dass (.f .


import
. . *.
Java.rnu.. ,
I
< re...ire3ist r look
Y
J'ava ·r ...,. patkage
c: ~01n9 the
lop) IS'n t he
public class MyRemoteClient {
public static void main (String[] args)
new MyRemoteClient() .go();

J. t ht V't~isty~ as ~'/Yt
public void go () \t t.o.,.,es Ol/.t 't ~«~tt t ht t.as
r: O'oy:.t.t, so don
try { \I-
MyRemote service = (MyRemote) Naming .lookup(~rmi://127.0.0.1/Remote Hello");

String s = service . sayHello () ; Y d


010 nee "Ule
1-. 7
IP address
'\
a c1 t.he "artie ~ed VI
L-

It or hosw...e VI I L ' d Lhe stV'vit.t


System.out.println(s); \ ~Vld V'CUly\ ~
catch (Exception ex) { It looks j lASt like a I
ex. printStackTrace (); tall! (E'lt.tept it 1
9'" ~r old "'cthod
Re...oteE'lt.teptio~1AS at now/edse the

you are here ; 621


RMI class files

Je sure each lMachhte has the class


files it "eeds.
The top three things programmers do wrong with RMI are:
1) Forget to start rmiregistry before starting remote service
(when you register the service using Nammg.rebindt), the
nniregistry must be running!)
2) Forget to make arguments and return types serializable
(you won't know until runtime; this is not something the
compiler will detect.)
3) Forget to give the stub class to the client.

,gclient

Do,,'t +cn-5tt, tilt zhe..+'


uses the i"te~~att to tall
llUJln,
10UIn-
lIilUO""l
10 UO'
o U CI
o 11 0
Methods <»> the st.",b. Tnt O<Il1G1
0(111011
0CI110
00\ 01
clie"t JVM "eeas the si",b MyRemotelmpl,class MyRemotelmpLStub.class
tla~, b~ the tliO'lt "eveY Cllentclass MyRemotelmpLStub.class
rete",s to the shb class lQt~OI

i.- toae. Tbe tlit"t. always lOU01.,


to HoO 1.
l~
6 11 0
H.I) I

L~
v.ses the ve... o{:e i"ktate, ~ 1\ I)
~~l 10
OGt
"'" .t
UtOl
as thou5h the l"t"'ote MyRemotelmpl_Skel.class
iPlttrk.lte WERE. t.he MyR9mote.class
atb.al yC"'oU: objttt.
SeYVer "eeds both the stub a..a Skeld:.o"
dasses, as ""ell as the seYviu a.-t:I the
l"C"'otL i"u,-tau. It. MeaS the st.Lt'o tlass
~t.alAU rC"'-t'"bcr, the st.",b is s",bst.i+'"iea
to\" the veal service, wh(l\ the veal w-vice
is bOWla +.0 the RMI . . c5isttY·

622 chapter 18
remote deployment with RMI

~n yoor penCil
W:~$J~
Look at the sequence of events below, and
1.

2.
place them in the order in which they
occur in a Java RMI application.
3.

The client gets Ihe slub from 4.


-The--SlU-b-se-n-;ds-:th~e::--:m::e:;\h;;:od~ Ihe RMI regIstry
call to the server The diem invokes 8'm
s.
on the stub
The clIent does a looku
the RMI Registry
6.
The RMI registry Issta ate service (remote
implementation) isinstantiated
7.

,---- IUUR POINTS~


• An object on one heap cannot geta normal Java • Your remote service should extend UnicastRemoleObject.
reference 10 an object on a different heap (which means (Technically there are other ways 10 create a remote ob-
running on a different NM) ject, but extending UnicaslRemoteObject is the simplest).
• Java Remote Method Invocation (RMI) makes it seem like • Your remote service class must have a constructor,
you're calting a method on a remote object (l.e. an object and the constructor must declare a RemoleException
in a different JVM), but you aren't (because the superclass constructor declares one).
• When a client calls a method on a remote object, the • Your remote service must beinstantiated, and the object
client is really calling a method on a proxy of the remote registered with the RMI registry.
object. The proxy is called a 'stub'. • To register a remote service, use the static
• A stub is a client helper object that takes care of the low- Naming.rebind('Service Name", servicelnstance);
level networking details (sockets, streams, serialization, • The RMI registry must be running on the same machine
etc) bypackaging and sending method calls to the asthe remote service, before you try 10 register a remote
server. object with the RMI registry.
• To build a remote service (in other words, an object that • The client looks up your remote service using the static
a remote client can ultimately call methods on), you must Naming.lookup{'rmi:/IMyHostNameJServiceName");
start with a remote Interface.
• Almost everything related to RMI can throw a
• Aremote Inlerface must extend the java.rml.Remote RemoteException (checked bythe compiler). This
Interface. and all methods must declare Includes registering orlooking upa service In the relgstry,
RemoteException. and a/lremote method calls from the client tothe stub.
• Your remote service implements your remote Interface.

you are here. 623


usesfor RMI

Yeah, but who really uses RMI?

I use it
for serious B-to-B,
e-commerce back-
ends, running on J2EE
technology. I

624 chapter 18
remote deployment w ith RMI

100% Local Combination 100% Remote

What about Servlets1


Servlets are Java programs that run on (and with) an HTfP web server. When a dient uses a
web browser to interact with a web page, a request is sent back to the web server. If the request
needs the help of a Java servler, the web server runs (or calls, if the servlet is already running)
the servlet code. Servlet code is simply code that runs on the server, to do work as a result of
whatever the client requests (for example, save information to a text file or database on the
server). If you're familiar with eGl scripts written in Perl, you know exactly what we're talking
about. Web developers use CGJ scripts or servlets to do everything from sending user-submitted
info to a database, to running a web-site's discussion board.
And even serolets can use RMI/
By far, the most common use ofJ2EE technology is to mix servlets and EJBs together, where
servlets are the client of the EJB. And in that case, theserulet is using RJ1IlI to talk to theEJBs.
(Although the way you use RM1 with EJB is a little different from the process wejust looked at.)

1 Client fills out a registration form and clicks 'submit',


The HTTP server (i.e. web server) gets the request, sees that
it's for a servlet, and sends the request to the servlet,
Web Server
Web Browser
(client) -client requests RegisterServlet"

Servlet (Java code) runs, adds data to the database,


composes a web page (with custom info) and sends it back to
the client where it· displays in the browser.
Web Server
Web Browser
(client) "client requests Register5ervlet"
................

........ "heres a confirmation page"

conflnn.html
you are here. 625
very simple servlet

Step for making and running a servlet

Web Sel"Ver
G) Find out where your servlets need to be placed.
For these examples, we'll assume that you already have a web server
up and running, and that it's already configured to support servlets,
The most important thing is to find out exactly where your servlet
class files have to be placed in order for your server to 'see' them. If
you have a web site hosted by an ISP, the hosting service can tell you
where to put your servlets.just as they'll tell you where to place your
eGI scripts.

® Get the servlets.jar and add It to your c10sspath


Servlets aren't part of the standard Java libraries; you need
the servlets classes packaged into the servlets.jar file. You can
download the servlets classes fromjava .sun.com, or you can get
them from yourJava-enabled web server (like Apache Tomcat, at
servlals.Jar
the apache.org site). Without these classes, you won't be able to
compile your servlets.

® Write a servlet closs by extending HttpServlet UU Ot;


16 U~ I
o
A servlet isjust aJava class that extends HttpServlet (from the U 0
Cl61 1C1
Ql)l OI
javax.servlet.http package). There are other types ofservlers you
can make, but most of the time we care only about HttpServlet. MyServletA.cJass

public class MyServletA extends Htt:pServlet { ... }

~
@ WrIte an HTML page that invokes your servlet
When the user clicks a link that references your servlet, the web
server will find the servlet and invoke the appropriate method MyPage,html
depending on the HITP command (GET, POST. etc.)
<a href="aervlets/MyServletA">This is the most amazing servlet.</a>

Web Server
@ Make your servlet and HTML page Qvallable to your server
~l
~.
1-, " ~-
\" .

This is completely dependent on your web server (and more specifi-

- .J I'
~
cally, on which version ofJava Servlets that you're using). Your ISP " '-- - .' :
may simply tell you to drop it into a "Servlets" d irectory on your
web site. But if you're using, say, the latest version of Tomcat. you'll ' I, :1·.·. "
,I •.
,. :',- -
have a lot more work to do to get the servlet (and web page) into I ; , -:::-,'
the right location. (We just happen to have a book on this too .)

626 chapter 18
servlets and JSP

Dtherel&rH ? "
ume ~uestl9ns
Q.: What's a JSP, and how does it relate to servlets7
• Servlets are Java classes that run entirely on


(and/or within) an HTIP(web) server.
Servlets are useful for running code on the
A: JSP stands for Java Server Pages. In the end, the web server
turns a JSP into a servlet, but the difference between a servlet and
server as a result ofclient interaction witha a JSP is what YOU (the developer) actually create. With a servlet,
web page. For example, if a client submits you write a Java class that contains HTML in the output statements
information ina web page form, the servlet can (if you're sending back an HTML page to the client). But with a
process the information, add it toa database, JSP, it's the opposite-you write an HTML page that contains Java
and send back a customized, confirmation code!
response page. This gives you the ability to have dynamic web pages where you
write the page as a normal HTML page, except you embed Java
• To compile a servlet, you need the servlet code (and other tags that"trigger" Java code at runtime) that
packages which are in the servlets.jar file. The gets processed at runtime. In other words, part of the page is
servlet classes are not part ofthe Java standard customized at runtime when the Java code runs .
libraries, so you need todownload the servlets. The main benefit of JSP over regular servlets is that it's just a lot
jarfrom java.sun.com orget them from a servlet- easier to write the HTML part of a servlet as a JSP page than to
capable web server. (Note: the Servlet library write HTML in the torturous print out statements in the servlet's
is included with the Java 2 Enterprise Edition response. Imagine a reasonably complex HTML page, and now
(J2EE)) imagine formatting it within println statements. Yikes!
But for many applications, it isn't necessary to use JSPs because
• To run a servlet, you must have a web server
the servlet doesn't need to send a dynamic response, or the
capable ofrunning servlets, such as the Tomcat
HTML is simple enough not to be such a big pain. And, there are
server from apache.org. still many web servers out there that support servlets but do not
support JSPs, so you're stuck.
• Your servlet must be placed ina location that's
specific to your particular web server, so you'll Another benefit of JSPs is that you can separate the work by
need to find that out before you trytorun your having the Java developers write the servlets and the web page
servlets. If you have a web site hosted byan ISP developers write the JSPs. That's the promised benefit, anyway.
In reality, there's still a Java learning curve (and a tag learning
that supports servlets, the ISP will tell you which
curve) for anyone writing a JSP, so to think that an HTML web page
directory to place your servlets in.
designer can bang out JSPs is not realist ic. Well, not without tools.
• Atypical servlet extends HttpServlet and But that's the good news-authoring tools are starting to appear,
that help web page des igners create JSPs without writing the
overrides one ormore servlet methods, such as
code from scratch.
doGetO ordoPostO.
• The web server starts the servlet and calls the
Q.: Is this all you're gonna say about servlets? After such a
appropriate method (doGetO, etc.) based on the
huge thing on RMI7
client's request.
• The servlet can send back a response by getting
a PrintWriter output stream from the response A: Yes. RMI is part of the Java language, and all the classes for
RMI are in the standard libraries. Servlets and JSPs are not part of
parameter ofthe doGetO method.
the Java language; they're considered standard extensions. You
• The servlet 'writes' out an HTML page, complete can run RMI on any modern JVM, but Servlets and JSPs require a
properly configured web server with a servlet "container': This is
with tags).
our way of saying, "it's beyond the scope of this book." But you can
read much more in the lovely Head First Servlets & JSp'

628 chapte r 18
remote deployment with RMI

Just for fUt1, lets tMake the Phrase-O-Matic


work as aservlet Try my
new web-enabled
Now that we told you that we won't phrase-o-matic and you'll
say any more about servlets, we can't be a slick talker just like
resist servletizing (yes, we am verbify the boss or those guys in
it) the Phrase--O-Matic from chapter 1. marketing.
A servlet is stilljustJava. AndJava code
can call Java code from other classes.
So a servlet is free to call a method on
the Phrase-O-Matic. All you have to do
is drop the Phrase-O-Matic class into
the same directory as your servlet, and
you 're in business. (The Phrase-O-
Matie code is on the next page) .

import java .io.* ;

import javax.servlet .- ;
import javax.servlet .http .*;

public class KathyServlet extends BttpServlet {


public void doGet (HttpServletRequest request, BttpServletResponse response)
throws ServletException, IOException

String title = "PhraseOMatic has generated the following phras8. H ;

response. setcontentType ("text/html") ;


PrintWriter out = respons8.getWriter();

out.printl.n(\\<HTML><HEAD><'l'ITLE>"); r: r \/OUI( SfY"'~ I -l. td\'l t4\\ ",~od1


I
QI'\
\1' II
I tho

~
~ee. T t4u 'fleve U 1\'1;)
out .println ("PhraseOmatio H
) ; ano1:.hey t.\a~ \'I I!> () '~cKi cJ the
ou t .p ri nt l n ("</TITLEX/HEAD><BOD'l>") ; t,\\e s-laBt. ",a\t.eP'nya.!>l '" ..,.t, a e}
out .println("<B1>" + title + " </ 8 1>" ) ; P~ya1(OMdtiC. tlau (()f'I the ne Y ~
out.prlntln("<P>" + Phr&seOMatic.makePhrass());
out.println(~<Pxa href=\"KathyServlet\ ">make another phrase</a></p>H);
out.println ("</BODY></BTML>") ;

out. close () ;

you are here ~ 629


Phrase-O-Matic code

Phrase-O-Matic code, servlet-friet1dly


This is a slightly different version from the code in chapter one. In the
original, we ran the entire thing in a mainO method, and we had to rerun
the program each time to generate a new phrase at the command-line. In this
version, the code simply returns a String (with the phrase) when you invoke
the static makePhrase 0 method. That way, you can call the method from any
other code and get back a String with the randomly-composed phrase.
Please note that these long String[] array assignments are a victim of word-
processing here-don't type in the hyphens! Just keep on typing and let your
code editor do the wrapping. And whatever you do, don't hit the return key in
the middle of a String (i.e. something between double quotes).

public class PhraseOMatic {


public static String makePhrase()

II make three sets of words to choose from


String[] wordListOne = {"24/7","multi-Tier","30,OOO foot","B-to-B","win-win","front-
end", "web-based" ,"pervasive" , "smart", "six-sigma","critical-path", "dynamic"};

String[] wordListTwo = {"empowered", "sticky", "valued-added", "oriented", "centric",


"distributed", "clustered", "branded","outside-the-box", "positioned", "networked", "fo-
cused", "leveraged", "aligned", "targeted", "shared", "cooperative", "accelerated"};

String[] wordListThree = {"process", "tipping point", "solution", "architecture",


"core competency", "strategy", "mindshare", "portal", "space", "vision", "paradigm", "mis-
sion"};

II find out how many words are in each list


int oneLength = wordListOne.length;
int twoLength = wordListTwo.length;
int threeLength wordListThree.length;

II generate three random numbers, to pull random words from each list
int randl (int) (Math.randomO * oneLength);
int rand2 (int) (Math .randomO * twoLength);
int rand3 = (int) (Math.randomO * threeLength);

II now build a phrase


String phrase = wordListOne[randl] + " " + wordListTwo[rand2] + " " +
wordListThree[rand3] ;

II now return it
return ("What we need is a " + phrase);

630 ch apt er 18
remote deployment with RMI

RMI is great for writing and running remote services. But


you wouldn't run something like an Amazon or eBay on RMI An EJB server adds abunch
alone. For a large, deadly serious, enterprise application, you
need something more. You need something that can handle
of services that you don't get
transactions, heavy concurrency issues (like a gazillion with straight RMI. Things
people are hitting your server at once to buy those organic
dog kibbles), security (not just anyone should hit your like transactions, security.
payroll database), and data management. For that, you need
an enterprise applil;atUm server. concurrency. database
In java, that means a java 2 Enterprise Edition 02EE) server. management. and networ"king.
AJ2EE server includes both a web server and an Enterprise
JavaBeans(EJB) server, so that you can deploy an application An EJB server steps into the
that includes both servlets and EJBs. Like servlets, EJE is
way beyond the scope of this book, and there's no way to middle of an RMI call and
show "just a little" EJE example with code, but we wiU take
a quick look at how it works. (For a much more detailed layers in all ofthe services.
treatment ofEJE, we can recommend the lively Head First
EJB certification study guide.)

EJ'B server:.-_---\-,--
.- ..... '.

This is only a small paM of the E,JB picture.!

you are here ~ 831


a little J InI

For our final trick... a little Jini


We love jini. We think]ini is pretty much the best thing in Java. IfE]B is RMI
on steroids (with a bunch of managers), Jini is RMI with wings. PureJava bliss.
Like the EJB material, we can't get into any of the Jini details here, but if you
know RMI, you're three-quarters of the way there. In terms of technology,
anyway, In terms of mindset, it's time to make a big leap. No, it's time to fl>'.
Jini uses RMI (although other protocols can be involved), but gives you a few
key features including:
Adaptive discovery
Self-healing networks
With RMT, remember, the client has to know the
name and location of the remote service. The
client code for the lookup includes the IP address or
hostnarne of the remote service (because that's where
the RMI registry is running) and the logical name the
service was registered under.
But withjini, the client has to know only one thing: the
interface implemented by the service! Tha t 's it.
So how do you find things? The trick revolves aroundjini lookup
services. jini lookup services are far more powerfuJ and flexible than
the RMI registry. For one thing,jini lookup services announce themselves to the
network, automatically. When a lookup service comes online, it sends a message (using IP
multicast) out to the network saying, "I'm here, if anyone's interested."
But that's not all. Let's say you (a client) come online after the lookup service has already
announced itself, you can send a message to the entire network saying, "Are there any
lookup services out there?"
Except that you're not really interested in the lookup service itself-you're interested in
the services that are registered with the lookup service. Things like RMI remote services,
other serializable java objects, and even devices such as printers, cameras, and coffee-
makers.
And here's where it gets even more fun: when a service comes online, it will dynamically
discover (and register itself with) any Jini lookup services on the network. When the
service registers with the lookup service, the service sends a serialized object to be placed
in the lookup service. That serialized object can be a stub to an RMT remote service, a
driver for a networked device, or even the whole service itself that (once you get it from
the lookup service) runs locally on your machine. And instead of registering by name, the
service registers by the interfacei: implements.
Once you (the client) have a reference to a lookup service, you can say to that lookup
service, "Hey, do you have anything that implements Scienuficf'alculator?" At that point,
the lookup service will check its list of registered interfaces. and assuming it finds a
match, says back to you, "Yes I do have something that implements that interface. Here's
the serialized object the ScientificCalculator service registered with me."
632 chapter 18
remote deployment with RMI

Adaptive discovery i" actio"


@) Jini lookup service is launched somewhere on the network, and
announces itself using IP multicast.

machIne on the network another machine on the network


somewhere ...

Register
me os something

• An already-running Jini service on


another machine asks to be registered
with this newly-announced lookup
service . It registers by capability,
that implements
ScientificCaJculator. Here's a
serialized object that represents
my service . Send it to
anybody who asks...
rather than by name. In other words,
it registers as the service interlace it
implements. It sends a serialized object
to be placed in the lookup service.

machine on the network another machine on the network


somewhere...

you are he re . 633


adaptive discovery in Jini

Adaptive discovery itt actio", co"thtued...


® A client on the network wants
something that implements the
ScientificColculator interface. It has
no idea where (or if) that thing exists,
so it asks the lookup service.
another machine
on the network

machine on the network


another machine on the network
somewhere...

@ The lookup service responds, since it does have something


registered as a ScientificCalculator interface.

machine on the network


another machine on the network
somewhere ...

634 ch apter 18
remote deployment with RMI

Self.. healit1Q t1etwork it1 actio"


e A Jini Service has asked to register with the lookup service. The lookup
service responds with a "leese". The newly-registered service must keep
renewing the lease, or the lookup service assumes the service has gone
offline. The lookup service wants always to present an accurate picture
to the rest of the network about which services are available.

another machine
on the network

machine on the network another machine on the network


somewhere .. ,

® The service goes off line (somebody shuts it down), so it fails to


renew its lease with the lookup service. The lookup service drops it.

machine on the network


another machine on the network
somewhere...
you are here ~ 635
universal service project

Fhtal Project: the Ut1iversal Service browser


We're going to make something that isn't jini-enabled, but quite easily could be.
It will give you the flavor and feeling ofJini, but using straight RMI. In fact the
main difference between our application and aJini application is how the service is
discovered. Instead of the Jini lookup service, which automatically announces itself and
lives anywhere on the network, we're using the RMI registry which must be on the same
machine as the remote service, and which does not announce itself automatically.
And instead of our service registering itself automatically with the lookup service, we
have to register it in the RMl registry (using Naming.rebind()).
But once the client has found the service in the RMI registry, the rest of the application
is almost identical to the way we'd do it inJini. (The main thing missing is the kasethat
would let us have a self-healing network ifany of the services go down .)
The universal service browser is like a specialized web browser, except instead of HTML
pages, the service browser downloads and displays interactive Java GUIs that we're
calling uniuersal services.

RMIBrowser Choose a ~Ite k'f'ol'l\ the


list The RMI TC"'oU: W"\IiU
has a ~~\IiteList.O
...cthod -th.it ~N:Js batK this
list. o-t SCT\litcs.
WheJI +.hc \!Sa' ~Ieth OYIC,
-the tl, eJI t. asks .f 0\'" the
ad;\oIG1 scrvitc cDil.eRolli,,~
Da'l0fneWccKJ e+.tJ to
be ~t batlt. ~'f'0ft\ the RMI
yt"'oU: W"\/itc.

636 chapter 18
remote deployment w ith RMI

How it works:
Server
CI ient starts up and Service Browser
does a lookup on the (client)
RMI registry for
the service called
"Service.Server", and
gets back the stub.

Client calls getServiceListO on the stub. The ServiceServer


returns an array of services
Server
ServIce Browser
(client) - "getServiceListO· ~==
-
"OK, here's an array of services"

• Client displays the list of services in a GUI

Server
Service Browser
(client)

you are here. 631


universal service browser

How it works, continued ...

• User selects from the list, so client calls the get5erviceO


method on the remote service. The remote service returns a
serialized object that is an actual service that will run inside
the client browser.

Server
'getService(selectedSl/ct

'OK, here 's the service-

• Client calls the getGuiPanelO on the serialized service object it


just got from the remote service. The GUI for that service is
displayed inside the browser, and the user can interact with it
locally. At this point , we don't need the remote service unless/until
the user decides to select another service.

Service Browser
(client)

638 chapter 18
remote deployment with RMI

The classes and interfaces:

interface Servlce.Server Implements Remote Servlc9Server


A regular old RMI remote interlace for the remote service (the gelServicesUslO
remote service has the method for getting the service list and gelServlceO
returning a selected service).

• class ServlceServerImpl Implements 5ervlceServer


The actual RMI remote service (extends UnicastRemoteObject). ServlceServerlmpl
Its job is to instantiate and store a/l the services (the things gelServicesListO
that will be shipped to the client), and reg ister the server itself gelServiceO
(ServiceServerImpJ) with the RMI registry.

3' class ServlceBrowser


The client. It builds a very simple GUI, does a lookup in the RMI ServlceBrowser
registry to get the Service5erver stub, then calls a remote method on mainO
it to get the list of services to display in the GUI list .

Interface Service
This is the key to everything. This very simple interface has just one
method, getGuiPanelO . Every service thot gets shipped over to the
client must implement this interface. This is what makes the whole thing
UNIVERSAL! By implementing this int e rface , a service can come over
even though the client has no ideo what the actual class (or classes) S&lVlce
are that make up that service. All the client knows is that whatever
comes over, it implements the Service interface, so it MUST hove a getGuiPaneJO
getGuiPanelO method.
The client gets a serialized object as a result of calling
getService(selectedSvc) on the Service5erver stub, and all the client
says to that object is, "r don't know who or what you are, but I DO . ..
,
.
., ..
~

'"
know that you implement the Service interface, so I know I can call , ., ..
getGuiPanelO on you. And s ince getGuiPanelO returns a JPanel , rll just
,,
,
,
" I
I

,,
"

...I

slap it into the browser GUI and start interacting with itl
,,
,
, ,,
,, ...
/ I ....

: DiceServlce
r - - - - - -... . ..
class Dic£5ervice implements Service
Got dice? If not , but you need some, use this service to roll anywhere
. .... gelGulPanelO ..
from 1 to 6 virtual dice. for you. ,, ...
class MlnlMusicService implements Service
..
, .
Remember that fabulous little 'music video' program from the first ,, MlnlMuslcServlce
GUI Code Kitchen? We've turned it into a service, and you can play it r----'-----~ gelGulPanelO
over and over and ove.r until your roommates finally leave. DayOfTheWeekServlce
gelGuiPanelO
• class DayOfTheWukSuviu Implements Suvlce
Were you born on a Friday? Type in your birthday and find out .

you are here. 639


universal service code

interface ServiceServer (the remote interface)

import java.rmi.*;
public interface ServiceServer extends Remote (
Object [] getServiceList () throws RemoteException;
Service getService(Object serviceKey) throws RemoteException;

public interface Service extends Serializable {


public JPanel getGuiPanel();

640 chapter 18
remote deployment with RN

ass ServiceServerlmpl (the remote Implementation)


java.rm.i.*;
java.util.*;
java. rm.i. server. • ; \ RM\ 'l"'f\tl'l\tn~bOt'l
A \"\O'I'",a
public class ServiceServerImpl extends UnicastRemoteObject implements ServiceServer

BashMap serviceList;

public ServiceServerImpl () throws RemoteException I


setUpServices() ;
. 'b aliu tht ad:.u.al )
~1..d.D'r i~ taIled, '~I . M~itS~:r.il{,t., dt..
V/'h(.Yt the t. . CDit.tStY~iU) M,nI
private void setUpServices () ( . _"\ ~e.YV~t.es
serviceList = new BashMap();
...nIV(;,'~

service.List.put("Dice Rolling Service", new DiceService();


servlceList. put ("Day of the Week Service" I new DayOfTheWHkService () ) ;
serviceLlst.put("Visual Music Service", new MiniMusicService()); .u

~
L\..6 KyVit.e.~ (the. at~~I\..K"""1
MaKe. V'" t t\olc.'" '' ''1v> v>c. r
o'oy:tb) a~ flo' sh"',,,~ I\il .... e (-to'!"
~as\olMa~J WIth a
the. 'KC'/ ).
public Object£] getServiceList () { Client. t.alts .1, . .
. t l ('"
S ys tern . ou t . ~rl.n. te")
n an r6ltlO; display in the"UlJSbroIn oraet- f.o ;)Cl:
Q....L /• .L
a Ib~ f'
O't s~viles f.o
return servJ..ceLJ..st.keySet() ,toArray(); ~ d r wsa- (s.o t.he lI.S~ tan ~1.1. )
iln array o-t f. e Ob' t e... l; one We
h

~ il'lSiae) by "'d kin9


j .. the lf~lhN!ap. We
a!:rrd
~:f .(eva. th~h ii: has S&-il'l~s
,'Y JlI.St the i(EYS t.h~f. a"e
I J W<»It lCha ~n ~lt."~1 C' - •
LAn eLl; f.he diePlt asks .for ;1 b . -.. ~.,.v'te objai
l; y l.dJlln~ gef.StrvileO.

public static void main (Strinq[] arqa) {


tty {
Naminq.rebind("ServiceServer", new Servic:eServerImpl(»:
catch(Exception ex) (
ex,printStackTraoe() ;
}
Syst&m.out.println("Ramote sarvice is running");

you are he re . 64
ServlceBrowser code

class ServlceBrowser (the client)

import java.awt.·i
import javax. swing. * i
~rt java.rmi.*i
import java.awt .event.*;

public class SarviceBrowsar

JPanel mainPanel;
JComboBox serviceList;
ServlceServer server;

public void buildGUI () (


JFrame frame = new JFrame(~RMI Browser H ) ;
mainPanel D new JPanel();
frame .geteontentPane () . add (BorderLayout.CEN'rEll, mainPanel); .~ lQOku.\,'
-e'nis Method o~s -e'n~ \~~iteL.irtO .
~j.ot[] ~i~~.M;:dd:'~:~::::~~t;~\_~
••

servlceList = new JCombo80x (services) ; JCorr-bo~ (the \~~. n~ cJ eat'n thi~ ',,, the oYTd'1'
Mav-e disylcl'1cl\'le Sh,~
fr8llMi. getcontentpane () . add (BorderLayout.NOR'l'B, serviceList);

serviceList.addActionListener(new MyListL1stener(»;

frame.setSize(SOO,500) ;
frama.setVisible(true) ;

642 chapter 18
remote deployment w it h RMI

Object[] getServicesList() {
Object obj = null;
Object[] services = null ;

try {

obj = Naming .lookup(~rmi://127 .0.0.1/ServiceServer");


)
catch(Exception ex) {
ex .printStackTrace() ;
} ~
server = (ServiceServer) obj; Cast the stlAb to th
so that we tall tall e ~".o~e illtertate type
~e ervlteListO Oil it '
try {

services = server.getServiceList() ; ~ __

catch(Exception ex) {
ex.printStackTrace() ; ~d:.set'viteLis·W ~ives lAS the at't'ay 0+ Objetts,
-Chat we display in the JCoMboBo'/C. tOt' Hie lASet' to
return services; selett tt'OI'l\.

class MyListListener implements ActionListener {


public void actionPerformed(ActionEvent ev) {

public static void main(String[] args)


new ServiceBrowser() .buildGUI();

you are here. 643


DiceService code

class DiceService (a universal service, implements Service)


eee lUIl l flD'Vrltt
- -~
Dlullolll"9_.
import javax.swing.·; '=

import java.awt.event.*; -
fT.1Wl SH

import java.io.*;

public class DiceService implements Service (

JLabel label;
JComboBox numOfDice;

public JPanel getGuiPanel() (


JPanel panel = new JPanel () ;
JButton button = new JButton("Roll 'em!");
String[] choices = {"I", "2", "3", "4", "5 H } ;
numOfDice = new JComboBox(ohoices) ;
label =
new JLabel ("dice values here");
button.addActionListener(new Rol1EmListener(»;
panel. add (numOfDice) ; ftt:r' th .
panel. add (button) ; St:r:i: i f..t:C»Il'",POl"idl'rt ",tthod! nt: ",eihod 0+ tht:
panel. add (label) ; thil S~i~t: : a~e--;_ v'e 07It: t.he dibrt's 901\1Id ~II whtrl
return panel; ..... a t ·.1'
l\ In
ua
SZ}t and loaded. rAJ, u" do whdie
tne ~t:u:jlliPa"eJO eihod
y
I vty y04l.
JPal'u~" $(I it bioi/as tht: at.t.:~1 d" J as II~n~ ~s you retur" a
- Ilt-ro,~ '-JUt.
public class RollEmListenar implements ActionListener {
publiC! void aotionPerfo:rmed(ActionEvent ev) {
/ I roll the dice
String diceOutput = "";
String selection = (String) numOfDice . get5electedItem () :
int numOfDiceToRoll = Integer.parselnt(selection) ;
for (int i =
0; i < numOfDiceToRoll; i++) (
int r =
(int) ((Math. random () * 6) + 1);
diceoutput += (" " + r);
)
label. setText (diceOUtput) ;

~arpen your penCil


Think about waysto improve the DiceService. One
suggestion:using what you learned In the GUI chapters,
makethe dice 9raphicaI.Use a rectangle, and draw the
appropriate number of circles on each one,correspondIng
to the roll for that particular die.
1---1
••
644 chapter 18
remote deployment with RMI

class MlnlMusicService (a universal service, implements Service)


1'i.~.o.!~6~
~w... ~=~"'~~~==;:~
............. -
import j avax . sound. midi ... ;
import java.io.*;
import javax.sving.*;
illlport java.art.*;
illlport java.awt.event .*;

MyDrawPanel myPanel;

public JPanel getGuiPanel () (


r
public clau MiniMusicService implements Service {
-n...
In<.. d'sola'ol
does's '\ I
t.he ,h·a\Oli,,~ ~'f"'I'
ta~lt.S ..,tIl C\l~
il
I /'t..\\
~.,.\iLt,~ ",rth06. L __
D~~ a"
. lot
tu.a\\~
°rt

(..,httr(
6

JPanel mainPanEll = new JPanel () ; thC "'~\.edJ


myPanel = new MyDrawPanel () ; ~ ya," .
JButton playltButton = new JButton("Play it N ) ;
playItButton.addActionLiatener(ne. PlayItLlstener());
mainPanel.lldd(myPanel) ;
mainPanel.lldd(playItButton);
return mainPanel;

publio class PlayItListener implements ActionLiatener


publie void actionPerfo~(ActionEventev) (

try (

Sequencer sequencer = MidiSystam. qetSequencer () ;


sequencer.open();

sequencer.addControllerEventLiatener(myPanel, new lnt[] (127»);


Sequence seq = new sequence (Sequence. PPQ, 4);
Track track = s&q.creataTrack() ;

for (lnt i = 0; i < 100; i+= 4) {

lnt rNum = (int) «(Math.random() * 50) + 1);


if (rNum < 39) ( II so now only do it if num <38 (15\ of the time)
track.add(makeEvent(144,l,rNum,lOO,l») ;
track.add(makeEvent(116,l,121,O,i));
track.add(makeEvent(128,l,rNum,lOO,1 + 2»;
)
II end loop

sequencer .aetSequence(seq);
sequencer.start();
sequencer.setTampoInBPM(220) ;
catch (Exception ex) (ax.printstackTrace();}

} 1/ close actionperfor=ed
) II close inner class

you are here. 645


MiniMuslcServlce code

class MiniMusicService, continued••.


public MidiEvent makeEvent(int comel, int chan, int one, int two, int tick) {
MidiEvent event = null;
try (
ShortMessage a = new ShortMessage();
a.setMessage(comel, chan, one, two);
event = new MidiEvent(a, tick);

}catch(Exception e) { }
return event;

class MyDrawPanel extends JPanel implements ControllerEventListener

II only if we got an event do we want to paint


boolean mag = false;

public void controlChange(ShortMessage event) {


msg = true;
repaint 0 ;

public Dimension getPreferredSize()


return new Dimension(300,300);

public void paintComponent(Graphics g) {


if (msg) {

Graphics2D g2 = (Graphics2D) g;

int r = (int) (Math.random() * 250);


int gr = (int) (Math.random() * 250);
int b = (int) (Math.random() * 250);

g.setColor(new Color(r,gr,b»;

int ht = (int) «Math.random() * 120) + 10);


int width = (int) «Math.random() * 120) + 10);

int x = (int) «Math.randomO * 40) + 10);


int y = (int) «Math.random() * 40) + 10);

g .fillRect(x,y,ht, width);
mag = false;

} II close i f
} II close method
} II close inner class
II close class
remote deployment with RMI

class DayOfTheWeekService (a universal service, Implements Service)

import javax.swing .-; ,.e 9:" ............


D.rroln...... s-w.. ~

import java .awt .event .·; -.. , .... ~I ...


import java .awt .* ; 0., IF . ~ ~..,
.... j l OOI I
import java.lo.·;
import java.util.* ;
import java. text . • :

public class DayOfTheWeekServicEl implements Service (

JLabel outpu t:Labe1 ;


JComboBox month;
JTextFleld day;
J'l'extField year;

public. JPanel qetGuiPanel () (


JPanel panel "" new JPanel () ;
JButton button"" new JButton(~Do it!");
button.addAetionListener(new DoltListener(»;
outputLabel. "" new .JLabel ("date appearll he.ra ") ;
DateFormatsymbols dataStuff = new DateFonaatsymbols () ;
month = new JComboBox(dateStuff.g8tMOnthll{»;
day"" new JTextField(8);
year ;: new J'l'extField (8) :
JPanel inputpanel ;: new JPanel (new Gr iciLayout (3 ,2) ) ;
inputPane1.add(new JLabel ("Month") ;
inputpanel .add(month);
inpu tPanel . add (new JLabel ("Day") ) ;
inputPanel.add(day);
inputPanel. add {new JLabel ("Year"» ;
inputPanel.ac1d(year) ;
panel. add (inputpanel) :
panel .add(button);
panel.add(outputLabel);
return panel;

public class DoItLlstener implements A.ctionLilltener J O\l "etd Cl ....e....i"dev


public void aotionPerformed(ActionEvent &V) ( R ~O" to t'hayUY 10 -\:.t:'1 ~~t.t,,~ ""o'r\t.~
int monthNum == month.getselectedIndexO; ; h "",,'olY a",d d
6 t. ho"" e"'lY,
lnt dayNum • Integer .paraeInt (day. qatTextO ); ~e is t\'~"'t\~ ~\; ~\ass-
n\ the H Aho.
int yearNum :: Integer. parselnt (year. getTaxt () ) ; \) 11 u.st. it. lASt> the Ca IoU 1 tt.i~'1 a fott.ern
Calendar 0 • Calendar. qetInst&nce () ;
c • set (Calendar. MONTH J monthN\DJl):
c. set (Calendar. DAY_OF_MONTH I dayNum); CIf
f
et.4\tDa~f~t \~d \"~,,t ",,-l:.,
~""'f~ t,nt f dw t"'' '
c. set (Calendar. YEAR, yearNum):
Date date :: c. qetTime () ;
String dayOfWeelt ;: (new SimplaDataFor:JUt ("EEEE format (date) :
N
) ) •

outputLabel . setText (dayOfW&elt) ;

you are here ~ 647


the end ... sort of

Congratulations!
You made it to the end.
Of course, there's stili the two appendices.
And the Index.
And then there's the web site•••
There's no escape, really.

648 hapter 18
Appendix A: *
Final Code Kitchen

Chris: groove2 revised


NIgel: dance beat

FinaLLy, the complete version 01 the BeatBox!


It connects to a simple MusicServer so that you can
send and receive beat patterns with other clients.

this is a new appendix 649


final BeatBox code

Final BeatBox client program


Most of this code is the same as the code from the CodeKitchens in the previous
chapters, so we don't annotate the whole thing again. The new parts include:
GUI - two new components are added for the text area that displays incoming
messages (actually a scrolling list) and the text field .

NETWORKING - just like the SimpleChatClient in this chapter, the BeatBox now
connects to the server and gets an input and output stream.

THREADS - again, just like the SimpleChatClient, we start a 'reader' class that
keeps looking for incoming messages from the server. But instead of just text, the
messages coming in include TWO objects: the String message and the serialized
ArrayList (the thing that holds the state of all the checkboxes.)

import java.awt.* ;
import javax .swing .*;
import java.io.*;
import javax. sound. midi . *;
import java.util .*;
import java.awt.event.*;
import java.net.*;
import javax.swing .event.*;

public class BeatBoxFinal

JFrame theFrame;
JPanel mainPanel ;
JList incomingList ;
JTextField userMessage;
ArrayList<JCheckBox> checkboxList;
int nextNum;
Vector<String> listVector = new Vector<String>() ;
String userName;
ObjectOUtputStream out;
ObjectInputStream in;
HashMap<String, boolean[]> otherSeqsMap new HashMap<String, boolean[]>();

Sequencer sequencer;
Sequence sequence;
Sequence mySequence = null;
Track track;

String[] instrumentNames = {~Bass Drum", ~Closed Hi-Hat", ~Open Hi-Hat","Acoustic


Snare", ~Crash Cymbal", ~Hand Clap", ~High Tom", ~ H i Bongo", ~Maracas", ~Whistle",
~Low Conga", ~Cowbell", ~Vibraslap", ~Low-mid Tom", ~High Aqogo", ~Open Hi Conga");

int[] instruments = {35,42,46,38,49,39,50,60,70,72,64,56,58,47,67 ,63);

650 appendi x A
appendix A Fina l Code Kitchen

public static void main (String[] args) (


new BeatBoxFinal() .startUp(args[O]); II args[O] is your user ID/screen name
fI\ l .f \J0~V- stv-eeYl Yla",e·
""----- AdO. a t..o",....aYlo-liYle av-~~",eYl1;. ov- I
public void startup(String name) { c...'/.cl....yIe·' 01ID j'ava 0eatBo'l-f=iYlal thef=lash
[}
userName = name;
II open connection to the server
try (
Socket sock = new Socket("l27 .0 .0.l", 4242);
out = new ObjectOutputStream(sock.getOUtputStream(»;
in = new ObjectInputStream(sock.getInputStream(»;
Thread remote = new Thread(new RemoteReader(»;
remote . start 0 ;
catch(Exception ex) (
System.out.println("couldn't connect - you'll have to play alone .") ;
}
setupMidi 0 ;
buildGUI () ;
II close s ta rtUp

public void buildGUI () ~lA.1 tode, YlothiYl~ Yle-." hev-e

theFrame = new JFrame("Cyber BeatBox");


BorderLayout layout = new BorderLayout() ;
JPanel background = new JPanel(layout) ;
background.setBorder(BorderFactory.createEmptyBorder(10,10,10,10»;

checkboxList = new ArrayList<JCheckBox>() ;

Box buttonBox = new Box(BoxLayout.Y_AXIS);


JButton start = new JButton("Start");
start.addActionListener(new MyStartListener(»;
buttonBox.add(start);

JButton stop = new JButton("Stop") ;


stop.addActionListener(new MyStopListener(»;
buttonBox.add(stop);

JButton upTempo = new JButton("Tempo Up");


upTempo.addActionListener(new MyUpTempoListener(»;
buttonBox.add(upTempo);

JButton downTempo = new JButton("Tempo Down") ;


downTempo.addActionListener(new MyDownTempoListener(»;
buttonBox.add(downTempo) ;

JButton sendlt = new JButton("sendIt");


sendlt.addActionListener(new MySendListener(»;
buttonBox.add(sendIt);

userMessage = new JTextField();

you are here ~ 651


final BeatBox code

buttonBox.add(userMessage):

Box namaBox ::; new Box (BoxLayout. 'i_AXIS) i


for (int i = 0; i < 16; i++) {
nameBox. aeld(naw Label (i.nst%UmentNames [i]» ;

background.. add (Bord.erLayout . EAST , buttonBox) i


background.. add (Bord.erLayou t. WEST, nameBox);

theFrame. qetContentpane () . add. (background) ;


GridLayout grid'" new GridLayout(16,16);
grid. aetVgap (1) ;
grid.setHqap(2):
mainPanel '" new .Ji'anel (grid) :
background. add (BorderLayout. CENTER, UlA1nPanel);

for (int i '" 0; i < 256; i++) (


JCheckBox c '" new JCheck.Box () ;
c .setse1ected(false);
checkboxList.add.(c) ;
DIlU.nPanel. add. (c) ;
II end loop
theFrAmQ.aetBounds(50,50,300,300);
theFrAmQ .pack () ;
theFrame.setVisible(true);
II close buildGUI

public void. setUpMidi ()


try (
sequencer IS MidiSystem .getSequencer () i

sequencer.open();
sequence IS new sequence (Saquence.PPQ,4) ;
track '" sequance.areateTrack();
sequencer.setTempolnBPM(120);
catch (Exception e) (e .printstackTrace () ;)

II close setUpMldi

652 appendix. A
appendix A Final Code Kitche n

public void buildTrackAndStart() {


ArrayList<Integer> trackList = null ; II this will hold the instruments for each
sequence .deleteTrack(track); h the t..het.k'ooi-tS
track = sequence.createTrack(); '0 'fIo\ki\'\~ thY"o~ t t to a\'\
?J",M 0 kO,t.kSJtel oYlO .,..aYYMi~~ ,chl/~Ylt koY" .o. L
l
for (int i = 0; i < 16; i++) { to «jtt "flt C\'\0 ",okiYl~ the . 1~1r;,. ACTL.:'! oSi"
i\'\stv-",,,,e\'\t ~. • o\e1'o, b",t It IS ~)< L oY"el/iol.lS
. et,,\1 ..0"', Y"eteY" "IP ,
trackList = new ArrayList<Integer>();
L
T\oils 'S yY" ' r . t.hay"eY"s, so L'
. the yyel/lOI.lS L LL f' "'\\ ei-y\aYlo"IOYl
a~aiYl.
'fIoS 1\'\ • to ~e" "fie -t
for (int j = 0 ; j < 16; j++) { Code~ltt..he\'lS
JCheckBox jc = (JCheckBox) checkboxList.get(j + (16*i»;
if (jc.isSelected(» (
int key = instruments[i];
trackList.add(new Integer(key»;
else {
trackList.add(null); II because this slot should be empty in the track
}
} II c lose inner l oo p
makeTracks{trackList);
} II c los e o ute r l oop
track.add(makeEvent{192,9,1,0,15»; II - so we always go to full 16 beats
try {
sequencer.setSequence(sequence);
sequencer . setLoopCount (sequencer. LOOP_CONTINUOUSLY) ;
sequencer .start();
sequencer.setTempolnBPM{120);
} catch(Exception e) {e.printStackTrace();}
} II close me tho d

public class MyStartListener implements ActionListener


public void actionPerformed(ActionEvent a) {
buildTrackAndStart() ;
} II c lose actionPe r f o rmed
II close inner cl as s

public class MyStopListener implements ActionListener


public void actionPerformed(ActionEvent a) (
sequencer . stop () ;
} II c l o se a c t ionPerformed
II close inne r c lass

public class MyUpTempoListener implements ActionListener


public void actionPerformed(ActionEvent a) {
float tempoFactor = sequencer.getTempoFactor();
sequencer.setTempoFactor«float) (tempoFactor * 1.03»;
} II close act i o nPer f o rmed
II c l o se inner c l ass

you are here . 653


final BeatBox code

public class MyDownTempoListener ~lements ActionListener


public void actionPerformed(ActionEvent a) {
fioat tempoFactor = sequencer .getTempoFactor();
sequencer.setTempoFactor«fioat) (tempoFactor * .97»;

public class MySendListener implements ActionListener (


public void actionPerformed(ActionEvent a) {
II make an arraylist of just the STATE of the checkboxes
boolean[] checkboxState = new boolean[256] ;
for (int i = 0; i < 256; i++) {
JCheckBox check = (JCheckBox)
if (check.isSelected(» {
checkboxState[i] = true;
}
} II close l oop
String messageToSend = null;
try {
out.writeObject(userName + nextNum++ + ". " + userMessage.getText(» ;
out .writeObject(checkboxState);
catch(Exception ex) {
System.out.println("Sorry dude. Could not send it to the server.") ;
}
userMessage.setText(" ");
} I I c l ose action Pe r f o r med
II c l os e i nne r c l a s s

public class MyListSelectionListener implements ListSelectionListener


public void valueChanged(ListSelectionEvent le) {
if (!le .getValueIsAdjusting(» {
String selected = (String) incomingList .getselectedValue();
if (selected != null) (
II now go to the map, and change the sequence
boolean[] selectedState = (boolean[]) otherSeqsMap.get(selected);
changeSequence(selectedState);
sequencer.stop();
buildTrackAndStart();

}
II close valueCha nged
I I c l os e i nne r class

654 append ix A
appendix A Final Code Kitchen
public class RemoteReader implements Runnable {
boolean[] checkboxState = null;
String nameToShow = null ;
Object obj = null;
public void rune) {
try {
while«obj=in.readObject(» != nul l ) {
System.out.println("got an object from
System.out.println(obj .getClass(»;
String nameToShow = (String) obj ;
W~~II a ~esS4
checkboxState = (boolean[]) in.readObject();
otherSeqsMap.put(nameToShow, checkboxState) ; (deseriaJi~) {h~
~~ssage alld.L
t:ob ill, lIIe read
listVector .add(nameToShow) ; t hetkb. ,;he Arra
e 1110
rs the
the JL~~ stau vallAesf~ Ids+, 0+ Boo/eall
incomingList.setListData(listVector) ;
c:
ie t L (

} I I close wh i l e .
IS a 1;111 U Ohe n,;..L Add'
J C to~p I'l tidd ·.L J
I,; 1;0
catch(Exception ex) {ex.printStackTrace();} 0+ 11
the!:;ts p thil'l.9: 'lOlA k 1 9 to a JList
I I close run fashioned A data !Vetto :~p a Vettor
II close inner c lass JList to rrayLisi) a ; an oJd_ 't.
.for wh t lAse thai. Ve~k hen t~1J t h
public class MyPlayMineListener implements ActionListener { a to display' .L as it's SOIA e
public void actionPerformed(ActionEvent a) { III ,;h~ lisi.. rt~
i f (mySequence != null) {
sequence = mySequence ; II restore to my original
}
} II cl ose ac tionPerformed
II close inner class This Ift~thod is tailed h t
i
sOlftethin~ .ft-Olft th I' ~ he lASer seletts
public void changeSequence(boolean[] checkboxSta~,n~ the patter: ;;.fh e /NI'j1hf;[)/ATE.LY
for (int i = 0; i < 256; i++) { e one .. ey selet ted.
JCheckBox check = (JCheckBox) checkboxList.get(i) ;
i f (checkboxState[i]) {
check .setSelected(true) ;
else {
check .setSelected(false) ;
All the MIDI sh H is ~uttl~ the SaMe as it
}
II c l ose l oop
I I close change Sequence was in the yYe'JiolAS 'Jet-Slon.

public void makeTracks(ArrayList list)


Iterator it = list . iterator();
for (int i = 0; i < 16 ; i++) {
Integer num = (Integer) it.next();
if (num != null) {
int numKey = num.intValue() ;
track.add(makeEvent(144 ,9 ,numKey, 100, i» ;
track .add(makeEvent(128,9 ,numKey,100, i + 1»;
}
} I I clo se loop
I I close makeTrac ks()

you are he re. 655


._ - -- - - - - - - -
final BeatBox code

public MidiEvent makeEvent(int comd, int chan, int one, int two, int tick) {
MidiEvent event = null;
try {
ShortMessage a = new ShortMessage();
a. setMessage (comd, chan, one, two);
event = new MidiEvent(a, tick);
}catch (Exception e} { } \i~e the last ~e'f"si()'l\·
return event; Not\\'''~ "eVl· J~t
} II close rnakeEvent

} II c l os e c l a s s

~yourpenCii
What are some of the ways you can improve this program?
Here are a few ideas to get you started :
1) Once you select a pattern, whatever current pattern was playing is blown
away. If that was a new pattern you were working on (or a modification of
another one), you're out of luck.You might want to pop up a dialog box that
asksthe user if he'd like to save the current pattern.

2) If you fail to type in a command-line argument, you just get an exception


when you run it! Put something in the main method that checks to see if
you've passed in a command-line argument. If the user doesn't supply one,
either pick a default or print out a message that saysthey need to run it
again, but this time with an argument for their screen name.

3) It might be nice to have a feature where you can click a button and it
will generate a random pattern for you.You might hit on one you really like.
Better yet, have another feature that lets you load in existing 'foundation'
patterns, like one for jazz, rock, reggae, etc. that the user can add to.
You can find existing patterns on the Head First Java web start.

656 appen dix A


appendix A Final Code Kitchen

Final BeatBox server program


Most of this code is identical to the SimpleChatServer we made in the
Networking and Threads chapter. The only difference , in fact, is that this server
receives, and then re-sends, two serialized objects instead of a plain String
(although one of the serialized objects happens to be a String).

import java.io.*;
import java.net.*;
import java.util.*;

public class MusicServer

ArrayList<ObjectOutputStream> clientOutputStreams;

public static void main (String[] args) {


new MusicServer() .go();

public class ClientHandler implements Runnable {

ObjectlnputStream in;
Socket clientSocket;

public ClientHandler(Socket socket) (


try {
clientSocket = socket;
in = new ObjectlnputStream(clientSocket .getlnputStream(»;

catch(Exception ex) (ex.printStackTrace();}


} II clos e const ruc t or

public void run {} {


Object 02 = null ;
Object 01 = null;
try {

while ((01 = in.readObject(» != null) (

02 = in .readObject();
System .out .println("read two objects") ;
tellEveryone(01, 02);
I I close wh ile

catch(Exception ex) (ex.printStackTrace();}


I I cl os e run
II c lo s e inn e r c lass

you are here ~ 657


final BeatBox code

public void qo() {


clientOutputStreams = new ArrayList<ObjectOutputStream>();

try {
ServerSocket serverSock = new ServerSocket(4242);

while (true) {
Socket clientSocket = serverSock.accept();
ObjectOutputStream out = new ObjectOutputStream(clientSocket.qetOutputStream(»
clientOutputStreams.add(out);

Thread t = new Thread(new ClientHandler(clientSocket»;


t. start() ;

System.out.println("qot a connection");
}
}catch(Exception ex) {
ex.printStackTrace();
}
II c lose go

public void tellEveryone(Object one , Object two)


Iterator it = clientOutputStreams.iterator();
while(it .hasNext(» {
try {
ObjectOutputStream out = (ObjectOutputStream) it .next();
out.writeObject(one) ;
out.writeObject(two) ;
}catch(Exception ex) {ex.printStackTrace() ;}

II close t e l l Everyone

} I I close class

658 appendix A
Appendix B
The Top Ten Topics that almost made it into the Real Book...

We covered a lot of ground,and you're almost finished with this book. We'll miss you, but before
we let you go, we wouldn't feel right about sending you out Into JavaLand without a little more
preparation. We can't possibly fit everything you'll need to know Into this relatively small appendix.
Actually, we did originally Include everything you need to know about Java (not already covered by
the other chapters), by reducing the type point size to .00003. It all fit, but nobody could read It. So,
we threw most of it away,but kept the best bits for this Top Ten appendix.

This really Is the end of the book. Except for the Index (a must-read I).

this is a new appendix 659


bit manipulati on

#10 Bit Manipulation


Why do you care? The Shift Operators
These operators take a single integer primitive and shift (or
We've talked about the fact that there are 8 bits in a byte, slide) all of its bits in one direction or another. If you want
16 bits in a short, and so on. You might have occasion to to dust off your binary math skills, you might realize that
turn individual bits on or off. For instance you might find shifting bits left effectively multiplies a number by a power of
yourself writing code for your newJava enabled toaster, two, and shifting bits right effectively divides a number by a
and realize that due to severe memory limitations, certain power of two.
toaster settings are controlled at the bit level. For easier
reading, we're showing only the last 8 bits in the comments We'll use the following example for the next three operators:
rather than the full 32 for an int).
int x = -11; II bits are 11110101
Bitwise NOT Operator: ... Ok, ok, we've been putting it off, here is the world's
This operator 'flips all the bits' of a primitive. shortest explanation of storing negative numbers, and
two's complement. Remember, the leftmost bit of an integer
int x = 10; II bits are 00001010 number is called the sign bit. A negative integer number in
Java always has its sign bit turned on (i.e. set to 1). A positive
x = -x; II bits are now 11110101
integer number always has its sign bit turned 011(0). Java
uses the two's complement formula to store negative numbers.
The next three operators compare two primitives on a bit To change a number's sign using two's complement, flip all
by bit basis, and return a result based on comparing these the bits, then add 1 (with a byte, for example, that would
bits. We'll use the following example for the next three mean adding 00000001 to the flipped value).
operators:

int x = 10; II bits are 00001010


Right Shift Operator: »
This operator shifts all of a number's bits right by a certain
int y = 6; II bits are 00000110 number, and fills all of the bits on the left side with whatever
the original leftmost bit was. The sign bit does not change:

Bitwise AND Operator: & int y =x »2; II bits are 11111101


This operator returns a value whose bits are turned on only
if both original bits are turned on:
Unsigned Right Shift Operator: »>
int a = x «y; II bits are 00000010 Just like the right shift operator BUT it ALWAYS fills the
leftmost bits with zeros. The sign bit mightchange:

Bitwise OR Operator:
This operator returns a value whose bits are turned on only int y = x»> 2; II bits are 00111101
if either of the original bits are turned on:

int a = x I y; II bits are 00001110 Left Shift Operator: «


Just like the unsigned right shift operator, but in the other
direction; the rightmost bits are filled with zeros. The sign bit
Bitwise XOR (exclusive OR) Operator: A
mightchange.
This operator returns a value whose bits are turned on only
if exactly oneof the original bits are turned on: int y = x «2; II bits are 11010100

int a = x A y; II bits are 00001100

660 appendix B
appendix B Top Ten Reference

#9 Immutability

Why do you eare that Strlt1i!..are 1"''Mutable? Why do you care that Wra2!.ers are
When yourJava programs start to get big. you 'll It"",utable?
inevitably end up with lots and lots of String objects. In the Math chapter we talked about the two main
For security purposes, and for the sake of conserving uses of the wrapper classes:
memory (remember yourJava programs can run on
teeny Java-enabled cell phones), Strings in java are • Wrapping a primitive so it can pretend to be an
immutable. What this means is that when you say: object.
• Using the static utility methods (for example,
String s = "0"; Integer. parseln t ()).
for (int x :: 1; x < 10; x++) ( It's important to remember that when you create a
8 = S + Xi wrapper object like:
)
What's actually happening is that you're creating ten Integer iWrap :: new Integer(42);
String objects (with values "0", "01", "012 ", through
"0123456789") . In the end s is referring to the String
That's it for that wrapper object. Its value will always
with the value "0123456789", but at this point there
be 42. There is no settermethodfor a wrapper object.
are ten Strings in existence I
You can , of course, refer iWrap to a different wrapper
Whenever you make a new String, theJVM puts it object, but then you'll have two objects. Once you
into a special part of memory called the ' String Pool' create a wrapper object, there's no way to change
(sounds refreshing doesn't it.?). If there is already the value of that objectl
a String in the String Pool with the same value, the
JVM doesn't create a duplicate, it simply refers your
reference variable to the existing entry. TheJVM can
get away with this because Strings are immutable; one
reference variable can't change a String's value out
from under another reference variable referring to
the same String.
The other issue with the String pool is that the
Garbage Collector doesn't go there. So in our example.
unless by coincidence you later happen to make a Roses orered. .
String called "01234", for instance, the first nine Strln ' Violets oreblue
.11S ar.'mmutobf, .
Strings created in our forloop willjust sit around e, 'NfDppe,s are too.
wasting memory.

How does this save memory?


Well, if you're not careful, it dcesn 't! But if you un-
derstand how String immutability works, than you
can sometimes take advantage of it to save memory.
If you have to do a lot of String manipulations (like
concatenations, etc .), however, there is another class
StringBuilder, better suited for that purpose. We'll
talk more about StringBuilder in a few pages.

you are here ~ 661


assertions

#8 Assertions
We haven't talked much about how to debug yourJava How to make Assertions work
program while you 're developing it. We believe that
you should learn java at the command line, as we've Add assertion statements to your code wherever you
been doing throughout the book. Once you're aJava believe that something must be true. For instance :
pro, if you decide to use an IDE*, you might have
assert (height> 0);
other debugging tools to use . In the old days, when
a java programmer wanted to debug her code, she'd II if true, program continues normally
stick a bunch of System .out.println ( ) statements
II if false, throw an AssertionError
throughout the program, printing current variable
values, and "I got here" messages, to see if the flow You can add a little more information to the stack
control was working properly. (The ready-bake code trace by saying:
in chapter 6 left some debugging 'print' statements
in the code.) Then, once the program was working assert (height> 0) : "height = " +
correctly, she'd go through and take aU those System . height + " weight = " + weight;
out.println( ) statements back out again . It was
The expression after the colon can be any legal
tedious and error prone. But as ofJava 1.4 (and 5.0),
Java exp ression that resolves to a non-null value. But
debugging got a whole lot easier. The answer?
whatever you do . don't create assertions that cJumge an
Assertions objed's stale! If you do, enabling assertions at runtime
might change how your program performs.
Assertions are like Systern .out.println ( ) statements
on steroids. Add them to your code as you would
add println statements. The java 5.0 compiler
Compiling and running with
assumes you 'll be compiling source files that are 5.0 Assertions
compatible, so as ofJava 5.0, compiling with assertions
To compilewilh assertions:
is enabled by default.
At runtime, if you do nothing, the assert statements javac TestDriveGame.java
you added to your code will be ignored by the JVM,
(Notice that no command line options were
and won 't slow down your program. But if you tell the
necessary.)
JVM to enable your assertions, they will help you do
your debugging, without changing a line of code I To run with assertions:
Some folks have complained about having to leave
java -ea TestDriveGame
assert statements in their production code, but
leaving them in can be really valuable when your
code is already deployed in the field. !fyour client
is having trouble, you can instruct the client to run
the program with assertions enabled, and have the
client send you the output. If the assertions were
stripped out of your deployed code, you'd never
have that option. And there is almost no downside;
when assertions are not enabled, they are completely
ignored by thejVM, so there's no performance hit to '" IDE SlaDW for Integrated Development Environment
worry about. and includes tools such as Eclipse, Borland's jbuilder, or
the open source NetBeans (netbeans.org).

662 appsnuix B
appendix B Top Ten Reference

#7 Block Scope
In chapter 9, we talked about how local variables
live only as long as the method in which they're
declared stays on the stack. But some variables can
have even shorter lifespans. Inside of methods, we
often create blocks of code. We've been doing this
all along, but we haven't explicitly talkedin terms of
blocks. Typically, blocks of code occur within methods,
and are bounded by curly braces {}. Some common
examples of code blocks that you'll recognize include
loops (jar, while) and conditional expressions (like if
statements) .
+,nod b\ot.\I.
Let's look at an example: s-tarl. ~ -tne ,.,e
void doStuff () {~ J t.o the e"tiYe ",ethod
, /_ lotal vayiable stofe"
Lnt; x = 0; ~

for (int y = 0; y < 5; y++) { ~be~i\'l\'li\'l~' a


~
stofed t.o
~
OY r
1 f blotk a"d '1 is
I "
0\'11'1 the 0\" oof·

x = x + y; ~ ..., LI y.. a"d \I aye both i\'l st°fe


1'0 fYOD e"', I
H- e\'lQ o.f the tor loop blotk

In the previous example, y was a block variable,


declared inside a block, and y went out of scope as
soon as the for loop ended. Your java programs will
be more debuggable and expandable if you use local
variables instead of instance variables, and block
variables instead of local variables, whenever possible.
The compiler will make sure that you don't try to use
a variable that's gone out of scope, so you don 't have
to worry about runtime meltdowns.

you are here • 663


linked invocations

#6 Linked Invocations
While you did see a little of this in this book, we tried to keep our syntax as clean and
readable as possible. There are, however, many legal shortcuts inJava, that you'll no doubt
be exposed to, especially if you have to read a lot code you didn't write. One of the more
common constructs you will encounter is known as linked invocations. For example:
StringBuffer sb = new StringBuffer("spring");
sb = sb.delete(3,6) .insert(2,"umme") . d e l e t e Ch a r At (l ) ;
System.out.println("sb = " + sb);
II result is sb = summer
What in the world is happening in the second line of code? Admittedly, this is a contrived
example, but you need to learn how to decipher these.
1 - Work from left to right.
2 - Find the result of the leftmost method call , in this case sb. delete (3, 6) . If you
look up StringBuffer in the API docs, you'll see that the delete () method returns a
StringBuffer object. The result of running the delete () method is a StringBuffer object
with the value "spr".
3 - The next leftmost method (insert () )is called on the newly created StringBuffer
object "spr". The result of that method call (the insert () method), is also a StringBuffer
object (although it doesn 't have to be the same type as the previous method return), and so
it goes, the returned object is used to call the next method to the right. In theory, you can
link as many methods as you want in a single statement (although it 's rare to see more than
three linked methods in a single statement). Without linking, the second line of code from
above would be more readable, and look something like this:

sb sb.delete(3,6);
sb sb.insert(2,"umme");
sb sb.deleteCharAt(l);
But here's a more common, and useful example, that you saw us using, but we thought
we'd point it out again here. This is for when your main 0 method needs to invoke an
instance method of the main class, but yo u don't need to keep a reference to the instance of
the class. In other words, the main 0 needs to create the instance only so that main 0 can
invoke one of the instance's methods.
c lass Faa {
public static void main (String [] args)
[
we do,,' t. ea-e ab~t.
L L
new Faa () . go (); ~ we 'fJa"t. +.0 t.all ~o ()
't. bot.heY assi~l'Iil'l~
,0,",,,.1
L r.: il'ls-tal'lt.e, so we l.\Ol'l I'
"t,he rOO r.: ~,. t.t. +.0 a ye-teyel'lt.e·
void go () t.he l'Iew rOO 0 ~e
I I here's what we REALLY want. ..
}

664 append ix B
appendix B Top Ten Reference

#5 Anonymous and Static Nested Classes

Nested classes come In many flavors


In the GUl event-handling section of the book, we started using inner (nested) classes as a
solution for implementing listener interfaces. That's the most common, practical, and read-
able form of an inner class-where the class is simply nested within the curly braces of another
enclosing class. And remember, it means you need an instance of the outer class in order to get
an instance of the inner class, because the inner class is a member of the outer/enclosing class.
But there are other kinds of inner classes including static and arwnymous. We're not going
into the details here, but we don't want you to be thrown by strange syntax when you see it in
sorneone's code. Because out of virtually anything you can do with the Java language, perhaps
nothing produces more bizarre-looking code than anonymous inner classes. But we'll start with
something simpler--static nested classes.
Static nested classes
You already know what static means-s-something tied to the class, not a particular instance. A
static nested class looksjust like the non-static classes we used for event listeners, except they 're
marked with the keyword static.

public class FooOuter (


class Barlnner
void saylt() {
System. out . printin ("method of a static inner class");
)
}

class Test (
publ ic s t a tic void

faa. sayIt () ;

Static nested classes are more like reguJar non-nested classes in that they don't enjoy a special relation-
ship with an enclosing outer object. But because static nested classes are still considered a member oi
the enclosing/outer class, they still get access to any private members of the outer class... but only the
onesthat arealso statu. Since the static nested class isn't connected to an instance of the outer class, it
doesn't have any special way to access the non-static (instance) variables and methods.

you are here ~ 665


when arrays aren't enough

#5 Anonymous and Static Nested Classes, continued

The diHerenee between nested and Inner


AnyJava class that's defined within the scope of another class is known as a rI£SU:d class. It
doesn't matter if it's anonymous, static. normal, whatever. If it's inside another class, it's
technically considered a nested class. But non-statu nested classes are often referred to as inner
classes, which is what we called them earlier in the book. The bottom line : all inner classes are
nested classes, but not all nested classes are inner classes.
Anonymous inner classes
Imagine you 're writing some GUI code, and suddenly realize that you need an instance
of a class that implements ActionListener. But you realize you don't have an instance of an
Actionl.istener, Then you realize that you also never wrote a class for that listener. You have two
choices at that point:
1) Write an inner class in your code, the way we did in our GUI code, and then instantiate it
and pass that instance into the button's event registration (addActionListenerO) method.
OR
2) Create an anonymous inner class and instantiate it, right there.just-in-time. Litera11y right
where YlJU are at the pmnt you need the listener or,jed. That's right, you create the class and the
instance in .the place where you'd normally be supplying just the instance. Think about that for
a moment-it means you pass the entire cla.sswhere you'd normally pass only an instance into a
method argumentl

666 append ix 8
access levels appendix B Top Ten Reference

#4 Access Levels and Access Modifiers (Who Sees What)

Java has four access levels and three access modifiers. There are only three modifiers because
the default (what you get when you don't use any access modifier) is one of the four
access levels.

Access Levels (in order of how restrictive they are, from least to most restrictive)

public ~ rlAblit ....eans any cede anywhere tan aUess the flAblit thin~ (by
thin~' we ....ean tlass, I/ariable, ....ethod, tonstrlAttor, eUJ.

protected "''-:- - - froutud works jlAst like detalAlt (tode in the sa....e fatka~e has auess), EXCEPT it
also allows slAbtiasses olAtside the fatka~e to inherit the yrotetud thin~.

default ~
detalAlt aUess ....eans that only cede within the sa....e fatka~e as
the tlass with the detalAlt thin~ tal'l aUess the detalAlt thin~.
private ~
fril/at e ....eans that ol'lly tode withil'l the same dass tal'l aUess the yril/ate thin~.
Keef il'l mil'ld it means fril/au to the tlass, not fril/ate to the objett. One D~
tal'l see al'lother D~ objett's fril/au shU, blAt a Cat tan't see a D~'s yril/aus.
Access modifiers

public
protected
private

Most of the time you'll use only public and private access levels.
public
Use public for classes, constants (static final variables) , and methods that you're
exposing to other code (for example getters and setters) and most constructors.
private
Use private for virtually all instance variables, and for methods that you don't want
outside code to call (in other words, methods used by the public methods of your class).
But although you might not use the other two (protected and default), you still need to
know what they do because you'll see them in other code.

you are here ~ 667


when arrays aren't enough

#4 Access Levels and Access Modifiers, cont.

default and protected

default
Both protected and default access levels are tied to packages. Default access is simple-it
means that only code within the samepackage can access code with default access. So a
default class, for example (which means a class that isn't explicitly declared as puhlil:) can
be accessed by only classes within the same package as the default class.
But what does it really mean to MUSS a class? Code that does not have access to a class is
not allowed to even think about the class. And by think, we mean use the class in code.
For example, if you don't have access to a class, because of access restriction, you aren't
allowed to instantiate the class or even declare it as a type for a variable, argument, or
return value. You simply can't type it into your code at all! !fyou do, the compiler will
complain .
Think about the implications-a default class with public methods means the public
methods aren't really public at all. You can't access a method if you can't see the class.
Why would anyone want to restrict access to code within the same package? Typically,
packages are designed as a group of classes that work together as a related set. So it might
make sense that classes within the same package need to access one another's code, while
as a package, only a small number of classes and methods are exposed to the outside
world (i.e. code outside that package).

OK, that's default. It's simple-if something has default access (which, remember, means
no explicit access rnodifierl), only code within the same package as the default thing
(class, variable, method, inner class) can access that thing.
Then what's proucudfor?

protected
Protected access is almost identical to default access, with one exception: it allows sub-
classes to inherit the protected thing, even iJthose subclasses are ()UtsUU the pad1.age of the super--
class they extend: That's it. That's all protected buys you-the ability to let your subclasses
be outside your superclass package, yet still inherit pieces of the class, including methods
and constructors.
Many developers find very little reason to use protected, but it is used in some designs,
and some day you might find it to be exactly what you need. One of the interesting things
about protected is that-unlike the other access levels-protected access applies only to
inheritance. If a subclass-outside-the-package has a nference to an instance of the superc1ass
(the superclass that has, say, a protected method), the subclass can 't access the pro-
tected method using that superclass referencel The only way the subclass can access that
method is by inheritingit. In other words, the subclass-outside-the-package doesn't have
access to the protected method. it just has the method, through inheritance.
668 appendix B
String and StringBuffer appendix B Top Ten Reference

#3 String and StringBufferlStringBuilder Methods


Two of the most commonly used classes in th e Java API are String and StringBuffer (rem em ber from
#9 a few pages back, Strings are immutable, so a StringBuffer/StringBuilder can be a lot mor efficient
if you're manipulating a String). As ofJ ava 5.0 you should use the StringBuilderclass in stead of
StringBuffer, unless your String manipulations need to be thread-safe, which is not co m m on . Here's a
brief overview of the key methods in these classes:
Both String and StringBuffer/StringBuilder classes have:
char charAt(int index) ; / / what char is at a ce rtain position
int Iength t): / / how long is th is
String substring(int start, int end ); / / get a part of this
String to.String () : / / what's the String value of th is

To concatenate Strings:
String co n cat (stri n g); / / for the String class

String appen d (Stri ng); / / for StringBuffer & StringBuilder

The String class has:


String replace (char old, char new); / / replace all occurences of a char
String substring(int begin, int end); / / get a portion of a String
char [] toCharArrayO ; / / convert to an array of chars
String toLowerCase () ; / / convert all characters to lower case
String toUpperCaseO; / / co nvert all characters to upper case
String trim () ; / / remove whitespace from the ends
String valueOf( char []) / / make a String out of a char array
String valu eOf(int i) / / make a String out of a primitive
/ / other primitives are supported as well
The StringBuffer & StringBuilder classes have:
StringBxxxx delete (int start, int end); / / delete a portion
StringBxxxx insert(int offset, any primitive or a char [] ); / / insert something
StringBxxxx replace (int start, int end, String s); / / replace this part with this String
Stringlsxxxx reverser): / / reverse the SB from front to back
void setCharAt(int index, char ch); / / replace a given character
Note: StringBxxxx refers to either StringBufferor StringBuilder, as appropriate.

you a re here. 669


when arrays aren't enough

#2 Multidimensional Arrays
In most languages, if you create, say, a 4 x 2 two-dimensional array, you would visualize a
rectangle, 4 elements by 2 elements, with a total of 8 elements. But inJava, such an array
would actually be 5 arrays linked together! In java, a two dimensional array is simply an arra)'
of arrays. (A three dimensional array is an array of arrays of arrays, but we'll leave that for
you to play with.) Here's how it works

i.nt ]] (] a2d = new int [4] (2];

The JVM creates an array with 4 elements. Each. of these four elements is actually a reference
variable referring to a (newly created), int array with 2 elements.

int array object (int[][D


int[J(]

Working with multidimensional arrays


- To access the second element in the third array: int x = a2d [2) [1) i I I remember, 0 based!
- To make a one-dimensional reference to one of the sub-arrays: int [J copy = a2d [1 J;
-Short-cut initialization ofa2x3array: intlJ I) x = ( l 2,3,4 }, I 7,8,9 } };
- To make a 2d array with irregular dimensions:
int(J [J y = new int (2) [); II makes only the first array, with a length of 2
y[Ol new int (3J; II makes the first sub-array 3 elements in length
y(l] = new int 15J; II makes the second sub-array 5 elements in length

670 appendix B
enumerations appendix B Top Ten Reference

And the number one topic that didn't quite make it in...

#1 Enumerations (also called Enumerated Types or Enums)

We've talked about constants that are defined in the API, for instance,
JFrame.EXIT_ON_CLOSE. You can also create your own constants by
marking a variable static final. But sometimes you'll want to create a set
of constant values to represent the only valid values for a variable. This set of
valid values is commonly referred to as an enumeration. Before Java 5.0 you
could only do a half-baked job of creating an enumeration in Java. As ofJava
5.0 you can create full fledged enumerations that will be the envy of all your
pre:Java 5.0-using friends.

Who's in the band?

Let's say that you 're creating a website for your favorite band, and you want to
make sure that all of the comments are directed to a particular band member.

The old way to fake an "enum":

public static final int JERRY = 1;


public static final int BOBBY = 2 ;
public static final int PHIL = 3;

I I later in the code We're h . Lh L b Lh L "


~ °flll~;; a;; y;; e ;;'l'WIe we ~ot here
if (sele ctedBandMember == JERRY) {
s
" det te dBalldMel'Wlber" has a valid val"t.!
II do JERRY related stuff

The good news about this technique is that it DOES make the code easier to
read. The other good news is that you can't ever change the value of the fake
enums you've created; JERRY will always be 1. The bad news is that there's
no easy or good way to make sure that the value of selectedBandMember
will always be 1, 2, or 3. If some hard to find piece of code sets
selectedBandMember equal to 812, it's pretty likely your code will break.. .

you are he re ~ 671


when arrays aren't enough

#1 Enumerations, cont.
The same situation using a genuine Java 5.0 enum. While this is a very basic
enumeration, most enumerations usually are this simple.

A new, official "enum":


~
public enum Members { JERRY, BOBBY, PHIL };
public

Your enum extends java.lang.Enum


When you create an enum, you're creating a new class, and you're implicitly extending
java . lang . Enum. You can declare an enum as its own standalone class, in its own
source file, or as a member of another class.

Using "if" and "switch" with Enums


Using the enum we just created, we can perform branches in our code using either
the if or swi tch statement. Also notice that we can compare enum instances using
either == or the . equa ls () method. Usually == is considered better style.

______ Assi~r.ir.~ ar. er.1mI yal~ to a variable,


Members n = Members.BOBBY; ~
if (n .equals(Members.JERRY)) System. out.println("Jerrrry!"); I. r, el
if (n == Members.BOBBY) System.out.println("Rat Dog"); "--- ~o-\:)l J t"'e$e '"
0'(" """ ,

""$ ,"",,-\:,ed,
Members ifName = Members.PHIL;
"Rat D~
switch (ifName) {
case JERRY: System.ou t.print("make it sing ");
case PHIL: System. o ut.print("go deep ") ;
case BOBBY: System.out.println("Cassidy! ");

672 appendix 8
enumerations appendix B Top Ten Reference

#1 Enumerations, completed
A really tricked-out version of a similar enum
You can add a bunch of things to your enum like a constructor, methods.
variables, and something called a constant-specific class body. They're
not common, but you might run into them:
L sstO il'\ -\:p
public class HfjEnum ( ay~"",el'\1:. ~a L.\
________ nils is a~\Il.~ oeda.... td ~ o'Wl·
enum Names ( ~__ L.' • _ ~~_ . ~e ~Q'I\S th $O-t.llleo
JERRi' ("lead guitar) { public String sings () { ~ Tkese a....e e ok' dau bodies".
return "plaintively";} ; / "~Ylt.-s?etl It o . -th
} J Think ~ t.he'" as O"t:rt"IO.ln~ e
o
BOBBY ("rhythm guitar") ( public String s i nqs () I
LLod (iYl -thIS t,4St
\)asit eYl......... n.n r oO .
return "hoarsely"; ) the "S'IYI~O)l ""et.hcxl), iot S,,\~ IS
), t.llleo 0" a lIayid'ole ...ith aYl en--
PHIL ("bass") ;
lIaIv.t o-tr J~RRY ~ BOBBY·
private String instrument;

Names(String instrument) ( ~~-- This is -the tr>lAM'S toYlShvttm-. It. ruYlS


this. instrument = instrument; OWIU +t*'
e6th detla.. . ed eYllAM I/al~ (iYl
) t.his ~ it. . . "'W\.\ t.hree tiMes)o
public String getlnstrument{)
return this. instrument;
)
public String sings () (
return "occasionally";

public static void main(String [] args) (0 ___________


for (Names n : Names.values(») ( ~
System.aut.print<n);
System.out.prin~(", instrument: "+ n.getlnstrument<)):
System.aut.println(", sings: " + n.sings());

%java HfjEnum
Not.itt that the ba.sit Usi,,~())
JERRY, i n s t r ume n t : lead guitar, sings: plaintively
BOBBY , instrument : rhythm guitar, sings : hoarsely ""et.hod is oYlly lJlled wheYl the
PHIL, instrument: bass , sings: occasionally e"w.- I/al~ has 110 tOPl.Sta7lt-
% speti.fit tlas.s body.

you are here . 673


when arrays aren't enough

A Long Trip Home

Captain Byte of the Flatland starship "Traverser" had received an urgent, Top Secret transmission
from headquarters. The message contained 30 heavily encrypted navigational codes that the
Traverser would need to successfully plot a course home through enemy sectors. The enemy
Hackarians, from a neighboring galaxy, had devised a devilish code-scrambling ray that was capable
of creating bogus objects on the heap of the Traverser's only navigational computer. In
addition, the alien ray could alter valid reference variables so that they referred to these
bogus objects . The only defense the Traverser crew had against this evil Hackarian ray was
to run an inline virus checker which could be imbedded into the Traverser's state of the art
Java 1.4 code.

Captain Byte gave Ensign Smith the following programming instructions to process the critical
navigational codes:

"Put the first five codes in an array of type ParsecKey. Put the last 25 codes in a five by fi ve, two
dimensional array of type QuadmntKey. Pass these two arrays into the plolCourseO method of the
public final class Shipblavigation. Once the course object is returned run the inline virus checker
against all the programs reference variables and then run the NavSim program and bring me the
results."

A few minutes later Ensign Smith returned with the NavSim output. "NavSim output ready for
review, sir", declared Ensign Smith. "Fine", replied the Captain. "Please review your work". "Yes
sir!", responded the Ensign, "First I declared and constructed an array of type ParsecKey with the
following code ; ParsecKey 0 p = new ParsecKey[5]; , next 1 declared and constructed an array
of type QuadrantKey with the following code: QuadrantKey 0 0 q = new QuadrantKey [5] [5]; .
Next, I loaded the first 5 codes into the ParsecKey array using a 'for' loop, and then I loaded the last
25 codes into the Quadrantkey,array using nested 'for'{oops, Next, I ran the virus checker against
all 32 reference variables, I for the ParsecKey array, and 5 for its elements, I for the QuadrantKey
array. and 25 for its elements. Once the virus check returned with no viruses detected, I ran the
NavSim program and re-ran the virus checker, just to be safe... Sir!"

Captain Byte gave the Ensign a cool , long stare and said calmly, "Ensign, you are confined to
quarters for endangering the safety oftbis ship, I don't want to see your face on this bridge again
until you have properly learned your Java! Lieutenant Boolean, take over for the Ensign and do this
job correctly!"

Why did the captain confine the Ensign to his quarters?


674 appendix B
A Long Trip Home
Captain Byte knew that in Java, multidimensional arrays are actu-
ally arrays of arrays. The five by five QuadrantKey array ' g' , would
actually need a total of31 reference variables to be able to access
all of its components:

I - reference variable for 'q'

5 - reference variables for q [0) - q [4J

25 - reference variables for q [0] [0] - q [4] [4]

The ensign had forgotten the reference variables for the five one
dimensional arrays embedded in the 'q' array. Any of those five
reference variables could have been corrupted by the Hackarian
ray, and the ensign's test would never reveal the problem .

you are here ~ 675


This isn't goodbye
Bring your brain over to
wickedlysmart.com

You might also like