Think Java

How to Think Like a Computer Scientist


Think Java
How to Think Like a Computer Scientist

Allen B. Downey

Version 5.0

Copyright c 2011 Allen Downey.

Permission is granted to copy, distribute, transmit and adapt this work under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License: If you are interested in distributing a commercial version of this work, please contact Allen B. Downey.
A A The original form of this book is L TEX source code. Compiling this L TEX source has the effect of generating a device-independent representation of the book, which can be converted to other formats and printed. A The L TEX source for this book is available from
A This book was typeset using L TEX. The illustrations were drawn in xfig. All of these are free, open-source programs.

and that obscured the material I really wanted to get to. In other words. we should be glad of an Opportunity to serve others by any Invention of ours. Morgan. I had taught an introductory computer science class using the Java programming language. I wrote a chapter a day for 13 days.Preface “As we enjoy great Advantages from the Inventions of others. to define them carefully when they are first used. I told the students that they would be expected to read one chapter a week. Then I sent it to be photocopied and bound. I try to introduce the minimum number of terms. Why I wrote this book This is the fifth edition of a book I started writing in 1999. but I had not found a textbook I was happy with. and on the 14th day I edited. And I didn’t want them to. Many students who were otherwise doing well just hit a wall when we got to objects. So I started writing. whether we did it at the beginning. when I was teaching at Colby College. quoted in Benjamin Franklin by Edmund S. they would read it seven times slower than I wrote it. and this we should do freely and generously. The other problem I found was that the introduction to object oriented programming was too abrupt. and to organize . The philosophy behind it Here are some of the ideas that make the book the way it is: • Vocabulary is important. they were all too big! There was no way my students would read 800 pages of dense. For one thing.” —Benjamin Franklin. technical material. even if I wanted them to. When I handed it out on the first day of class. middle or end. Most of the material was too specific—details about Java and its libraries that would be obsolete by the end of the semester. Students need to be able to talk about programs and understand what I am saying.

sound and network applications. and many of the exercises involve string manipulation and mathematical ideas. that are unnecessary. I include vocabulary questions on quizzes and exams. Object-oriented programming Some books introduce objects immediately. I recommend that students read this material early and come back to it often. I think too many books neglect debugging. and they have to be able to debug. The problem is that many of the more exciting features involve lots of details and not much concept. like recursion. • Some concepts take time to sink in. Some of the more difficult ideas in the book. Pedagogically. like the switch statement. like graphics. In my class. and additional topics that aren’t in the book. and I have found that they are willing to do that and their comprehension is good. The purpose of this book is to teach programming and some introductory ideas from computer science. I think some of them are fun. There is not much here that is intrinsically fun. Each chapter is about ten pages. students have to understand the algorithm. But minimalism has some Preface them in glossaries at the end of each chapter. Most of my examples demonstrate the most basic use of a language feature. • I try to use the minimum amount of Java to get the maximum amount of programming power. a chance to catch up. that means a lot of effort for not much payoff. in-class exercises. but many of the things that excite students about computer science. I am trying to give students a chance to review and reinforce or. • In order to write a program. and require students to use appropriate terms in short-answer responses. I left out some language features. especially the ones like the AWT that have been changing quickly or are likely to be replaced. and avoided most of the libraries. others warm up with a more procedural style and develop object-oriented style more gradually. if they missed it the first time. I leave it to individual teachers to find the balance that is best for their classes. In my classes I ask students to read each chapter before we discuss it. appear several times. This book is probably the extreme of the “objects late” approach. . the book includes appendices that cover graphics. So there is a tradeoff between the material that students enjoy and the material that is most intellectually rich. know the programming language. The minimalism of my approach has some advantages. By coming back to these ideas. keyboard input and file input. This book includes an appendix on debugging and an appendix on program development (which can help avoid debugging). Their preparation makes class time available for discussion of the more abstract material. not including the exercises. To help. are given short shrift. not Java.

On the contrary. • I added a few sections to improve coverage of the AP syllabus. the material I covered was almost identical to the AP Syllabus. Looking at the proposed AP Syllabus. It just happens that it takes 13 steps. I got to it as quickly as I could. when the College Board announced that the AP Exam would switch to Java. • I improved the appendices on debugging and program development. Naturally. I saw that their subset of Java was all but identical to the subset I had chosen. It wasn’t my intention to postpone object-oriented programming. The Computer Science AP Exam During Summer 2001 I worked with teachers at the Maine School of Science and Mathematics on a version of the book that would help students prepare for the Computer Science Advanced Placement Exam. • I collected the exercises. limited by my intention to introduce concepts one at a time. I also made up some problems that are intended to help with AP Exam preparation. Teachers are free to send the book to a short-run printer and make as many copies as they need. • I revised several sections that I had found problematic. Free books! Since the beginning. this book and its descendents have been available under licenses that allow users to copy. maybe most importantly. and exam questions I had used in my classes and put them at the end of the appropriate chapters. distribute and modify the book. making these changes: • I added a new chapter covering Huffman codes. You can download the L TEX source code. And. The translation went quickly because. and then .vii Many of Java’s object-oriented features are motivated by problems with previous languages. I made plans to update the Java version of the book. including the transition to object-oriented programming and the discussion of heaps. Readers can download the book in a variety of formats and print it or read it on screen. I worked on the Fourth Edition of the book. quizzes. in a way that allows students to practice each idea in isolation before adding the next. During January 2003. and their implementations are influenced by this history. anyone is free to customize A the book for their needs. as clearly as possible. Some of these features are hard to explain if students aren’t familiar with the problems they solve. as it turned out. which used C++ at the time.

Allen Downey Needham. and probably a few more classes. If it is successful. and she gave me a whole stack of corrections. I do my best to minimize the number of errors. Massachusetts July 13. I have adopted the philosophy of releasing the book early and updating it often. edit. Many of these derivatives are also available under free licenses. This approach to publishing has a lot of advantages. versatile and powerful. 2011 Contributors List When I started writing free books. it seemed so obvious that I am embarassed by the omission. it didn’t occur to me to keep a contributors list. or when readers take the time to send feedback. so it omits many people who contributed suggestions and corrections to earlier versions. along with some great suggestions.viii Preface add. • Ellen Hildreth used this book to teach Data Structures at Wellesley College. Not everyone understands that it is—mostly—a joke. Oh. improving a little whenever I have time to make a revision. and that at some point you will find yourself thinking like a computer scientist. When Jeff Elkner suggested it. But there is a kernel of truth in the title: this book is not about Java.” Often I can correct an error and post an updated version almost immediately. I think of the book as a work in progress. the title I get a lot of grief about the title of the book. but there is one drawback: my books have never been through a formal editing and proofreading process and sometimes it shows. and it is only partly about programming. I hope that this book gives you a sense of what that approach is. French and German). but I also depend on readers to help out. or rearrange material. Reading this book will probably not make you think like a computer scientist. . and make the book that is best for you or your class. remove. Computer scientists have an approach to problem-solving. that is unique. experience. this book is about a way of thinking. That takes time. The response has been great. and a way of crafting solutions. Motivated by Open Source Software. People have translated the book into other computer languages (including Python and Eiffel). I get messages almost every day from people who have read the book and liked it enough to take the trouble to send in a “bug report. This list starts with the 4th Edition. and other natural languages (including Spanish.

• Doan Thanh Nam corrected an example in Chapter 3. She is also working on a Ruby version of the book! • Matt Crawford sent in a whole patch file full of corrections! • Chi-Yu Li pointed out a typo and an error in one of the code examples. • Elizabeth Wiethoff noticed that my series expansion of e−x was wrong.ix • Tania Passfield pointed out that the glossary of Chapter 4 has some leftover terms that no longer appear in the text. 2 .

x Preface .

. . . . . . . . . . . . . Variables . . . . . . . . . . . . . . .2 2. . . . . . . . . . . . . Operators for Strings .5 2. . . . . . . . . . . . . . . . . . .11 More printing . Glossary . . . . . . . . . . . . . . . . . . . . . . . .7 What is a programming language? . . . . . . . . . . . . . . . . . . . .7 2. . . . . . . . . . . . . . . . Exercises . . . . . . . . . . . Assignment . . . . . Glossary . . .4 1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercises . . . . . .9 2. . . . . . . . . . . . . . . . . . . . Operators . . . . . . . . . . . . What is debugging? . . .3 2.Contents Preface 1 The way of the program 1. . . . . . . 2 Variables and types 2. . . . . . . . . . . Printing variables . . . . . . . . . . Order of operations . . .6 1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Composition . . . . . . . . .1 2. . . .6 2. . . . . . . . . . . . . . . . . . . . . . . . What is a program? . . . .2 1. . . . . . . . . . . . . The first program . . . . . . . . .8 2. . . .3 1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Keywords . . v 1 1 3 3 5 6 7 9 11 11 12 13 14 14 15 16 16 17 17 18 Formal and natural languages . . . . . . . . . . . . . . . . . . . . . .4 2. . .1 1. . . . . . . . . . . . . . . . . . . . . . . . . .5 1. . . . . . .10 2. .

. . . . . . . . . . .2 3. . . . . . . . . .8 3. . . . . . . . . . . Composition . Converting from double to int . . . . . .10 3. . . . . . .5 4. Nested conditionals . . . . . . . . . . . . . . . . . . 4 Conditionals and recursion 4. . .xii 3 Methods 3. . . . . . . . . . . .7 3. . The return statement .2 4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9 3. . . . . . .1 3. . . . . . . . . . . . . . . . Exercises . . . . . . . . Math methods . . . . . Programs with multiple methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Chained conditionals . . . . . . . . . . . . .6 4. . . . . .13 Contents 21 21 22 23 23 24 26 27 27 29 29 30 30 31 33 33 33 34 35 35 36 36 36 38 39 39 43 43 44 Floating-point . . 5 GridWorld: Part One 5.1 4. . . . . . . .9 4. . . . . . . . . . . BugRunner . . .8 4. Classes and methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Methods with results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Conditional execution . . . . Type conversion . . . . . . . .10 4. . . . . . .2 Getting started . . . Adding new methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5 3. . . Parameters and arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . .4 3. . . . . . . . . .7 4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Recursion . . . . . . . . . . . Glossary . . . . . . . . . . . . . . . . . Methods with multiple parameters . . . .11 The modulus operator . . . . . . . . . . . . . . . . Stack diagrams for recursive methods . . . . . . . . . . . . . . . Alternative execution . . . . . . Stack diagrams . . . . . . . . . . . . . Glossary . . . . . . . . . . . . . . . . .6 3. .1 5. . . . . . . . . . . . . . .11 3. . . . . . . .4 4.12 3. . . . .3 3. . . . . . . . . Exercises . . . . . . . . . . .3 4. . . . . . . .

.9 6. . . . The while statement . . . . . .2 7. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Leap of faith . . . . .11 6. . . . .3 7. . . . . . . . . . . . . . . . . . . One more example . . . . . . . . . . . . . . . More recursion . . . . . . . . . . . . . . . .10 6. . . . . . . . . . . . . . . . . . . . . .2 6. . . . . . . . Glossary . . . . . . . . . . . . . . . . . . Boolean methods . . . . . . . . . . . . . . . . . . .4 7. . . . . . . . . . . . . . . . . . . . . . .10 7. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8 7. . . . . .5 6. . . . . . . . . . . . . . . . . . . .9 7. . . . . . . . . 7 Iteration 7. . . . . . . . . . . . . Iteration . . . . .6 6.Contents 6 Fruitful methods 6. . . . . . . . Program development . .1 7. . Two-dimensional tables . . . . Overloading . . . . . . Tables . . .12 Multiple assignment . . . . . .11 7. . . . . . . . . More encapsulation . . . . . . . . . . . . . . . . . . . . . . . . Boolean expressions . . . . . . . . More generalization . . . . . . . . . . . . . . .4 6. .5 7. . . . . . . . . . . . . . . . . . . . Exercises . . .8 6. . . . . . . . . . . . . . . . . . . . . . . . . Local variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6 7. . . . . .1 6. . . . . .12 Return values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Encapsulation and generalization . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii 47 47 48 51 51 52 53 53 54 56 57 57 58 63 63 64 64 65 67 68 69 69 70 70 72 72 Logical operators . . . . . . . Methods . . . . . . . .7 6. . . Exercises . . .7 7. . . . . . . . . . . . . . . . . . . . . . . . . Composition . . . . . . . . .3 6. . . . . . . . Glossary . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . Looping and counting . .7 8. . . . . . . . . . . . Strings are incomparable . . . . . . . . . . . . . . . . . . . . . . Length . . . . . . . . . . . . . Rectangles . . . . . . Garbage collection . . . . .12 9. . . . . . . . . . . . . . . . . .3 8. . . . . . . . . . . . . . . . . . . . . .14 Points and Rectangles . . . . . . . . . . . . . . . . .6 8. . . Exercises . .9 9. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 9. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 8. . . Glossary . . . . . . Objects and primitives . . . . . . . . .8 8. . . . . . . . . . . . . . . . . . .10 9. . .2 9. . . . . . . . . . . . . . . . . . Strings are immutable . . Run-time errors . . . . . .2 8. . . . . . .4 9. . . . . . . 9 Mutable objects 9. . .8 9. . . . . . . . . .4 8. . . . . . . . . . . . . . .6 9.3 9. . . . . . . . . . . . . . . . . . . . .11 8. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .12 Contents 75 75 76 76 77 77 78 79 79 80 80 81 82 87 87 87 88 88 89 89 90 90 91 92 93 93 94 94 Invoking methods on objects .10 8. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .11 9. . . . . . . . . . . . . . . Increment and decrement operators . . .9 8. . . . The indexOf method . . . Instance variables . . . . . . . . . . . . . . . . . . . . . . . . . . . Aliasing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Reading documentation . Objects as return types . . . . . . . . . . Glossary . . . . . . . . . . . . . . . Objects are mutable . . . . . . . . . . . . . . . .xiv 8 Strings and things 8. . . . . . . . . . . . . . . .7 9. . . . . . . . . . . . .5 9. . Packages . . . . Exercises . . . null . . . . . . . . . . . . . . . . . Point objects . . . . . . . . . . . . . . . . . . . . . . . . . . .13 9. . . . . . . . . .5 8. . . . . . . . . . . . . . . . . . . . . Traversal . . . . . . . . . . . . . . . . . . . . . . . . . . Objects as parameters .

Contents 10 GridWorld: Part 2 10.1 10.2

xv 99

Termites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 Langton’s Termite . . . . . . . . . . . . . . . . . . . . . . . . . 103 105

11 Create your own objects 11.1 11.2 11.3 11.4 11.5 11.6 11.7 11.8 11.9

Class definitions and object types . . . . . . . . . . . . . . . . . 105 Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107

More constructors . . . . . . . . . . . . . . . . . . . . . . . . . . 107 Creating a new object . . . . . . . . . . . . . . . . . . . . . . . 108 Printing an object . . . . . . . . . . . . . . . . . . . . . . . . . 109 Operations on objects . . . . . . . . . . . . . . . . . . . . . . . 110 Pure functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 Modifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112

11.10 Fill-in methods . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 11.11 Which is best? . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 11.12 Incremental development vs. planning . . . . . . . . . . . . . . 113 11.13 Generalization . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 11.14 Algorithms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 11.15 Glossary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 11.16 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 12 Arrays 12.1 12.2 12.3 12.4 12.5 12.6 12.7 12.8 121

Accessing elements . . . . . . . . . . . . . . . . . . . . . . . . . 121 Copying arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 for loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 Arrays and objects . . . . . . . . . . . . . . . . . . . . . . . . . 124 Array length . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 Random numbers . . . . . . . . . . . . . . . . . . . . . . . . . . 125 Array of random numbers . . . . . . . . . . . . . . . . . . . . . 125 Counting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126

xvi 12.9 The histogram

Contents . . . . . . . . . . . . . . . . . . . . . . . . . . . 127

12.10 A single-pass solution . . . . . . . . . . . . . . . . . . . . . . . . 128 12.11 Glossary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 12.12 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 13 Arrays of Objects 13.1 13.2 13.3 13.4 13.5 13.6 13.7 13.8 13.9 133

Composition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 Card objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 The printCard method . . . . . . . . . . . . . . . . . . . . . . 134 The sameCard method . . . . . . . . . . . . . . . . . . . . . . . 136 The compareCard method . . . . . . . . . . . . . . . . . . . . . 137 Arrays of cards . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 The printDeck method . . . . . . . . . . . . . . . . . . . . . . 139 Searching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 Decks and subdecks . . . . . . . . . . . . . . . . . . . . . . . . . 143

13.10 Glossary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 13.11 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 14 Objects of Arrays 14.1 14.2 14.3 14.4 14.5 14.6 14.7 14.8 145

The Deck class . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 Shuffling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 Sorting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147 Subdecks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 Shuffling and dealing . . . . . . . . . . . . . . . . . . . . . . . . 149 Mergesort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 Glossary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151

Contents 15 Object-oriented programming 15.1 15.2 15.3 15.4 15.5 15.6 15.7 15.8 15.9

xvii 155

Programming languages and styles . . . . . . . . . . . . . . . . 155 Object and class methods . . . . . . . . . . . . . . . . . . . . . 156 The current object . . . . . . . . . . . . . . . . . . . . . . . . . 156 Complex numbers . . . . . . . . . . . . . . . . . . . . . . . . . . 156 A function on Complex numbers . . . . . . . . . . . . . . . . . . 157 Another function on Complex numbers . . . . . . . . . . . . . . 158 A modifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 The toString method . . . . . . . . . . . . . . . . . . . . . . . 159 The equals method . . . . . . . . . . . . . . . . . . . . . . . . 159

15.10 Invoking one object method from another . . . . . . . . . . . . 160 15.11 Oddities and errors . . . . . . . . . . . . . . . . . . . . . . . . . 161 15.12 Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 15.13 Drawable rectangles . . . . . . . . . . . . . . . . . . . . . . . . 162 15.14 The class hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . 163 15.15 Object-oriented design . . . . . . . . . . . . . . . . . . . . . . . 163 15.16 Glossary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 15.17 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164 A Program development plan B Debugging B.1 B.2 B.3 165 171

Syntax errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 Run-time errors . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 Semantic errors . . . . . . . . . . . . . . . . . . . . . . . . . . . 177 183 185

C Input and Output in Java D Graphics D.1 D.2 D.3 D.4 D.5

Java 2D Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . 185 Graphics methods . . . . . . . . . . . . . . . . . . . . . . . . . 186 Coordinates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 Color . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 Mickey Mouse . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187



computer scientists use formal languages to denote ideas (specifically computations).” On one level. and test predictions. As we go along. and express a solution clearly and accurately. and Natural Science. 1. The single most important skill for a computer scientist is problem-solving. I like the way computer scientists think because they combine some of the best features of Mathematics. and Perl. which is relatively new (Sun released the first version in May. you will be learning to program.” there are also lowlevel languages. By that I mean the ability to formulate problems. assembling components into systems and evaluating tradeoffs among alternatives. Thus.1 What is a programming language? The programming language you will be learning is Java. 1995). programs written in a high-level language have to be translated before they can run. . Like scientists.Chapter 1 The way of the program The goal of this book is to teach you to think like a computer scientist. think creatively about solutions. Loosely-speaking. they design things. computers can only run programs written in low-level languages. As it turns out. That’s why this chapter is called “The way of the program. Like engineers. sometimes called machine language or assembly language. they observe the behavior of complex systems. form hypotheses. As you might infer from the name “high-level language. other high-level languages you might have heard of are Python. which is a useful skill by itself. the process of learning to program is an excellent opportunity to practice problem-solving skills. which is a small disadvantage of high-level languages. Engineering. This translation takes time. that end will become clearer. On another level you will use programming as a means to an end. Like mathematicians. Java is an example of a high-level language. C or C++.

like a high-level language. it’s shorter and easier to read. in most program development environments these steps are automated for you. and generates Java byte code. it translates the program line-by-line. Usually you will only have to write a program and press a button or type a single command to compile and run it.class interpreter . the high-level program is called the source code.. compiler byte code x. before running any of the commands. and the translated program is called the object code or the executable. and the result appears on the The compiler reads the source code. On the other hand. Low-level languages are only used for a few special applications. A compiler is a program that reads a high-level program and translates it all at once. source code x. alternately reading lines and carrying out commands. like machine language. Although this process may seem complicated. so if something goes wrong you can figure out what it is.. In effect. interpreting and compiling. the Java compiler generates Java byte code. The Java language is unusual because it is both compiled and interpreted...2 The way of the program The advantages are enormous. In this case. Instead of translating Java programs into machine language.. almost all programs are written in high-level languages. Due to these advantages. First.. it is much easier to program in a highlevel language: the program takes less time to write. high-level languages are portable. Second. meaning that they can run on different kinds of computers with few or no modifications. transfer the byte code to another machine. There are two ways to translate a program. it is possible to compile a Java program on one machine.. and then interpret the byte code on the other machine.. Often you compile the program as a separate step. . A Java interpreter reads the byte code. This ability is an advantage of Java over many other high-level languages. and it’s more likely to be correct. and have to be rewritten to run on another. it is useful to know what steps are happening in the background. Low-level programs can only run on one kind of computer. but it is also portable. and then run the compiled code later. . An interpreter is a program that reads a high-level program and does what it says. Thus. Byte code is easy (and fast) to interpret.

1. which we will call statements. For example. or some other device. So does this one 1 This definition does not apply to all programming languages. Every program you’ve ever used. output: Display data on the screen or send data to a file or other device. is made up of statements that perform these operations. in English. . look different in different programming languages. a sentence must begin with a capital letter and end with a period. usually with some variation.1 Syntax errors The compiler can only translate a program if the program is syntactically correct. but it can also be a symbolic computation. That’s pretty much all there is to it.3. for alternatives. The computation might be something mathematical. Thus. no matter how complicated. testing: Check for certain conditions and run the appropriate sequence of statements. complex task up into smaller and smaller subtasks until the subtasks are simple enough to be performed with one of these basic operations. this sentence contains a syntax error.wikipedia.1. the compilation fails and you will not be able to run your program. 1. otherwise. like searching and replacing text in a document or (strangely enough) compiling a program.2 What is a program? A program is a sequence of instructions that specifies how to perform a computation1 . and it is useful to distinguish them to track them down more quickly. like solving a system of equations or finding the roots of a polynomial. The instructions. one way to describe programming is the process of breaking a large. or a file. Syntax refers to the structure of your program and the rules about that structure. see http: //en. programming errors are called bugs and the process of tracking them down and correcting them is called debugging.2 What is a program? 3 1. There are a three kinds of errors that can occur in a program. but there are a few basic operations most languages perform: input: Get data from the What is debugging? For whimsical reasons. math: Perform basic mathematical operations like addition and multiplication. repetition: Perform some action repeatedly.

3. In Java. especially for simple programs. Debugging is like detective work. the compiler will print an error message and quit. . run-time errors occur when the interpreter is running the byte code and something goes wrong. To make matters worse. which means that the compiler catches a lot of errors. As you gain experience. you will make fewer errors and find them faster. but it will not do the right thing. and in most environments they appear as windows or dialog boxes that contain information about what happened and what the program was doing when it happened. Compilers are not so forgiving.4 The way of the program For most readers. The semantics. Java tends to be a safe language. a few syntax errors are not a significant problem. are wrong. It will do something else. which is why we can read the poetry of e e cummings without spewing error messages. you will probably spend a lot of time tracking down syntax errors. The problem is that the program you wrote is not the program you wanted to write. it will compile and run without generating error messages. so-called because the error does not appear until you run the program. Identifying logic errors can be tricky because you have to work backwards.3. it will do what you told it to do. If there is a logic error in your program. In Java.2 Run-time errors The second type of error is a run-time error.3 Logic errors and semantics The third type of error is the logic or semantic error. and valuable parts of programming. or meaning of the program. challenging. and the error messages you get from the compiler are often not very helpful. run-time errors are called exceptions. During the first weeks of your programming career.3. So run-time errors are rare.4 Experimental debugging One of the most important skills you will acquire in this class is debugging. it is one of the most interesting. You are confronted with clues and you have to infer the processes and events that lead to the results you see. Specifically. If there is a single syntax error anywhere in your program. This information is useful for debugging. and you will not be able to run your program. there are more syntax rules in Java than there are in English. looking at the output of the program and trying to figure out what it is doing. 1. 1. 1. Although debugging can be frustrating.

however improbable. 2 Zz is not legal because there is no element with the abbreviation Zz. For example. In later chapters I will make more suggestions about debugging and other programming practices. “When you have eliminated the impossible. The idea is that you should always start with a working program that does something. you have to come up with a new one. If your hypothesis was wrong. that is. but 2 Zz is not. H2 O is a syntactically correct chemical name. Chemists use a formal language to represent the chemical structure of molecules. Formal languages are languages designed by people for specific applications. Linux is an operating system that contains thousands of lines of code. Also. Conan Doyle’s The Sign of Four). you modify your program and try again. They were not designed by people (although people try to impose order on them). “One of Linus’s earlier projects was a program that would switch between printing AAAA and BBBB. but it started out as a simple program Linus Torvalds used to explore the Intel 80386 chip. 1. debugging them as you go. and French.4 Formal and natural languages 5 Debugging is also like an experimental science. Syntax rules come in two flavors.1.4 Formal and natural languages Natural languages are the languages that people speak. the notation that mathematicians use is a formal language that is particularly good at denoting relationships among numbers and symbols. For example. programming is the process of gradually debugging a program until it does what you want. like English. programming and debugging are the same thing. Tokens are the basic elements of the language. whatever remains. Formal languages have strict rules about syntax. Spanish. pertaining to tokens and structure. For some people. . One of the problems with 3$ = is that $ is not a legal token in mathematics (at least as far as I know). and make small modifications. and you take a step closer to a working program. According to Larry Greenfield. but 3$ = is not. so that you always have a working program. That is. like words and numbers and chemical elements. they evolved naturally. If your hypothesis was correct. As Sherlock Holmes pointed out. This later evolved to Linux” (from The Linux Users’ Guide Beta Version 1). then you can predict the result of the modification. The statement 3$ = is structurally illegal. the way the tokens are arranged. Once you have an idea what is going wrong. 3 + 3 = 6 is a syntactically correct mathematical statement. Similarly.” (from A. The second type of syntax rule pertains to the structure of a statement. And most importantly: Programming languages are formal languages that have been designed to express computations. For example. must be the truth.

1. Formal languages mean exactly what they say. Formal languages are more concise. Similarly. identifying the tokens and interpreting the structure. syntax and semantics—there are differences. When you read a sentence in English or a statement in a formal language. remember that the details matter. First. and can be understood entirely by analysis of the tokens and structure. Prose: The literal meaning of words is more important and the structure contributes more meaning. left to right. redundancy: To make up for ambiguity and reduce misunderstandings. People who grow up speaking a natural language (everyone) often have a hard time adjusting to formal languages. and the whole poem together creates an effect or emotional response. the structure is important. this program looks like this: . natural languages are often redundant. can make a big difference in a formal language. This process is called parsing. Formal languages are designed to be unambiguous. remember that formal languages are much more dense than natural languages. which people deal with by using contextual clues and other information. which means that any statement has exactly one meaning. but more so: Poetry: Words are used for their sounds as well as for their meaning. structure. which you can get away with in natural languages. Here are some suggestions for reading programs (and other formal languages). Programs: The meaning of a computer program is unambiguous and literal. Although formal and natural languages have features in common—tokens. molecular formulas have to have subscripts after the element name. Finally. World. World. Instead. Little things like spelling errors and bad punctuation. literalness: Natural languages are full of idiom and metaphor. ambiguity: Natural languages are full of ambiguity. not before. learn to parse the program in your head. Ambiguity is common and deliberate. In some ways the difference between formal and natural language is like the difference between poetry and prose.” In Java. so it takes longer to read them.6 The way of the program because you can’t have an equals sign at the end of an equation. regardless of context. Also. you have to figure out what the structure of the sentence is (although in a natural language you do this unconsciously).5 The first program Traditionally the first program people write in a new language is called “Hello.” because all it does is display the words “Hello. so it is usually not a good idea to read from top to bottom.

we’ll do all our printing on the screen. When the program runs. it marks the place in the program where execution begins. which have the form: class CLASSNAME { public static void main (String[] args) { STATEMENTS } } Here CLASSNAME indicates a name chosen by the programmer. The outermost squiggly-braces (lines 1 and 8) contain the class definition.println is a method provided by one of Java’s libraries. meaning that it displays a message on the screen. main can have any number of statements. and expressing the solution. When the compiler sees //.).out. and the inner braces contain the definition of main. The print statement ends with a semi-colon (.6 Glossary class Hello { // main: generate some simple output public static void main(String[] args) { System.” In this book I won’t say much about sending things to the printer. it ignores everything from there until the end of the line. Confusingly. } } 7 This program includes features that are hard to explain to beginners.").6 Glossary problem-solving: The process of formulating a problem. which is a named collection of statements. System.” or “send something to the printer. 1. finding a solution. “print” can mean “display something on the screen. It is a print statement. which is a bit of English text that you can put a program. usually to explain what it does. A library is a collection of class and method definitions. Java uses squiggly-braces ({ and }) to group things together. it starts at the first statement in main and ends when it finishes the last statement. main is a method. but the example has one.println("Hello.1. Line 3 begins with //. Java programs are made up of class definitions. but it provides a preview of topics we will see in detail later. The class name in the example is Hello. world. That means it’s a comment.out. . The name main is special.

syntax error: An error in a program that makes it impossible to parse (and therefore impossible to compile). . portability: A property of a program that can run on more than one kind of computer. low-level language: A programming language that is designed to be easy for a computer to run. compile: To translate a program in a high-level language into a low-level language. before being compiled. but it is portable. Also called “machine language” or “assembly language. but that has no effect when the program runs. source code: A program in a high-level language. like a high-level language.8 The way of the program high-level language: A programming language like Java that is designed to be easy for humans to read and write. syntax: The structure of a program. after translating the program. semantics: The meaning of a program. executable: Another name for object code that is ready to run. bug: An error in a program. parse: To examine a program and analyze the syntactic structure. interpret: To run a program in a high-level language by translating it one line at a time. object code: The output of the compiler. All programming languages are formal languages. like representing mathematical ideas or computer programs. print statement: A statement that causes output to be displayed on the screen. byte code: A special kind of object code used for Java programs. Byte code is similar to a low-level language.” formal language: Any of the languages people have designed for specific purposes. statement: A part of a program that specifies a computation. comment: A part of a program that contains information about the program. in preparation for later execution. method: A named collection of statements. library: A collection of class and method definitions. natural language: Any of the languages people speak that have evolved naturally. all at once.

a. When you see familiar words. For example.1.7 Exercises 9 exception: An error in a program that makes it fail at run-time. The new comment should not affect the result. recompile. what’s the difference between a statement and a comment? b. “How are you?” Compile and run the program again. world!”. Add a comment to the program (anywhere). debugging: The process of finding and removing any of the three kinds of errors. The glossary at the end of each chapter is intended to highlight words and phrases that have special meanings in computer science. and you might find yourself trying to debug one program while you are accidentally running another.2 Before you do anything else. but it is the starting place for many of the programs we will work with. Some environments provide sample programs similar to the example in Section 1.7 Exercises Exercise 1. find out how to compile and run a Java program in your environment. in English. Adding (and changing) print statements is a simple way to be sure that the program you are looking at is the program you are running. but in programs they are different. Exercise 1. world” program. statements and comments are the same thing. don’t assume that you know what they mean! a. Something witty like. and run it again. What does it mean to say that a program is portable? c. In computer jargon. b. logic error: An error in a program that makes it do something other than what the programmer intended.1 Computer scientists have the annoying habit of using common English words to mean something different from their common English meaning.5. Add a print statement that prints a second message after the “Hello. 1. you have to have confidence in your programming environment. This exercise may seem trivial. In order to debug with confidence. Type in the “Hello. Sometimes the compiler tells you exactly what .3 It is a good idea to commit as many errors as you can think of. c. Also called a run-time error. then compile and run it. so that you see what error messages the compiler produces. What is an executable? Exercise 1. In some environments. it is easy to lose track of which program is executing.

Remove the word static.print is legal. Instead of main. Remove one of the open squiggly-braces. Add an extra one. Replace println with print. a. This one is tricky because it is a logic error.out. not a syntax error. But sometimes the error messages are misleading. b. . The statement System. Delete one of the parentheses. Remove one of the close squiggly-braces. Replace println with Println. h. but it may or may not do what you expect. c.10 The way of the program is wrong. e. i. f. Remove the word public. g. d. and all you have to do is fix it. You will develop a sense for when you can trust the compiler and when you have to figure things out yourself. Remove the word System. write mian.

public static void main(String[] args) { System.println("How are you?"). The next time println is invoked. punctuation marks. public static void main(String[] args) { System.out. use print: class Hello { // Generates some simple output.print("Goodbye.out. println is short for “print line. called a newline. that moves the cursor to the next line of the display. System. for example. to print more than one line: class Hello { // Generates some simple output. numbers. you can put comments at the end of a line.” because after each line it adds a special character.println("Hello. the new text appears on the next line. as well as on a line by themselves.1 More printing You can put as many statements as you want in main.Chapter 2 Variables and types 2.out. because they are made up of a sequence (string) of characters. } } As this example demonstrates. and other special characters. To display the output from multiple print statements all on one line. "). world. Strings can contain any combination of letters. The phrases that appear in quotation marks are called strings. // print one line // print another .").

System. The strings we have been printing ("Hello. so it affects the behavior of the program. Newlines and spaces are useful for organizing your program visually.println("cruel world!"). There is no such type as Int or string. This statement is a declaration.out. For example. In order to store a value.print("Goodbye.) are values. but the program is getting harder and harder to read.print("Goodbye.out. World. etc. the int type can store integers.out. There is a space between the word “Goodbye” and the second quotation mark. . The breaks at the ends of lines (newlines) do not affect the program’s behavior either. This space appears in the output. "). Values are things that can be printed. and the String type can store strings.". Each variable has a type that determines what kind of values it can store. Some types begin with a capital letter and some with lower-case. "). too. "Goodbye. because it declares that the variable named bob has the type String. For example. we declare that the new variable is a string: String bob. ". A variable is a named location that stores a value.println ("cruel world!"). } } Variables and types The output appears on a single line as Goodbye. } } This program would compile and run just as well as the original.2 Variables One of the most powerful features of a programming language is the ability to manipulate variables. and the compiler will object if you try to make one up. 2. cruel world!. I could have written: class Hello { public static void main(String[] args) { System. Spaces that appear outside of quotation marks generally do not affect the behavior of the program.12 System. System. stored and (as we’ll see later) operated on.out. Since the values we want to store are strings.println("cruel world!").out. making it easier to read the program and locate errors. We will learn the significance of this distinction later. you have to create a variable. but for now you should take care to get it right.}} That would work. so I could have written: class Hello { public static void main(String[] args) { System.

" hour 11 minute 59 As a general rule. The vocabulary can be confusing here. In general. you could guess what values would be stored in them. and Java sometimes converts things automatically. bob = "123". 2. if you saw these variable declarations: String firstName. 2 and 3.".3 Assignment 13 To create an integer variable. A common way to represent variables on paper is to draw a box with the name of the variable on the outside and the value of the variable on the inside. minute.2. but the idea is straightforward: • When you declare a variable. but they are not. you will want to make up variable names that indicate what you plan to do with the variable. the syntax is int bob. that rule can be confusing.3 Assignment Now that we have created variables. and we’ll talk about exceptions later. For now you should remember the general rule. • When you make an assignment to a variable. you create a named storage location. bob = "Hello. because there are many ways that you can convert values from one type to another. // legal bob = 123. You cannot store a String in minute or an integer in bob. which is made up of the characters 1. String lastName. This example also demonstrates the syntax for declaring multiple variables with the same type: hour and second are both integers (int type). We do that with an assignment statement. // set minute to 59 This example shows three assignments. you give it a value. Another source of confusion is that some strings look like integers. On the other hand. For example. // assign the value 11 to hour minute = 59. // give bob the value "Hello." hour = 11. where bob is the arbitrary name you made up for the variable. int hour. but that is not the same thing as the number 123. // not legal . and the comments show three different ways people sometimes talk about assignment statements. For example. This figure shows the effect of the three assignment statements: fred "Hello. a variable has to have the same type as the value you assign it. bob can contain the string "123". we want to store values..

out.5 Keywords A few sections ago.out.4 Printing variables You can print the value of a variable using println or print: class Hello { public static void main(String[] args) { String firstLine. I said that you can make up any name you want for your variables. System. System. There are certain words that are reserved . firstLine = "Hello. System.out. you can write String firstLine. When we talk about “printing a variable. assigns it the value "Hello.").out. again!". the output from print is stored without being displayed until println is invoked. the program may terminate without ever displaying the stored output! 2.print("The value of firstLine is "). minute. } } This program creates a variable named firstLine. System. WARNING: It is common practice to use several print statements followed by a println. But you have to be careful to remember the println at the end. System. you have to put it in quotes. System. but that’s not quite true. To print the name of a variable.14 Variables and types 2.println(firstLine). hour = 11.print("The current time is "). again!" and then prints that value. again! I am happy to report that the syntax for printing a variable is the same regardless of the variable’s type. in order to put multiple values on the same line.print(minute).out.out.out. firstLine = "Hello. For example.out.” we mean printing the value of the variable. minute = 59. In many environments.println("firstLine"). For example: System. The output of this program is The value of firstLine is Hello. System. int hour. System. If you omit println. at which point the entire line is displayed at once.println(".print(":"). The output of this program is The current time is 11:59.println(firstLine). again!".print(hour).out.

When both operands are integers (operands are the things operators operate on).print("Number of minutes since midnight: "). This site.6 Operators 15 in Java because they are used by the compiler to parse the structure of your tutorial/java/nutsandbolts/_keywords. even in cases like this where the next integer is so close. provided by Oracle. For example. and 59 divided by 60 is 0. Most operators in Java do what you expect them to do because they are common mathematical symbols.println(minute/60). Rather than memorize the list. I suggest you take advantage of a feature provided in many Java development environments: code highlighting. and many more. the result is also an integer. 1+1 hour-1 hour*60 + minute minute/60 Expressions can contain both variable names and numbers. and other code black. strings red. System. Variables are replaced with their values before the computation is performed. For example.6 Operators Operators are symbols used to represent computations like addition and multiplication. generates this output: Number of minutes since midnight: 719 Fraction of the hour that has passed: 0 The first line is expected.out. As you type. it will get confused. 2.out. keywords might be blue. The problem is that Java is performing integer division. minute = 59. and if you use them as variable names.out. but the second line is odd. System. this program: int hour. These words. and division is /.print("Fraction of the hour that has passed: "). The value of minute is 59. An alternative is to calculate a percentage rather than a fraction: . The complete list is available at http://download. System. parts of your program should appear in different colors. and by convention integer division always rounds down. System. but you might be surprised by division. the operator for addition is +. hour = 11. If you type a variable name and it turns blue. include public.html. Subtraction is -. For example.println(hour*60 + minute). includes Java documentation I refer to throughout the book. called keywords. minute. Addition. int. multiplication is *.98333. void.2. watch out! You might get some strange behavior from the compiler. subtraction and multiplication all do what you expect. not 0.out.

the + operator does work with Strings. even though it doesn’t change the result. not 4. but just to get you started: • Multiplication and division happen before addition and subtraction." and bob + "ism" adds the suffix ism to the end of whatever bob is. the multiplication happens first. The only way to tell the type of a variable is to look at the place where it is declared. so 2 *(3-1) is 4. So "Hello.8 Operators for Strings In general you cannot perform mathematical operations on Strings. We’ll get to that in the next chapter. even if the strings look like numbers.out. If the operations had gone from right to left. which is wrong. Expressions in parentheses are evaluated first. the + operator represents concatenation. In order to get a more accurate answer. The result is: Percentage of the hour that has passed: 98 Again the result is rounded down. Interestingly. . For Strings. So in the expression minute*100/60.print("Percentage of the hour that has passed: "). the result would be 59*1 which is 59.16 Variables and types System. can you tell by looking at those expressions whether bob is an integer or a string? Nope. 2. 2. • Any time you want to override the rules of precedence (or you are not sure what they are) you can use parentheses. yielding 5900/60. but it might not do what you expect." yields the string "Hello. • If the operators have the same precedence they are evaluated from left to right.out. " + "world. which is handy for naming new forms of bigotry. called floating-point.7 Order of operations When more than one operator appears in an expression. and 2/3-1 yields -1.1 "Hello"/123 bob * "Hello" By the way. The following are illegal (if we know that bob has type String) bob . but at least now the answer is approximately correct. which in turn yields 98. System. world. You can also use parentheses to make an expression easier to read. which means joining up the two operands by linking them end-to-end. So 2*3-1 yields 5. that can store fractional values. the order of evaluation depends on the rules of precedence. we can use a different type of variable. not 1 (remember that in integer division 2/3 is 0).println(minute*100/60). A complete explanation of precedence can get complicated. as in (minute * 100) / 60.

declaration: A statement that creates a new variable and determines its type. value: A number or string (or other thing to be named later) that can be stored in a variable. All variables have a type. without talking about how to combine them.println(17 * 3). can be used inside a print statement. . So the following is illegal: minute+1 = hour. operators and values that represents a single value. expressions.9 Composition So far we have looked at the elements of a programming language—variables. WARNING: The left side of an assignment has to be a variable name. type: A set of values. class and void as variable names. but we will see examples where composition expresses complex computations neatly and concisely. it turns out we can combine them in a single statement: System.9 Composition 17 2. percentage = (minute * 100) / 60. So far. and statements—in isolation. One of the most useful features of programming languages is their ability to take small building blocks and compose them. We’ve already seen one example: System. as determined by their operators and operands. only values.10 Glossary variable: A named storage location for values. For example. Every value belongs to a type. like public. keyword: A reserved word used by the compiler to parse programs. expression: A combination of variables. Any expression involving numbers. The type of a variable determines which values can be stored there. But you can also put arbitrary expressions on the right-hand side of an assignment statement: int percentage.out. assignment: A statement that assigns a value to a variable. That’s because the left side indicates the storage location where the result will go. Expressions do not represent storage locations.. the types we have seen are integers (int in Java) and strings (String in Java).2.println(hour*60 + minute). not an expression. strings and variables. we know how to multiply numbers and we know how to print.out. This ability may not seem impressive now. which is declared when the variable is created. 2. You cannot use keywords. Expressions also have types.

One player turns away while the other player adds an error to the program. write a program that creates variables named day. Exercise 2. July 16. Exercise 2. c. Create a new program named Date. Modify the program so that it prints the date in standard American form: Saturday. Note: please don’t remove the “l” from “public. precedence: The order in which operations are evaluated. one point if you find it using the compiler. b. operand: One of the values on which an operator operates. Modify the program again so that the total output is: American format: Saturday. concatenate: To join two operands end-to-end. e. 2. What type is each variable? Assign values to those variables that represent today’s date. d. July 16. date. and your opponent gets a point if you don’t find World” program and make sure you can compile and run it.11 Exercises Exercise 2. composition: The ability to combine simple expressions and statements into compound statements and expressions in order to represent complex computations concisely. and to practice developing programs gradually by adding a few statements at a time. Copy or type in something like the “Hello. 2011 The point of this exercise is to use string concatenation to display values with different types (int and String).3 . Following the example in Section 2. 2011 European format: Saturday 16 July.2 a. you might enjoy this exercise: find a partner and play ”Stump the Chump”: Start with a program that compiles and runs correctly. You get two points if you find the error without compiling the program. multiplication or string concatenation. day will contain the day of the week and date will contain the day of the month.18 Variables and types operator: A symbol that represents a computation like addition.” It’s not as funny as you think. Then the first player tries to find and fix the error.4. Print the value of each variable on a line by itself. This is an intermediate step that is useful for checking that everything is working so far. month and year. 2011.1 If you are using this book in a class.

Create a new program called Time. and to start thinking about compound entities like the time of day that that are represented with multiple values. Make the program calculate and print the number of seconds remaining in the day. and assign them values that are roughly the current time. The point of this exercise is to use some of the arithmetic operations. and check to make sure that the program works correctly with different values. Following the example in Section 2. Make the program calculate and print the percentage of the day that has passed. Also. Change the values of hour. which is the motivation for floating point numbers in the next chapter. f.11 Exercises 19 a. Make the program calculate and print the number of seconds since midnight. minute and second to reflect the current time (I assume that some time has elapsed).6. b. are sometimes called intermediate or temporary variables. c. that are used in a computation but never printed. Use a 24-hour clock. From now on. minute and second.2. working program. HINT: you may want to use additional variables to hold values temporarily during the e. . so that at 2pm the value of hour is 14. d. Variables like this. you might run into problems computing percentages with ints. but you should. I won’t remind you to start with a small. create variables named hour.

20 Variables and types .

the floating-point type is called double. . For example. the following is illegal: int x = 1. is that an integer. a floating-point number. Although floating-point numbers are useful.0.” You can create floating-point variables and assign values to them using the same syntax we used for the other types.14159. which is short for “double-precision. For example: double pi. you are not allowed to make assignments between types.14159.1 Floating-point In the last chapter we had some problems dealing with numbers that were not integers. a combined declaration and assignment is sometimes called an initialization. For example. or both? Java distinguishes the integer value 1 from the floating-point value 1. This syntax is common. which can represent fractions as well as integers. We worked around the problem by measuring percentages instead of fractions. even though they seem to be the same number. In Java. if you have the value 1. pi = 3. They belong to different types. double pi = 3. and strictly speaking. It is also legal to declare a variable and assign a value to it at the same time: int x = 1. but a more general solution is to use floating-point numbers. String empty = "".Chapter 3 Methods 3. they are a source of confusion because there seems to be an overlap between integers and floating-point numbers.1.

3. The reason is that the expression on the right is the ratio of two integers. which yields the integer value 0. This leniency is convenient. should technically not be legal. so x gets the value 3. but it can cause problems. You might expect the variable y to get the value 0. In fact.0. Typecasting is so called because it allows you to take a value that belongs to one type and “cast” it into another type (in the sense of molding or reforming). most processors have special hardware just for performing floating-point operations. although you might be interested to know that the underlying mechanism is completely different.0. but Java allows it by converting the int to a double automatically. not 62. in order to make sure that you.0 / 3.0. the result is 0. Converted to floating-point. for example: double y = 1 / 3.333333.333333. and the result is 60. as the programmer. as expected.14159. The syntax for typecasting is to put the name of the type in parentheses and use it as an operator. are aware of the loss of the fractional part of the number. int x = (int) pi.2 Converting from double to int As I mentioned. subtraction. double pi = 3. so Java does integer division.0. and division—also work on floating-point values. but in fact it gets 0. The operations we have seen so far—addition. Java doesn’t perform this operation automatically. . For example. so in the following example. the value of pi gets converted to an integer first.22 Methods because the variable on the left is an int and the value on the right is a double. Java converts ints to doubles automatically if necessary. Typecasting takes precedence over arithmetic operations. The simplest way to convert a floating-point value to an integer is to use a typecast. This sets y to 0. One way to solve this problem (once you figure out what it is) is to make the right-hand side a floating-point expression: double y = 1. because no information is lost in the translation. But it is easy to forget this rule. For example: double y = 1. multiplication. especially because there are places where Java will automatically convert from one type to another. going from a double to an int requires rounding off. On the other hand. which is a legal floating-point value. The (int) operator has the effect of converting what follows into an integer.

you have probably seen functions like sin and log. then evaluate the function.3 Math methods In mathematics. you can use any expression as an argument to a method: . and you have learned to evaluate expressions like sin(π/2) and log(1/x). To convert from degrees to radians. double height = Math. int x = Math.round(Math. For example. pi. which is 1. First we evaluate the argument of the innermost function. meaning that you use one expression as part of another. which is called the argument of the function. Then you can evaluate the function itself.sin(angle). double x = (int) pi * 20. even if the fraction part is 0. and so on.sqrt(17.3.4 Composition Just as with mathematical functions. double angle = degrees * 2 * Math.14159. 3.3 Math methods double pi = 3. The second example finds the sine of the value of angle.PI: double degrees = 90. Java methods can be composed. you evaluate the expression in parentheses. Java provides Math. The result is 63 (rounded up from 62. which rounds a floating-point value off to the nearest integer and returns an int. Java provides functions that perform the most common mathematical operations. or pie. First.PI * 20.5.99999999. The math methods are invoked using a syntax that is similar to the print statements we have already seen: double root = Math.0. Notice that PI is in all capital letters. Java assumes that the values you use with sin and the other trigonometric functions (cos. Conveniently. either by looking it up in a table or by performing various computations. before the method is invoked.0).0. Java does not recognize Pi.0). In this case the multiplication happens first. The first example sets root to the square root of 17.8319). These behaviors (precedence and rounding) can make typecasting error-prone. 23 Converting to an integer always rounds down.PI / 360. tan) are in radians. 3. This process can be applied repeatedly to evaluate more complicated expressions like log(1/ sin(π/2)). These functions are called methods. Another useful method in the Math class is round. you can divide by 360 and multiply by 2π. double angle = 1.5.

divides it by two and adds the result to the value of the variable angle. We have already seen one method definition: main. Printing a String with no letters in it may not seem all that useful. Java methods start with a lower case letter and use “camel caps.out. You can also take the result of one method and pass it as an argument to another: double x = Math. so the syntax looks like this: public static void newLine() { System. so this statement skips to the next line. The method named main is special. Methods This statement takes the value Math. which means that whoever invokes main has to provide an array of Strings (we’ll get to arrays in Chapter 12).cos(angle + Math. but println skips to the next line after it prints. indicated by "". you have to provide in order to use (or invoke) the new method. but the syntax is the same for other methods: public static void NAME( LIST OF PARAMETERS ) { STATEMENTS } You can make up any name you want for your method. The list of parameters specifies what information. if any. The result gets assigned to x. It contains one statement. } This method is named newLine. and the empty parentheses mean that it takes no parameters. which prints an empty String. The sum is then passed as an argument to cos. except that you can’t call it main or any other Java keyword.exp(Math.5 Adding new methods So far we have used methods from the Java libraries. but it is also possible to add new methods. so this statement finds the log base e of 10 and then raises e to that power. not even the empty argument ()). not a method.PI. 3.” which is a cute name for jammingWordsTogetherLikeThis.println(""). The first couple of methods we are going to write have no parameters. .24 double x = Math. In Java. The parameter for main is String[] args.out.PI/2). so there are no arguments. By convention.println("First line. the log method always uses base e. I hope you know what it is. In main we invoke this new method the same way we invoke Java methods: public static void main(String[] args) { System.0)). (PI is the name of a variable.").log(10.

named threeLine.println("First line. In this case. this example demonstrates two: 1. which is syntactically legal (remember that spaces and new lines usually don’t change the meaning of a program).out. Methods can simplify a program by hiding a complex computation behind a single statement. main invokes threeLine and threeLine invokes newLine.println("Second line.5 Adding new methods newLine().println("Second line. System.out. There are several reasons. System. } public static void main(String[] args) { System. Which is clearer. newLine(). Creating a new method gives you an opportunity to give a name to a group of statements.out. Second line.println("First line."). threeLine(). It is usually a good idea to put each statement on its own line. newLine(). but I sometimes break that rule. • You can have one method invoke another method. What if we wanted more space between the lines? We could invoke the same method repeatedly: public static void main(String[] args) { System. newLine(). } Or we could write a new method.").out.")."). 25 Notice the extra space between the lines."). newLine().println("")? . So far. System. newLine or System. newLine().println("Second line. • In threeLine I wrote three statements all on the same line.3. that prints three new lines: public static void threeLine() { newLine(). and by using English words in place of arcane code. } You should notice a few things about this program: • You can invoke the same procedure more than once. } The output of this program is First line. it may not be clear why it is worth the trouble to create all these new methods.out.out.

the class definition looks like this: class NewLine { public static void newLine() { System.out. A class is a collection of related methods. } public static void threeLine() { newLine().println("Second line.7 we will come back to this question and list some additional benefits of dividing programs into methods. threeLine. we have to specify the name of the class (Math) and the name of the method. In this case.0. The first statement invokes the pow method in the Math class (which raises the first argument to the power of the second argument).println(""). . 3. } } The first line indicates that this is the class definition for a new class called NewLine. When we invoke a mathematical method.0. newLine(). For example.6 Classes and methods Pulling together the code fragments from the previous section.0). newLine(). and main. System. you could invoke threeLine three times.out. to print nine consecutive new lines. Creating a new method can make a program smaller by eliminating repetitive code. if you type: pow(2. the class named NewLine contains three methods. The second statement invokes the newLine method.println("First line."). which Java assumes is in the NewLine class. In Section 7. sin. The other class we’ve seen is the Math class. and others. If you try to invoke a method from the wrong class.pow(2.26 Methods 2."). 10. the compiler will generate an error. } public static void main(String[] args) { System.0). newLine(). threeLine(). That’s why the syntax is slightly different for Java methods and the methods we write: Math. named newLine.out. For example. which is what we are writing. It contains methods named sqrt. 10.

The Java interpreter takes care of things like deleting windows and general cleanup. What’s the moral of this sordid tale? When you read a program. it picks up where it left off in newLine. don’t read from top to bottom. newLine invokes the Java method println. we might have to go off and execute the statements in threeLine. Instead of going to the next statement.” If you have seen this message. which takes two doubles. but that is likely to be confusing. you have to provide the number. which is why println takes a String as a parameter. Execution always begins at the first statement of main. Instead. execution picks up where it left off in the program that invoked main. if you want to find the sine of a number. which are values that you provide to let the method do its job. To print a string. so when println completes. which is the Java interpreter. Fortunately. while we are in the middle of main. Instead. except that you have to remember that one method can invoke another. you might have wondered why it was looking for pow in your class definition. Statements are executed one at a time. execute all the statements there. follow the flow of execution. and then come back and pick up again where you left off. For example.7 Programs with multiple methods 27 The compiler will say something like.8 Parameters and arguments Some of the Java methods we have used have parameters. Some methods take more than one parameter. we get interrupted three times to go off and execute newLine. Method invocations are like a detour in the flow of execution. “Can’t find a method named pow in class NewLine.7 Programs with multiple methods When you look at a class definition that contains several methods. because that is not the order of execution of the program. 3. until you reach a method invocation. regardless of where it is in the program (in this example I deliberately put it at the bottom). Technically. . you have to provide the string. the program does not terminate at the end of main. 3. and then the program terminates. For its part. it is tempting to read it from top to bottom. Thus. Java is adept at keeping track of where it is.3. Now you know. and then finally gets back to main so the program can terminate. That sounds simple enough. and then gets back to threeLine. like pow. So sin takes a double as a parameter. the base and the exponent. you go to the first line of the invoked method. in order. which causes yet another detour. But while we are executing threeLine.

but in general you can choose any name you want. For example: public static void printTwice(String s) { System.". For example. The value you provide as an argument must have the same type as the parameter of the method you invoke. } The string you provide is called an argument. contrary to its wishes. but it gets complicated in Java for two reasons: • There are some methods that can accept arguments with many different types. I chose the name s as a hint that the parameter is a string. you can send any type to print and println. but also what type they are.println(s). though. and it will do the right thing no matter what. So it shouldn’t surprise you that when you write a class definition.println(s). we might have a main method like this: public static void main(String[] args) { printTwice("Don’t make me say this twice!")."). They can be the same or they can be different. In order to invoke this method. Alternatively.out. } Notice something very important: the name of the variable we pass as an argument (argument) has nothing to do with the name of the parameter (s). we have to provide a String. Let me say that again: The name of the variable we pass as an argument has nothing to do with the name of the parameter.out. For example. and we say that the argument is passed to the method. This rule is important. the parameter list indicates the type of each parameter. it gets printed twice.28 Methods We have to specify not only how many parameters there are. } This method takes a single parameter. except that they happen to have the same value (in this case the string "Never say never. printTwice(argument). named s. if we had a String variable. . In this case we are creating a string value that contains the text “Don’t make me say this twice!” and passing that string as an argument to printTwice where. System. Whatever that parameter is(and at this point we have no idea what it is). This sort of thing is an exception. we could use it as an argument instead: public static void main(String[] args) { String argument = "Never say never. but it is important to realize that they are not the same thing. it will get printed twice. that has type String.

out. Another common source of confusion is that you do not have to declare the types of arguments. } It might be tempting to write int hour.out. there is no such thing as s. int minute) { System. If you try to use it. System.10 Methods with multiple parameters The syntax for declaring and invoking methods with multiple parameters is a common source of errors. you will figure out how to interpret it.3. 3. the value of each variable is drawn inside a box with the name of the variable beside it. but that format is only legal for variable declarations. inside printTwice there is no such thing as argument.print(hour)." For each method there is a gray box called a frame that contains the method’s parameters and variables.print(":"). the compiler often generates a confusing error message. Once you have seen this error message a few times. One way to keep track of where each variable is defined is with a stack diagram.9 Stack diagrams Parameters and other variables only exist inside their own methods. First. minute. Similarly.println(minute). As usual. For example public static void printTime(int hour. The name of the method appears outside the frame. The stack diagram for the previous example looks like this: main argument "Never say never. System. The following is wrong! . Within the confines of main." printTwice s "Never say never. Instead of saying something like. 3.” it will probably say something to the effect that it could not find a method with that name that would accept an argument with that type. the compiler will complain. remember that you have to declare the type of every parameter.out. “You are passing the wrong kind of argument to this method. not for parameters. though.9 Stack diagrams 29 • If you violate this rule.

println("boo!") + 7? • Can we write methods that yield results. and may or may not produce a result. int minute = 59. and we have written classes named Hello and NewLine. In fact. a good way to find out is to ask the compiler. . Exercise 3. 3. Java can tell the type of hour and minute by looking at their declarations.e. 3. Methods may or may not take parameters. int minute). minute). I will leave it up to you to answer the other two questions by trying them out. Other methods. or are we stuck with things like newLine and printTwice? The answer to the third question is “yes. printTime(int hour. like System.1 Draw a stack frame that shows the state of the program when main invokes printTime with the arguments 11 and 59.” and we’ll do it in a couple of chapters.12 Glossary initialization: A statement that declares a new variable and assigns a value to it at the same time. class: A named collection of methods. you don’t assign it to a variable or use it as part of a larger expression)? • What happens if you use a print method as part of an expression.30 int hour = 11. like the Math methods. Methods // WRONG! In this case.11 Methods with results Some of the methods we are using. The correct syntax is printTime(hour. any time you have a question about what is legal or illegal in Java. perform an action but they don’t return a value. yield results. So far.out. floating-point: A type of variable (or value) that can contain fractions as well as integers. That raises some questions: • What happens if you invoke a method and you don’t do anything with the result (i. you can write methods that return values. It is not necessary to include the type when you pass them as arguments. The floating-point type we will use is double. like println and newLine. we have used the Math class and the System class. method: A named sequence of statements that performs a useful function.

baffle(). b.println(". HINT: Start by describing in words what ping and baffle do when they are invoked.print("You wugga "). 3.out.print("I "). What is the output of the following program? Be precise about where there are spaces and where there are newlines. } Exercise 3. a.out. Draw a stack diagram that shows the state of the program the first time ping is invoked.13 Exercises Exercise 3. frame: A structure (represented by a gray box in stack diagrams) that contains a method’s parameters and variables.3.out. public static void zoop() { baffle(). } public static void main(String[] args) { System. zoop(). Parameters are variables: they contain values and have types. This value must have the same type as the corresponding parameter. invoke: Cause a method to execute.13 Exercises 31 parameter: A piece of information a method requires before it can run. baffle().print("wug").out. } public static void baffle() { System.print("No. System. System."). } public static void ping() { System. argument: A value that you provide when you invoke a method. .out.3 The point of this exercise is to make sure you understand how to write and invoke methods that take parameters. I ").2 The point of this exercise is to practice reading code and to make sure that you understand the flow of execution through a program with multiple methods. ping().

The output should look something like this (except that the date might be different): Saturday. Test your method by invoking it from main and passing appropriate arguments.4 The purpose of this exercise is to take code from a previous exercise and encapsulate it in a method that takes parameters. Exercise 3. Write the first line of a method named zool that takes three parameters: an int and two Strings. and the name of the street you grew up on. passing as arguments the value 11. b. .2. date. July 16. 2011 c. a. the name of your first pet. You should start with a working solution to Exercise 2.32 Methods a. write another method called printEuropean that prints the date in European format. Write a line of code that invokes zool. b. month and year as parameters and that prints them in American format. Once you have debugged printAmerican. Write a method called printAmerican that takes the day.

7 divided by 3 is 2 with 1 left over. In Java. int remainder = 7 % 3.out. } The expression in parentheses is called the condition. Also. we almost always need to check conditions and change the behavior of the program accordingly. The syntax is the same as for other operators: int quotient = 7 / 3. Thus.2 Conditional execution In order to write useful programs. The second operator yields 1. the modulus operator is a percent sign. For example. integer division. %. The first operator. yields 2. nothing happens.1 The modulus operator The modulus operator works on integers (and integer expressions) and yields the remainder when the first operand is divided by the second. The modulus operator turns out to be surprisingly useful. Similarly x % 100 yields the last two digits. . you can check whether one number is divisible by another: if x % y is zero. If the condition is not true. For example. then x is divisible by y. 4. Conditional statements give us this ability. The simplest form is the if statement: if (x > 0) { System. then the statements in brackets get executed.println("x is positive"). you can use the modulus operator to extract the rightmost digit or digits from a number.Chapter 4 Conditionals and recursion 4. If it is true. x % 10 yields the rightmost digit of x (in base 10).

If the condition is false. the syntax Java uses is a little different from mathematical symbols like =.3 Alternative execution A second form of conditional execution is alternative execution. in which there are two possibilities. there is no such thing as =< or =>.out. 4.10.out.println("x is odd"). } else { System. The two sides of a condition operator have to be the same type. We will see how to compare strings Section 8.println("x is odd"). and == is a comparison operator. then we know that x is even. = and ≤. sometimes called relational operators: x x x x x x == y != y > y < y >= y <= y // // // // // // x x x x x x equals y is not equal to is greater than is less than y is greater than is less than or y y or equal to y equal to y Although these operations are probably familiar to you. as follows: public static void printParity(int x) { if (x%2 == 0) { System. but they don’t do what you expect.println("x is even"). A common error is to use a single = instead of a double ==.println("x is even"). you might want to “wrap” this code up in a method.34 Conditionals and recursion The condition can contain any of the comparison operators. and the condition determines which one gets executed. } If the remainder when x is divided by 2 is zero. Also. The operators == and != work with Strings. and this code prints a message to that effect. As an aside. } else { System. the second print statement is executed. } } . The syntax looks like: if (x%2 == 0) { System. And the other relational operators don’t do anything at all.out. Since the condition must be true or false. if you think you might want to check the parity (evenness or oddness) of numbers often.out. Remember that = is the assignment operator. exactly one of the alternatives will be executed. You can only compare ints to ints and doubles to doubles.

println("x is zero").println("x is negative"). Always remember that when you invoke a method. One way to do this is by chaining a series of ifs and elses: if (x > 0) { System. } else { System.5 Nested conditionals In addition to chaining. 4. as demonstrated in these examples. We could have written the previous example as: if (x == 0) { System. } else { if (x > 0) { System. One way to make them easier to read is to use standard indentation. } else if (x < 0) { System. } } There is now an outer conditional that contains two branches.out.println("x is positive").out. you can also nest one conditional within another.out. although they can be difficult to read if they get out of hand. you are less likely to make syntax errors and more likely to find them if you do.println("x is zero").out. } else { System. Java can figure out what type they are.out.println("x is negative"). In main you would invoke this method like this: printParity(17). The first branch contains a simple print statement. // WRONG!!! 4. which has two branches of its own. you do not have to declare the types of the arguments you provide. Those two branches . } These chains can be as long as you want.4 Chained conditionals 35 Now you have a method named printParity that will print an appropriate message for any integer you care to provide.4.4 Chained conditionals Sometimes you want to check for a number of related conditions and choose one of several actions.out.println("x is positive"). but the second branch contains another conditional statement. You should resist the temptation to write things like: int number = 17. printParity(int number). If you keep all the statements and squiggly-brackets lined up.

println("Positive numbers only.7 Type conversion You might wonder how you can get away with an expression like "The log of x is " + result. One reason to use it is if you detect an error condition: public static void printLogarithm(double x) { if (x <= 0.println("The log of x is " + result). On the other hand. return. I used a floating-point value on the right side of the condition because there is a floating-point variable on the left.out. System. In this case Java is being smart on our behalf. I neglected to mention that it is also legal . and we will see it again.36 Conditionals and recursion are both print statements.8 Recursion I mentioned in the last chapter that it is legal for one method to invoke another.out. Indentation helps make the structure apparent.log(x). The flow of execution immediately returns to the caller and the remaining lines of the method are not executed. automatically converting the double to a String before it does the string concatenation. nested conditionals get difficult to read very quickly.6 The return statement The return statement allows you to terminate the execution of a method before you reach the end. Whenever you try to “add” two expressions. and we have seen several examples. in which case it prints an error message and then uses return to exit the method. Avoid them when you can. 4. but nevertheless. please. but they could have been conditional statements as well. } double result = Math.0) { System. Java converts the other to a String and then perform string concatenation. What do you think happens if you perform an operation between an integer and a floating-point value? 4. It checks whether x is less than or equal to zero. } This defines a method named printLogarithm that takes a double named x as a parameter. 4. if one of them is a String. so you better get used to it. since one of the operands is a String and the other is a double. this kind of nested structure is common.").

The countdown that got n=2 returns. and since n is not zero. The countdown that got n=3 returns. } . } } The name of the method is countdown and it takes a single integer as a parameter.out.” Otherwise. it prints the value 2. It may not be obvious why that is a good thing.out. but it turns out to be one of the most magical and interesting things a program can do. The execution of countdown begins with n=0. look at the following method: public static void countdown(int n) { if (n == 0) { System. The execution of countdown begins with n=3. and since n is not zero.8 Recursion 37 for a method to invoke itself. in main. and since n is not zero. } else { System.... it prints the word “Blastoff.. countdown(n-1). it prints the value 1. it prints the value 3. it prints the number and then invokes a method named countdown—itself—passing n-1 as an argument. And then you’re back in main. it prints the word “Blastoff!” and then returns.println("Blastoff!").out. and then invokes itself.. and then invokes itself. The execution of countdown begins with n=2. The countdown that got n=1 returns..4. So the total output looks like: 3 2 1 Blastoff! As a second example. For example. If the parameter is zero. What happens if we invoke this method. and then invokes itself. public static void newLine() { System. like this: countdown(3).println(n).println(""). and since n is zero. The execution of countdown begins with n=1. let’s look again at the methods newLine and threeLine.

The total number of newlines that get printed is 1 +(n-1). A better alternative would be public static void nLines(int n) { if (n > 0) { System. each with a different value for the parameter n. nLines(n-1). . or 106. which usually comes out to roughly n. The following figure is a stack diagram for countdown. that’s called recursion. newLine(). called with n = 3: main countdown countdown countdown countdown n n n n 3 2 1 0 There is one frame for main and four frames for countdown. The bottom of the stack. newLine(). and such methods are recursive. } } This program similar to countdown. 4. It does not make a recursive call. Remember that every time a method gets called it creates a new frame that contains a new version of the method’s parameters and variables. When a method invokes itself. it prints a newline and then invokes itself to print n-1 additional newlines.println("").9 Stack diagrams for recursive methods In the previous chapter we used a stack diagram to represent the state of a program during a method invocation. countdown with n=0 is called the base case. as long as n is greater than zero. } Conditionals and recursion Although these work. they would not be much help if we wanted to print 2 newlines. so there are no more frames for countdown.out. The same kind of diagram can make it easier to interpret a recursive method.38 public static void threeLine() { newLine().

conditional: A block of statements that may or may not be executed depending on some condition.10 Glossary modulus: An operator that works on integers and yields the remainder when one number is divided by another.11 Exercises Exercise 4.1 Draw a stack diagram that shows the state of the program after main invokes nLines with the parameter n=4. In Java it is denoted with a percent sign(%). 4.10 Glossary 39 The frame for main is empty because main does not have any parameters or variables. base case: A condition that causes a recursive method not to make a recursive call.4. just before the last invocation of nLines returns. In Java it appears as a type name in parentheses. 4. coordinate: A variable or value that specifies a location in a two-dimensional graphical window. prototype: A way of describing the interface to a method using Java-like syntax. Exercise 4. interface: A description of the parameters required by a method and their types. recursion: The process of invoking the same method you are currently executing. Read the following code and answer the questions below. typecast: An operator that converts from one type to another. bounding box: A common way to specify the coordinates of a rectangular area. nesting: Putting a conditional statement inside one or both branches of another conditional statement. chaining: A way of joining several conditional statements in sequence. pixel: The unit in which coordinates are measured.2 This exercise reviews the flow of execution through a program with multiple methods. . like (int).

Write a program that prints the entire lyrics of “99 Bottles of Beer.40 public class Buzz { Conditionals and recursion public static void baffle(String blimp) { System.” Your program should include a recursive method that does the hard part. ya’ pass it around. and so on until the end of the program. ya’ take one down.println(quince + " zoop"). no bottles of beer.println(blimp). ’cause there are no more bottles of beer on the wall! And then the song(finally) ends. Subsequent verses are identical except that the number of bottles gets smaller by one in each verse. Write the number 1 next to the first statement of this program that will be executed. test it with a small number of verses. } } public static void main(String[] args) { zippo("rattle".out.out. int flag) { if (flag < 0) { System. baffle(quince). If a statement is executed more than once. What is the output of this program? Exercise 4. b. } public static void zippo(String quince. c.out.println("boo-wa-ha-ha"). } } a.3 The first verse of the song “99 Bottles of Beer” is: 99 bottles of beer on the wall.” . As you develop your code. 13). Write the number 2 next to the second statement. zippo("ping". but you might want to write additional methods to separate the major functions of the program. Be careful to distinguish things that are statements from things that are not.out. ya’ can’t take one down. 98 bottles of beer on the wall. ya’ can’t pass it around. System. until the last verse: No bottles of beer on the wall. 99 bottles of beer. like “3 Bottles of Beer. } else { System.println("ik"). it might end up with more than one number next to it. What is the value of the parameter blimp when baffle gets invoked? d. -5).

int bob) { System.out.out. } public static void ping(String strangStrung) { System. and to solve the smaller problems by writing simple methods. Fermat was wrong!” Otherwise the program should print “No. } else { System. For example: int x = raiseToPow(2. that doesn’t work. Exercise 4.println("!").println("any " + strangStrung + "more "). clink(2*buzz). fork) . } public static void clink(int fork) { System. } } Exercise 4. c and n—and that checks to see if Fermat’s theorem holds. } } public static void main(String[] args) { int bizz = 5. bizz). zoop("just for". . the program should print “Holy smokes. if (bob == 5) { ping("not "). b. b.4.out.print("It’s "). int buzz = 2.4 What is the output of the following program? public class Narf { public static void zoop(String fred.println(fred). Write a method named checkFermat that takes four integers as parameters—a.” You should assume that there is a method named raiseToPow that takes two integers as arguments and that raises the first argument to the power of the second. would assign the value 8 to x. because 23 = 8. and c an + b n = c n except in the case when n = 2. zoop("breakfast ".5 such that Fermat’s Last Theorem says that there are no integers a.out. 3).11 Exercises 41 The purpose of this exercise is to take a problem and break it into smaller problems. If n is greater than 2 and it turns out to be true that an + bn = cn .

42 Conditionals and recursion .

Rocks and the Grid itself.collegeboard.1 Getting started Now is a good time to start working with the AP Computer Science Case Study.Chapter 5 GridWorld: Part One 5. • An object is also called an instance because it is a member. . of a class. When you unpack this code. There are instructions here that might help: http://www. every object belongs to a class. which you can download from the College Board: http://www.pdf. Once you run BugRunner.collegeboard. • A class is a set of which contains BugRunner. download the GridWorld Student Manual from http://www. or instance. Make a copy of BugRunner. including Bugs. • An attribute is a piece of information about an ap/compsci_a/ in another folder and then import it into your development environment. • A constructor is a special method that creates new objects. The Student Manual uses vocabulary I have not presented yet. are objects. install GridWorld.pdf. here is a quick preview: • The components of GridWorld.html. so to get you started. which is a program called ap/compsci_a/ap07_gridworld_studmanual_appends_v3. you should have a folder named GridWorldCode that contains projects/firstProject. To get started. like its color or student/testing/ap/compsci_a/case.

gridworld. new is a Java keyword that creates new objects.getLocation()).java contains this code: import Note: If you run this before adding the Bug to the world. BugRunner defines a class that provides a main method. } } The first three lines are import statements. You can find the documentation for these classes at for editing and replace this line: world. • A modifier method changes an attribute of an object. Like the other programs we have seen.add(redBug).44 GridWorld: Part One • An accessor method is a method that returns an attribute of an object.2 BugRunner BugRunner. world.Rock. world. world.add(new Rock()).actor. import info. world. .ActorWorld.greenteapress. The first line assigns the Bug to a variable named redBug.out.Bug. with these lines: Bug redBug = new Bug() Now you should be able to read Part 1 of the Student Manual and do the Bug()).gridworld. The next two lines create a Bug and a Rock. The first line of main creates an ActorWorld object. 5. we can use redBug to invoke the Bug’s methods.add(new Bug()). the result is null. they list the classes from GridWorld used in this program. The last line shows the world on the screen. public class BugRunner { public static void main(String[] args) { ActorWorld world = new ActorWorld(). Open BugRunner. Try this: System. which means that the Bug doesn’t have a location yet. import info. and add them to

c. d. Modify randomBug to take an integer n and repeat n times.html. it invokes turn instead. like Color. which are defined in the Java libraries.0 (not including 1. or create a new color like this: Color purple = new Color( Invoke the methods canMove. You can read the documentation at http://download. Then write a method named colorBug that takes a Bug as a The Math class provides a method named random that returns a double between 0. c. Exercise 5.3 GridWorld uses Color objects. which you can read about at http://en. Then you can access the predefined colors. as a parameter. 180 or 270 with equal probability. To create Bugs with different colors.0 and 1. Now replace the line that creates the ActorWorld with this: ActorWorld world = new ActorWorld(new UnboundedGrid()). Modify moveBug so that if the bug can’t move. The result is a random walk. Write a method named moveBug that takes a bug as a parameter and invokes move. Make a few bugs with different colors. To see a longer random walk. b. Exercise 5. and moves the bug n times (if it can). reads its location. Test your method by calling it from main. At the top of BugRunner. Modify moveBug so that it takes an integer. Now try these exercises: Exercise 5. wikipedia. So you can get the x-coordinate of a Bug like this: . 211).5.2 a. You should be able to run your random walk for a few thousand steps (you might have to use the scrollbars to find the Bug).grid. Write a method named randomBug that takes a Bug as a parameter and sets the Bug’s direction to one of 0.UnboundedGrid. you can give ActorWorld a bigger stage. b. and then moves the bug if it can. and sets the color. d. we have to import Color: import java. add this import statement: import info. Modify moveBug so that it invokes canMove and moves the bug only if it can.2 BugRunner 45 Invoke the other accessor methods and print the bug’s attributes.0). The Location object you get from getLocation has methods named getRow and getCol that return 90. move and turn and be sure you understand what they do.1 a.Color.awt. 0.

getCol().getLocation(). Use the row number to control the red level and the column to control the blue. GridWorld: Part One Write a method named makeBugs that takes an ActorWorld and an integer n and creates n bugs colored according to their location. .46 int x = bug.

so we could have written this method more concisely: . return area. } The first thing you should notice is that the beginning of the method definition is different.Chapter 6 Fruitful methods 6. “return immediately from this method and use the following expression as a return value.sin(angle). we see public static double. that is. In this chapter we write methods that return things. When you invoke a void method. double height = radius * Math. nLines(3). The first example is area. which we usually assign to a variable or use as part of an expression. which I call fruitful methods. which takes a double as a parameter. This statement means. which indicates a void method. For example: double e = Math. with no assignment: countdown(3). That is. and returns the area of a circle with the given radius: public static double area(double radius) { double area = Math. But so far all the methods we have written have been void methods. like the Math functions.PI * radius * radius.1 Return values Some of the Java methods we have used. which means that the return value from this method is a double. I still haven’t explained what public static means.exp(1. but be patient. it is typically on a line by itself. produce results. The last line is a new form of the return statement that includes a return value. the effect of invoking the method is to generate a new value.0). Instead of public static void. methods that return no value.” The expression you provide can be arbitrarily complicated.

} // WRONG!! } This program is not legal because if x is 0.2 Program development At this point you should be able to look at complete Java methods and tell what they do. or any place else where it can never be executed. the type of the expression in the return statement must match the return type of the method.PI * radius * radius. If you put return statements inside a conditional. A typical compiler message would be “return statement required in absoluteValue. neither condition is true and the method ends without hitting a return statement. Although it is legal to have more than one return statement in a method. In either case. temporary variables like area often make debugging easier. when you declare that the return type is double. only one will be executed. I am going . 6. } else if (x > 0) { return x. one in each branch of a conditional: public static double absoluteValue(double x) { if (x < 0) { return -x.48 Fruitful methods public static double area(double radius) { return Math. } else { return x. } } Since these return statements are in an alternative conditional.” which is a confusing message since there are already two of them. But it may not be clear yet how to go about writing them. } On the other hand. the compiler will take you to task. is called dead code. If you try to return with no expression. In other words. Some compilers warn you if part of your code is dead. or an expression with the wrong type. you are making a promise that this method will eventually produce a double. then you have to guarantee that every possible path through the program hits a return statement. For example: public static double absoluteValue(double x) { if (x < 0) { return -x. the method terminates without executing any subsequent statements. Sometimes it is useful to have multiple return statements. Code that appears after a return statement. you should keep in mind that as soon as one is executed.

} The statement return 0.0.println("dx is " + dx).0. and it is natural to represent them using four doubles. the result will be 5 (the hypotenuse of a 3-4-5 triangle). double y1. y2 ). System. In order to test the new method. imagine you want to find the distance between two points. it is useful to know the right answer. but it is worthwhile to try compiling it so we can identify any syntax errors before we add more code. 4. Somewhere in main I would add: double dist = distance(1. double y2) { return 0. 2.out. double x2. although we will see later that there is a Point object in Java that we could use. The return value is the distance. double y2) { double dx = x2 .6. public static double distance (double x1. that way. Already we can write an outline of the method: public static double distance (double x1. we recompile and run the program. The next step is to find the differences x2 − x1 and y2 − y1 . double dy = y2 . we can start adding lines of code one at a time. double x2. we have a good idea where to look: in the last line we added.0. given by the coordinates (x1 . In other words.y1. return 0. Once we have checked the syntax of the method definition. 6. I chose these values so that the horizontal distance is 3 and the vertical distance is 4. we have to invoke it with sample values.0).x1. at this stage the program doesn’t do anything useful.2 Program development to suggest one technique that I call incremental development. which will have type double. 49 As an example. distance = (x2 − x1 )2 + (y2 − y1 )2 (6. If there is an error at any point. double y1. By the usual definition. is a place-keeper that is necessary in order to compile the program.0. System. Obviously. } . After each incremental change. When you are testing a method.println("dy is " + dy).out. what are the inputs (parameters) and what is the output (return value)? In this case. the two points are the parameters. I will store those values in temporary variables named dx and dy.0.1) The first step is to consider what a distance method should look like in Java.0. y1 ) and (x2 .

At any point. Finally. double y1. Nevertheless.x1. but only if it does not make the program difficult to read.out. .0. incremental changes. return 0. • Once the program is working. public static double distance (double x1. double result = Math. The key aspects of the process are: • Start with a working program and make small. this incremental development process can save you a lot of time. but it is not part of the final product. System. double x2.0 and 4. public static double distance (double x1. double dsquared = dx*dx + dy*dy. you will know exactly where it is.println("dsquared is " + dsquared).sqrt to compute and return the result. We could use the Math. } In main. • Use temporary variables to hold intermediate values so you can print and check them. double y1. because it is helpful for building the program.x1. They should be 3.0).50 Fruitful methods I added print statements so we can check the intermediate values before proceeding. return result.y1. The next step is to square dx and dy.sqrt(dsquared). When the method is finished I will remove the print statements.y1. double dy = y2 . double y2) { double dx = x2 . if there is an error. } Again. As you gain more experience programming. double dy = y2 . we can print and check the value of the result. double y2) { double dx = x2 . double dsquared = dx*dx + dy*dy. we can use Math. double x2. I would compile and run the program at this stage and check the intermediate value (which should be 25. you might write and debug more than one line at a time.0.pow method. Code like that is called scaffolding. you can remove scaffolding and consolidate multiple statements into compound expressions. but it is simpler to multiply each term by itself.

double y2) { return area(distance(xc. and return it. So we could rename circleArea: public static double area (double x1. yp)). but once the program is working we can make it more concise by composing the method invocations: public static double circleArea (double xc. we have a method. Wrapping that all up in a method. double xp. we have to provide the radius. you can use it as part of an expression. which is the distance between the two points. If two methods do the same thing. yp). and the perimeter point is in xp and yp. yc. For example. xp. xp. yp)). double y1. double yc. yc. xp. double yp) { return area(distance(xc. } 6. double area = area(radius).6. For area. } . is legal in Java as long as each version takes different parameters. double area = area(radius). and you can build new methods using existing methods. return area.3 Composition 51 6. the center of the circle and a point on the perimeter. what if someone gave you two points. return area. double radius = distance(xc. The first step is to find the radius of the circle.4 Overloading You might have noticed that circleArea and area perform similar functions— finding the area of a circle—but take different parameters. we get: public static double circleArea (double xc. double xp. and asked for the area of the circle? Let’s say the center point is stored in the variables xc and yc. yc. for circleArea we provide two points. Having more than one method with the same name. yc. distance that does that. it is natural to give them the same name. } The temporary variables radius and area are useful for development and debugging. double yc. Fortunately. yp). The second step is to find the area of a circle with that radius.3 Composition Once you define a new method. double x2. double yp) { double radius = distance(xc. xp. which is called overloading.

and so it uses the first version. For booleans. 6. And that reminds me of one of the cardinal rules of debugging: make sure that the version of the program you are looking at is the version of the program that is running! Some day you may find yourself making one change after another in your program. The exceptions we have seen are the relational operators.0). those sets are pretty big.0. This is a warning sign that you are not running the version of the program you think you are. there is a version of abs that works on doubles. or two doubles and produces a double. Java goes looking for a method named area that takes one double as an argument. In the case of ints. which compare ints and floats and return either true or false. doubles and Strings. true and false are special values in Java.0. and there is also a version for ints. 4. For example. If you write: double x = area(1. etc. Many Java methods are overloaded. I said it was a set of values.5 Boolean expressions Most of the operations we have seen produce results that are the same type as their operands. the + operator takes two ints and produces an int. meaning that there are different versions that accept different numbers or types of parameters. And notice that the second version of area actually invokes the first. 6. You might get yourself nicely confused if you are trying to debug one version of a method while accidently invoking a different one. boolean testResult = false.52 Fruitful methods When you invoke an overloaded method. and together they make up a type called boolean. In the Math class. 2. To check. and seeing the same thing every time you run it. Java uses the second version of area. For example.0. bob = true. . Although overloading is a useful feature. not so big. which interprets the argument as a radius. You might recall that when I defined a type. If you write: double x = area(3. add a print statement (it doesn’t matter what you print) and make sure the behavior of the program changes accordingly.0). it should be used with caution. Boolean expressions and variables work just like other types of expressions and variables: boolean bob. there are versions of print and println that accept a single parameter of any type. Java knows which version you want by looking at the arguments that you provide.

// true if n is even // true if x is positive and then use it as part of a conditional statement later: if (evenFlag) { System.out. and the third example is an initialization. if evenFlag is true OR the number is divisible by 3. the second example is an assignment. which are denoted by the symbols &&. || and !. Finally. so they may appear in a different color. The result of a conditional operator is a boolean. so you can store the result of a comparison in a variable: boolean evenFlag = (n%2 == 0). OR and NOT. can you re-write this code using a single conditional? if (x > 0) { if (x < 10) { System.7 Boolean methods Methods can return boolean values just like any other type. } A variable used in this way is called a flag because it flags the presence or absence of some condition.6 Logical operators 53 The first example is a simple variable declaration.6. For example. depending on your development environment. Logical operators can simplify nested conditional statements. 6. the NOT operator inverts a boolean expression."). boolean positiveFlag = (x > 0). which is often convenient for hiding tests inside methods. so !evenFlag is true if evenFlag is false—if the number is odd. For example x > 0 && x < 10 is true only if x is greater than zero AND less than 10.6 Logical operators There are three logical operators in Java: AND.println("n was even when I checked it"). The semantics of these operators is similar to their meaning in English. } } 6.out.println("x is a positive single digit. The values true and false are keywords in Java. For example: public static boolean isSingleDigit(int x) { if (x >= 0 && x < 10) { return true. that is. . evenFlag || n%3 == 0 is true if either of the conditions is true.

although it is a bit longer than it needs to be. } In main you can invoke this method in the usual ways: boolean bigFlag = !isSingleDigit(17). which means that we can compute anything computable. The return type is boolean. The code itself is straightforward. let’s look at some methods for evaluating recursively-defined mathematical functions. in the sense that the definition contains a reference to the thing being defined. A truly circular definition is not very useful: recursive: an adjective used to describe a method that is recursive.println(isSingleDigit(2)).println("x is little"). To give you an idea of what you can do with the tools we have learned so far. which means that every return statement has to provide a boolean expression.out. The most common use of boolean methods is inside conditional statements if (isSingleDigit(x)) { System.out. It is common to give boolean methods names that sound like yes/no questions. org/wiki/Turing_thesis. . } 6. for any reasonable definition of “computable. You can read more about it at http://en.” This idea was developed by Alonzo Church and Alan Turing.out. so it is known as the Church-Turing thesis. Remember that the expression x >= 0 && x < 10 has type boolean.54 } else { return false. } } Fruitful methods The name of this method is isSingleDigit. A recursive definition is similar to a circular definition. so there is nothing wrong with returning it directly and avoiding the if statement altogether: public static boolean isSingleDigit(int x) { return (x >= 0 && x < 10).println("x is big"). System. The first line sets bigFlag to true only if 17 is not a single-digit number.8 More recursion Now that we have methods that return values. } else { System. The second line prints true because 2 is a single-digit number.wikipedia. we have a Turing complete programming language.

int result = n * recurse. If you can write a recursive definition of something. return 1: public static int factorial(int n) { if (n == 0) { return 1. you might be annoyed. and this is the interesting part... n. Otherwise. Since 1 is not zero. which is 2 times 1!. we get 3! equal to 3 times 2 times 1 times 1. you can usually write a Java method to evaluate it. we take the second branch and calculate the factorial of n − 1. If we invoke factorial with the value 3: Since 3 is not zero..8. which is 6. which is not to be confused with the Java logical operator ! which means NOT.) This definition says that the factorial of 0 is 1. So 3! is 3 times 2!.. the method takes an integer as a parameter and returns an integer: public static int factorial(int n) { } If the argument happens to be zero. Since factorial is defined for integers. } } That’s the base case. return result. public static int factorial(int n) { if (n == 0) { return 1. The first step is to decide what the parameters are and what the return type is. we take the second branch and calculate the factorial of n − 1. .6. } } The flow of execution for this program is similar to countdown from Section 4. On the other hand. } else { int recurse = factorial(n-1).8 More recursion 55 If you saw that definition in the dictionary. and then multiply it by n. we take the second branch and calculate the factorial of n − 1. which is 1 times 0!. we have to make a recursive call to find the factorial of n − 1.. you might get something like: 0! = 1 n! = n · (n − 1)! (Factorial is usually denoted with the symbol !. Since 2 is not zero. Putting it all together. and the factorial of any other value. if you looked up the definition of the mathematical function factorial.. is n multiplied by the factorial of n − 1.

The return value (2) gets multiplied by n. .” When you come to a method invocation. An alternative is what I call the “leap of faith. The return value (1) gets multiplied by n. When you invoke Math. you are already practicing this leap of faith when you use Java methods. In fact. Once we convince ourselves that this method is correct— by testing and examination of the code—we can use the method without ever looking at the code again. For example. is returned to main. which is 2. which is 3.cos or System. 6.println. or whoever invoked factorial(3). and the result is returned.9 Leap of faith Following the flow of execution is one way to read programs it can quickly become labarynthine.out. Here is what the stack diagram looks like for this sequence of method invocations: main 6 factorial factorial factorial factorial n 3 n 2 n 1 n 0 recurse 2 recurse 1 recurse 1 result 6 2 result 2 1 result 1 1 The return values are shown being passed back up the stack. Notice that in the last frame recurse and result do not exist because when n=0 the branch that creates them does not execute. 6. instead of following the flow of execution. and the result is returned.7 we wrote a method called isSingleDigit that determines whether a number is between 0 and 9. and the result. you assume that the method works correctly and returns the appropriate value. in Section 6. which is 1. you don’t examine the implementations of those methods. You can apply the same logic to your own methods. we take the first branch and return the value 1 immediately without making any more recursive invocations.56 Fruitful methods Since 0 is zero. The return value (1) gets multiplied by n. You just assume that they work.

it is strange to assume that the method works correctly when you have not even finished writing it. that is. But according to the leap of faith. dead code: Part of a program that can never be executed.10 One more example The second most common example of a recursively-defined mathematical function is fibonacci. Translated into Java. instead of following the flow of execution. and then ask yourself.6. . 6. } } values of n. you can. you should assume that the recursive invocation works.10 One more example 57 The same is true of recursive programs. return value: The value provided as the result of a method invocation. } else { return fibonacci(n-1) + fibonacci(n-2). “Assuming that I can find the factorial of n − 1. one that does not return a value. Of course. scaffolding: Code that is used during program development but is not part of the final version. but that’s why it’s called a leap of faith! 6. When you get to the recursive invocation. by multiplying by n. this is public static int fibonacci(int n) { if (n == 0 || n == 1) { return 1.11 Glossary return type: The part of a method declaration that indicates what type of value the method returns. can I compute the factorial of n?” Yes. void: A special return type that indicates a void method. often because it appears after a return statement. your head explodes. if we assume that the two recursive invocations work correctly. then it is clear that we get the right result by adding them together. which has the following definition: f ibonacci(0) = 1 f ibonacci(1) = 1 f ibonacci(n) = f ibonacci(n − 1) + f ibonacci(n − 2).

exp. which can be difficult.58 Fruitful methods overloading: Having more than one method with the same name but different parameters. 6. flag: A variable(usually boolean) that records a condition or status information. . it is a good idea to test the first method carefully before you start working on the second. boolean: A type of variable that can contain only the two values true and false. Write a method called yikes that takes a double as a parameter and that uses multadd to calculate xe−x + 1 − e−x HINT: the Math method for raising e to a power is Math. Java knows which version to use by looking at the arguments you provide.0.12 Exercises Exercise 6. d. you get a chance to write a method that invokes a method you wrote. Also in main. a. When you invoke an overloaded method. use multadd to compute the following values: sin π 4 + cos π 4 2 log 10 + log 20 e. like 1. 3.1 Write a class method named isDivisible that takes two integers. Create a new program called Multadd. Otherwise. Some processors even provide a hardware implementation of this operation for floating-point numbers. you might find yourself debugging two methods at the same time. Write a method called multadd that takes three doubles as parameters and that returns their multadditionization.0. c. In the last part. logical operator: An operator that combines boolean values and produces boolean values. Whenever you do that. b. Exercise 6. n and m and that returns true if n is divisible by m and false otherwise. One of the purposes of this exercise is to practice pattern-matching: the ability to recognize a specific problem as an instance of a general category of problems. Write a main method that tests multadd by invoking it with a few simple parameters. 2. which takes three operands and computes a*b + conditional operator: An operator that compares two values and produces a boolean that indicates the relationship between the operands.0.2 Many computations can be expressed concisely using the “multadd” operation.

out.3 If you are given three sticks. you can.println(flag1). y1 ) and (x2 . For any three lengths. depending on whether you can or cannot form a triangle from sticks with the given lengths. if one of the sticks is 12 inches long and the other two are one inch long. Exercise 6. } else { hoopyFlag = false.” Write a method named isTriangle that it takes three integers as arguments. } } public static boolean isHoopy(int x) { boolean hoopyFlag. } else { frabjuousFlag = false. then you cannot form a triangle.5 The distance between two points (x1 . there is a simple test to see if it is possible to form a triangle: “If any of the three lengths is greater than the sum of the other two. } return hoopyFlag. The point of this exercise is to use conditional statements to write a fruitful method. if (flag1 && flag2) { System.12 Exercises 59 Exercise 6. public static void main(String[] args) { boolean flag1 = isHoopy(202).out. } Exercise 6. boolean flag2 = isFrabjuous(202). For example.println("pong!"). you may or may not be able to arrange them in a triangle. and that returns either true or false.4 What is the output of the following program? The purpose of this exercise is to make sure you understand logical operators and the flow of execution through fruitful methods. you will not be able to get the short sticks to meet in the middle. } return frabjuousFlag.out. Otherwise. if (x > 0) { frabjuousFlag = true.println(flag2).out.println("ping!"). if (x%2 == 0) { hoopyFlag = true. y2 ) is . System. } if (flag1 || flag2) { System.6. System. } public static boolean isFrabjuous(int x) { boolean frabjuousFlag.

x2 and y2—and that prints the distance between the points. You should write only one method: distance. What is the output of this program? b.60 Fruitful methods Distance = (x2 − x1 )2 + (y2 − y1 )2 Write a method named distance that takes four doubles as parameters—x1. The Ackerman function is defined for non-negative integers as follows: A(m. n-1). Rewrite prod without using the temporary variables recurse and result. n − 1)) if if if m=0 m > 0. You should not write sumSquares or main and you should not invoke distance. public class Prod { public static void main(String[] args) { System. The point of this exercise is to write a new method that uses an existing one.6 The point of this exercise is to use a stack diagram to understand the execution of a recursive program. Exercise 6.0. You should assume that there is a method named sumSquares that calculates and returns the sum of the squares of its arguments. } } } a. int result = n * recurse. } public static int prod(int m. A(m.out. n = 0 m > 0. Draw a stack diagram showing the state of the program just before the last instance of prod completes.7 The purpose of this exercise is to translate a recursive definition into a Java method. } else { int recurse = prod(m. int n) { if (m == n) { return n.0).0 to x. 4. c. Explain in a few words what prod does. would assign the value 25. n) =   n+1 A(m − 1. For example: double x = sumSquares(3.println(prod(1. . return result. Exercise 6. n > 0 Write a method called ack that takes two ints as parameters and that computes and returns the value of the Ackerman function. y1. 4)). 1)  A(m − 1.

Write a method called printString that takes a String as a parameter and that prints the letters of the String. The new String should contain the same letters as the parameter. when n is even. Optional challenge: you can make this method more efficient. using 2 xn = xn/2 .charAt(0). d. one on each line.length(). } b.out. the output of the following code String backwards = reverseString("Allen Downey"). . e. It should be a void method. c.length()).9 Write a recursive method called power that takes a double x and an integer n and that returns xn . should be yenwoD nellA Exercise 6. and make sure you understand what they do. Write a method called reverseString that takes a String as a parameter and that returns a new String as a return value. Also. s.println(backwards). System.8 a. } // length: returns the length of the given String public static int length(String s) { return s. Exercise 6. WARNING: the return value gets very big very quickly. You should try it only for small values of m and n (not bigger than 2).6. Create a program called Recurse. } // last: returns a new String that contains all but the // first letter of the given String public static String rest(String s) { return s. Hint: a recursive definition of this operation is xn = x · xn−1 . Write some code in main that tests each of these methods. Make sure they work.12 Exercises 61 Test your implementation of Ackerman by invoking it from main and printing the return value. For example.substring(1. but in reverse order. Write a method called printBackward that does the same thing as printString but that prints the String backward (one character per line). remember that anything raised to the zeroeth power is and type in the following methods: // first: returns the first character of the given String public static char first(String s) { return s.

10 (This exercise is based on page 44 of Ableson and Sussman’s Structure and Interpretation of Computer Programs. It can be shown that for any two starting numbers. The process is based on the observation that.) The following technique is known as Euclid’s Algorithm because it appears in Euclid’s Elements(Book 7. r) to successively reduce the problem of computing a GCD to the problem of computing the GCD of smaller and smaller pairs of integers. 1 For a definition of “algorithm”. Thus we can use the equation gcd(a.14. 0) = 4 implies that the GCD of 36 and 20 is 4. b) = gcd(b. 4) = gcd(4. if r is the remainder when a is divided by b. It may be the oldest nontrivial algorithm1 . 20) = gcd(20.C. ca. For example. this repeated reduction eventually produces a pair where the second number is 0. . 16) = gcd(16.62 Fruitful methods Exercise 6. jump ahead to Section 11. 300 B.). Then the GCD is the other number in the pair. then the common divisors of a and b are the same as the common divisors of b and r. Write a method called gcd that takes two integer parameters and that uses Euclid’s algorithm to compute and return the greatest common divisor of the two numbers. gcd(36.

When you assign a value to a variable. because the first time we print bob his value is 5. an assignment statement can make two variables equal.println(bob). equality is commutative. This kind of multiple assignment is the reason I described variables as a container for values. it is especially important to distinguish between an assignment statement and a statement of equality. you change the contents of the container. a statement of equality is true for all time. For example. fred fred 5 5 7 When there are multiple assignments to a variable. and the second time his value is 7. The output of this program is 57. bob = 7.print(bob). Furthermore. as shown in the figure: int fred = 5. The effect of the second assignment is to replace the old value with the new.out. If a = b now. in mathematics if a = 7 then 7 = a. Because Java uses the = symbol for assignment. But in Java a = 7. It is not! First of all. then a will always equal b. fred = 7. and assignment is not. in mathematics. is a legal assignment statement. but they don’t have to stay that way! . but it is legal in Java to make more than one assignment to the same variable. and 7 = a. it is tempting to interpret a statement like a = b as a statement of equality. In Java. System. is not. System.1 Multiple assignment I haven’t said much about it. int bob = 5.out.Chapter 7 Iteration 7.

Repeating tasks without making errors is something that computers do well and people do poorly. exit the while statement and continue execution at the next statement. Java provides language features that make it easier to write these methods. 7. yielding true or false. } System. If the condition is false.3 The while statement Using a while statement. int b = a.2 Iteration Computers are often used to automate repetitive tasks. the flow of execution for a while statement is as follows: 1.64 int a = 5. 3.println(n). “While n is greater than zero.or :=. Evaluate the condition in parentheses. We have already seen methods. that use recursion to perform repetition. 2. In some programming languages a different symbol is used for assignment.println("Blastoff!"). it can make the code difficult to read and debug. When you get to zero.out. print the value of n and then reduce the value of n by 1. 7.out. execute the statements between the squigglybrackets. you should use it with caution. such as <. If the values of variables change often. n = n-1. a = 3. also called iteration. print the word ‘Blastoff!”’ More formally. so they are no longer equal. . } You can almost read a while statement like English. and then go back to step 1. we can rewrite countdown: public static void countdown(int n) { while (n > 0) { System. The two features we are going to look at are the while statement and the for statement. If the condition is true. like countdown and factorial. Iteration // a and b are now equal // a and b are no longer equal The third line changes the value of a but it does not change the value of b. Although multiple assignment is frequently useful. in order to avoid this confusion. What this means is.

until we get to 1. if (n%2 == 0) { // n is even n = n / 2. we can prove termination. Since n sometimes increases and sometimes decreases. If the condition is false the first time through the loop. no one has been able to prove it or disprove it! For more information.4 Tables 65 This type of flow is called a loop because the third step loops back around to the top. “Lather. The previous example ends with such a sequence.” are an infinite loop. if the starting value (the argument passed to sequence) is 3. 4. the value of n is divided by two. 16. we can prove that the loop terminates if n is positive. In the case of countdown. At each iteration. } } } The condition for this loop is n != 1. 5. if the starting value is a power of two. 7. In other cases it is not so easy to tell: public static void sequence(int n) { while (n != 1) { System. which will make the condition false. If it is even. eventually.println(n). } else { // n is odd n = n*3 + 1. the resulting sequence is 3. repeat.wikipedia. So far. starting with 16. If it is odd. the interesting question is whether we can prove that this program terminates for all values of n. An endless source of amusement for computer scientists is the observation that the directions on shampoo. see http://en. The body of the loop should change the value of one or more variables so that. Particular values aside.out. the program prints the value of n and then checks whether it is even or odd. people had to calculate . which is called an infinite loop. 10. 1. rinse. the value is replaced by 3n + 1. the condition becomes false and the loop terminates.4 Tables One of the things loops are good for is generating and printing tabular wiki/Collatz_conjecture. 2. For example. For some particular values of n. Otherwise the loop will repeat forever. or that the program will terminate. before computers were readily available.7. so the loop will continue until n is 1. 8. then the value of n will be even every time through the loop. For example. there is no obvious proof that n will ever reach 1. The statements inside the loop are called the body of the loop. For example. the statements inside the loop are never executed.

1) " + Math. Looking at these values.log(x) / Math.out. Soon thereafter computers were so pervasive that the tables became obsolete. and the results were full of errors.1972245773362196 " + Math.wikipedia. To compute them. and then perform computations to improve the approximation.0 0.0 2. Creating these tables was slow and boring. . it still makes a good example of iteration.66 Iteration logarithms.0 3.println(x + " x = x + 1. almost.0 0.0 5.9459101490553132 2.0 computers use tables of values to get an approximate answer.0986122886681098 1. When computers appeared on the scene.log(x)).0) { System. one of the initial reactions was.” That turned out to be true (mostly). In some cases. but shortsighted.log(2. Although a “log table” is not as useful as it once was. while (x < 10.0 7.0794415416798357 2.out. we often want logarithms with respect to base 2. can you tell what base the log method uses? Since powers of two are important in computer science. For some operations.791759469228055 1.6094379124341003 1.0.0)).0 4. most famously in the table the original Intel Pentium used to perform floating-point division1 .6931471805599453 1. Well.0 9. } The output of this program is 1.3862943611198906 1. The following program prints a sequence of values in the left column and their logarithms in the right column: double x = 1. there have been errors in the underlying tables. http://en.println(x + " yields 1 See (7. and other common mathematical functions by hand. we can use the following formula: log2 x = loge x/loge 2 Changing the print statement to System. “This is great! We can use the computers to generate the tables. so there will be no errors. sines and cosines.0. there were books containing long tables where you could find the values of various functions.0 6. To make that easier.

0 2.0 0. while (x < 100.log(2.0 2.0 1. } System.0)).0 3. int i = 1.0 9.out.println(x + " x = x * 2. while (i <= 6) { System.println("").0 2.0 5. we could modify the program like this: double x = 1.0. which yields an arithmetic sequence.0 2. 2.0 1. } " + Math.0 8.print(2*i + " i = i + 1.0 4. If we wanted to find the logarithms of other powers of two.0 4.807354922057604 3.0 1.1699250014423126 67 We can see that 1.0 3. all on one line. 7. A good way to start is to write a simple loop that prints the multiples of 2.5849625007211563 2. ").0 5.log(x) / Math.584962500721156 2.321928094887362 2. we multiply x by something. knowing the powers of two is! When you have an idle moment.0) { System. 4 and 8 are powers of two.0 32. you should memorize the powers of two up to 65536 (that’s 216 ). .0 3.5 Two-dimensional tables A two-dimensional table is a table where you choose a row and a column and read the value at the intersection.0 8.5 Two-dimensional tables 1. A multiplication table is a good example. The result is: 1.0.0 6.0 16.7.0 7.0 64. Now instead of adding something to x each time through the loop.0 4. but for computer scientists.out.0 6. Let’s say you wanted to print a multiplication table for the values from 1 to 6.0 Log tables may not be useful any more.0 0.out. because their logarithms base 2 are round numbers. yielding a geometric sequence.

3 and isSingleDigit in Section 6. The output of this program is: 2 4 6 8 10 12 So far. or loop variable. parameter. allowing you to take advantage of all the things methods are good for. the output is By now you can probably guess how we are going to print a multiplication table: we’ll invoke printMultiples repeatedly with different arguments. which is going to act as a counter. and you forget to invoke println. all I had to do was add the first line.println(""). the output is: 3 4 6 8 9 12 12 16 15 20 18 24 and with argument 4. while (i <= 6) { System. To generalize. 7. Each time through the loop. In some environments the output from print gets stored without being displayed until println is invoked. the value of i increases from 1 to 6. } System. we print the value 2*i and three spaces.print. Here’s a method that encapsulates the loop from the previous section and generalizes it to print multiples of n. We have seen two examples of encapsulation. The next step is to encapsulate and generalize. With argument 3. when i is 7.7. Since we use System.print(n*i + " "). we are going to use another loop to iterate through the rows. like printing the multiples of any integer. As the loop executes. If the program terminates. In fact. the loop terminates.6 Encapsulation and generalization Encapsulation means taking a piece of code and wrapping it up in a method. you may never see the stored output. all I had to do was replace the value 2 with the parameter n. If I invoke this method with the argument 2.out.68 Iteration The first line initializes a variable named i. } To encapsulate. the output appears on a single line. when we wrote printParity in Section 4. I get the same output as before. . public static void printMultiples(int n) { int i = 1. like printing multiples of 2.out. which declares the name.out. and return type. and making it more general. so good. i = i + 1. Generalization means taking something specific.

7. i = i + 1. you can reuse it. Java provides methods that give you more control over the format of the output. 7. The output of this program is 1 2 3 4 5 6 2 4 6 8 10 12 3 4 5 6 6 8 10 12 9 12 15 18 12 16 20 24 15 20 25 30 18 24 30 36 which is a (slightly sloppy) multiplication table.7. } 69 First of all. you make your program easier to read and debug.7 Methods In the Section 3. while (i <= 6) { printMultiples(i). while (i <= 6) { printMultiples(i). } } . • Well-designed methods are often useful for many programs.7 Methods int i = 1. I’ll take the code from the previous section and wrap it up in a method: public static void printMultTable() { int i = 1.8 More encapsulation To demonstrate encapsulation again. • Dividing a long program into methods allows you to separate parts of the program. and then compose them into a whole. Here are more: • By giving a name to a sequence of statements. • Methods facilitate both recursion and iteration. but I’m not going to get into that here. If the sloppiness bothers you. Once you write and debug one. i = i + 1. All I did was replace the print statement with a method invocation. debug them in isolation.5 I listed some of the reasons methods are useful. notice how similar this loop is to the one inside printMultiples.

while (i <= high) { printMultiples(i). Didn’t I say that you can only declare a variable once? And doesn’t it cause problems when one of the methods changes the value of the variable? The answer to both questions is “no. not just the 6x6 table. You could add a parameter to printMultTable: public static void printMultTable(int high) { int i = 1.70 Iteration The process I am demonstrating is a common development plan. For example. it is common to use the names i. This approach lets you design as you go along. If you avoid using them in one method just because you used them somewhere else. and changing the value of one has no effect on the other. you extract it and wrap it up in a method. there are good reasons to reuse names. When you get it working. j and k as loop variables. Variables declared inside a method definition are called local variables because they only exist inside the method. as long as they are not in the same method. You develop code gradually by adding lines to main or another method. and you are free to have multiple variables with the same name.10 More generalization As another example of generalization. imagine you wanted a program that would print a multiplication table of any size. 7. They have the same name. } } I replaced the value 6 with the parameter high. You cannot access a local variable from outside its “home” method.” because the i in printMultiples and the i in printMultTable are not the same variable. i = i + 1. 7.9 Local variables You might wonder how we can use the same variable i in both printMultiples and printMultTable. but they do not refer to the same storage location. you make the program harder to read. If I invoke printMultTable with the argument 7. I get 1 2 2 4 3 6 4 8 5 10 6 12 . Although it can be confusing. This process is useful because sometimes you don’t know when you start writing exactly how to divide the program into methods.

I had to change the first line of the method (the interface or prototype). you often find that it has capabilities you did not plan. } newLine(). Change printMultiples(i. so all the entries in the table appear twice. except that I probably want the table to be square (same number of rows and columns). because ab = ba. . } } Notice that when I added a new parameter. i = i + 1.print(n*i + " "). } public static void printMultTable(int high) { int i = 1. I also call this parameter high.out. For example. int high) { int i = 1. this program generates a square 7x7 table: 1 2 3 4 5 6 7 2 4 6 8 10 12 14 3 4 5 6 7 6 8 10 12 14 9 12 15 18 21 12 16 20 24 28 15 20 25 30 35 18 24 30 36 42 21 28 35 42 49 When you generalize a method appropriately. you only have to change one line of printMultTable. to specify how many columns the table should have.10 More generalization 3 4 5 6 7 6 8 10 12 14 9 12 15 18 12 16 20 24 15 20 25 30 18 24 30 36 21 28 35 42 71 which is fine. You could save ink by printing only half the table. high). you might notice that the multiplication table is symmetric. and I also had to change the place where the method is invoked in printMultTable.7. i). demonstrating that different methods can have parameters with the same name (just like local variables): public static void printMultiples(int n. As expected. while (i <= high) { System. which means I have to add another parameter to printMultiples. i = i + 1. high). to printMultiples(i. while (i <= high) { printMultiples(i. To do that.

7. } . local variable: A variable that is declared inside a method and that exists only within that method. I demonstrated a style of development based on developing code to do simple. In this chapter. Local variables cannot be accessed from outside their home method. In later chapters I will suggest other styles of development.2 I demonstrated incremental development. development plan: A process for developing a program. and sometimes even easier to write. by using local variables). infinite loop: A loop whose condition is always true.1 public static void main(String[] args) { loop(10). 7. generalize: To replace something unnecessarily specific (like a constant value) with something appropriately general (like a variable or parameter).72 and you get 1 2 3 4 5 6 7 4 6 8 10 12 14 Iteration 9 12 15 18 21 16 20 24 28 25 30 35 36 42 49 I’ll leave it up to you to figure out how it works. Generalization makes code more versatile. and do not interfere with any other methods. iteration: One pass through (execution of) the body of the loop.12 Exercises Exercise 7. more likely to be reused. body: The statements inside the loop. encapsulate: To divide a large complex program into components (like methods) and isolate the components from each other (for example. including the evaluation of the condition.11 Glossary loop: A statement that executes repeatedly while some condition is satisfied. specific things. In Section 6. and then encapsulating and generalizing.

then the ith term is xi /i!. if (i%2 == 0) { i = i/2.075 and x3 = 3. and then improve the guess using the following formula: x1 = (x0 + a/x0 )/2 (7. using x1 to calculate x2 . while (i > 0) { System. } else { i = i+1.10 presents a recursive method that computes the factorial function.0001.println(i).75. So that is converging very quickly on the right answer(which is 3). Write a method called squareRoot that takes a double as a parameter and that returns an approximation of the square root of the parameter. and so on.12 Exercises public static void loop(int n) { int i = n.sqrt.0001. What is the output of this program? Exercise 7. We can repeat the procedure. x2 = 3.00091. Write an iterative version of factorial. Exercise 7. Now write an iterative method to perform the same calculation. which is closer. One way to do that is to start with a very rough guess about the answer. } } } 73 a. If the loop variable is named i. then x1 = (6 + 9/6)/2 = 15/4 = 3. and we start with x0 = 6.5 One way to calculate ex is to use the infinite series expansion ex = 1 + x + x2 /2! + x3 /3! + x4 /4! + ..4 Section 6.7. Draw a table that shows the value of the variables i and n during the execution of loop. Your method should iterate until it gets two consecutive estimates that differ by less than 0. Exercise 7. Exercise 7. b. The table should contain one column for each variable and one line for each iteration. which takes a double x and an integer n and returns xn . In this case. As your initial guess. You may not use Math. if we want to find the square root of 9.2 Let’s say you are given a number..3 In Exercise 6. and you want to find its square root. you should use a/2. a.out.9 we wrote a recursive version of power. using this technique. You can use Math. in other words. until the absolute value of xn − xn−1 is less than 0.2) For example.abs to calculate the absolute value.3) . (7. x0 .

2 2 (7. You can use the factorial method from Section 6.pow and factorial.. we need to add up a series of terms where the ith term is equal to (−1)i x2i /i!.708333333333333 2.10 or your iterative version from the previous exercise. and -100. 10. d.0 2. The output should look something like: 1. and check that you still get the same result. Adjust this value until the estimated value agrees with the “correct” answer when x is 1. You should not use factorial or pow.0. c. and that prints the values of x. 1. and 100. f.74 Iteration a.. Exercise 7. .0. How does the accuracy of the result vary as x varies? Compare the number of digits of agreement rather than the difference between the actual and estimated values.0. You can make this method much more efficient if you realize that in each iteration the numerator of the term is the same as its predecessor multiplied by x and the denominator is the same as its predecessor multiplied by i. Write a loop in main that invokes check with the values 0. b. Write a method named gauss that takes x and n as arguments and that returns the sum of the first n terms of the series.6 One way to evaluate e−x is to use the infinite series expansion e−x = 1 − x2 + x4 /6 − x6 /24 + .0. Add a loop in main that checks myexp with the values -0. -10. e.1.718281828459045 HINT: you can use the String "\t" to print a tab character between columns of a table.1.4) In other words.0. -1. Write a method called myexp that adds up the first n terms of this series. Vary the number of terms in the series(the second argument that check sends to myexp) and see the effect on the accuracy of the result. Math. Use this observation to eliminate the use of Math.0. Write a method called check that takes a single parameter. x. Comment on the accuracy.exp(x) and myexp(x) for various values of x.

Unlike string values (which appear in double quotes). Not all characters are letters. The rest are documented at symbols. character values can contain only a single letter or symbol. so you might ask “What is the data contained in a String object?” and “What are the methods we can invoke on String objects?” The data in a String object are letters or. and other things altogether. In order to store the result. But for simplicity I call them letters. There are many methods. which allows you to extract letters from a String.html. but I use only a few in this book. some are numbers. like ’c’. chars work just like the other types we have seen: char bob = ’c’. performing computations and sometimes modifying the object’s data. Strings are objects. Here’s how the charAt method is used: . } Character values appear in single quotes.println(bob). we need a new type: char is the variable type that can store individual characters (as opposed to strings). more generally. The first method we will look at is charAt. if (bob == ’c’) { System. characters.1 Invoking methods on objects In Java and other object-oriented languages. objects are collections of related data that come with a set of methods. These methods operate on the objects.Chapter 8 Strings and things 8.out.

// WRONG!! That won’t work.charAt(length-1). The 1th letter (“oneth”) is a and the 2th (“twooth”) letter is n. char last = fruit. Strings and things fruit. Since we started counting at 0. System. The 0th letter (“zeroeth”) of "banana" is b.length(). Unless you are a computer scientist. 8.charAt() means that I am invoking the charAt method on the object named fruit. If you want the zereoth letter of a string. length takes no arguments and returns an integer. This pattern of processing is called a traversal. Notice that it is legal to have a variable with the same name as a method (although it can be confusing for human readers). you have to pass 0 as an argument: char letter = fruit.charAt(1). The result is a character. To find the last letter of a string. do some computation with it. which means that I want to know the first letter of the string.length(). in this case 6.3 Traversal A common thing to do with a string is start at the beginning. which returns the number of characters in the string.charAt(0). you have to subtract 1 from length. I get a surprise: a a is not the first letter of "banana". A natural way to encode a traversal is with a while statement: . When I print the value of letter. To get the last character.2 Length The next String method we’ll look at is length. you might be tempted to try something like int length = fruit. I am passing the argument 1 to this method. computer scientists start counting from zero. char letter = fruit.println(letter). char last = fruit.out. which is stored in a char named letter. For example: int length = fruit.length(). the 6 letters are numbered from 0 to 5. and continue until the end. For perverse reasons. int length = fruit. 8. select each character in turn. The reason is that there is no 6th letter in "banana".charAt(length).76 String fruit = "banana".

while (index < Reading documentation If you go to http://download. The name of the loop variable is index.length(). 8.4 Run-time errors int index = 0. the next at index 1. An index is a variable or value used to specify a member of an ordered set. .html. The first char value of the sequence is at index 0. in this case the string of characters.3. Then the program terminates. and click on charAt. As an exercise. System. it prints an error message indicating the type of exception and where in the program it occurred.length()) { char letter = fruit. which are errors that don’t appear until a program has started running. If your program causes an exception. An index ranges from 0 to length() . In Java run-time errors are called exceptions. write a method that takes a String as an argument and that prints the letters backwards.out. The index indicates (hence the name) which one you want. all on one line. Notice that the condition is index < fruit. } 77 This loop traverses the string and prints each letter on a line by itself.4 Run-time errors Way back in Section 1. 8.8. If you use the charAt method and provide an index that is negative or greater than length-1.println(letter).com/javase/6/docs/api/java/lang/ String. Well. you will get an exception: specifically. as for array indexing. which means that when index is equal to the length of the string. You probably haven’t seen many run-time errors. because we haven’t been doing many things that can cause one. and so on. The last character we access is the one with the index fruit.1.charAt(index). a StringIndexOutOfBoundsException.length()-1.2 I talked about run-time errors. the condition is false and the body of the loop is not executed. Try it and see how it looks. index = index + 1. now we are. you get the following documentation (or something like it): public char charAt(int index) Returns the char value at the specified index.

Strings and things Returns: the char value at the specified index of this string. .the index of the char value. which indicates the name of the method. it returns the index of the first appearance. It takes a second argument that indicates where in the string to start looking. and returns the value -1. indexOf takes a character and finds the index where that character appears. If the letter happens to appear at the starting index. So int index = fruit. but the documentation is supposed to fit a standard format.78 Parameters: index . the type of the parameters. For an explanation of this kind of overloading. so it is not obvious what indexOf should do. the starting index is the answer. The next line describes what the method does. int index = fruit.if the index argument is negative or not less than the length of this string. If we invoke: int index = fruit. the letter appears three times. The last line explains what exceptions. if any. String fruit = "banana". 2). It might take some time to get comfortable with this kind of documentation. According to the documentation. In order to find subsequent appearances.4. In this case the explanations are a bit redundant. The first char value is at index 0. charAt fails if the index is out of range. there is another version of indexOf. 8. and the return type. The following lines explain the parameters and return values. see Section 6. can be caused by this method. This finds the index of the letter ’a’ in the string. indexOf fails if the character does not appear in the string. 5).indexOf(’a’.6 The indexOf method indexOf is the inverse of charAt: charAt takes an index and returns the character at that index. returns 5.indexOf(’a’. and causes an exception. Throws: IndexOutOfBoundsException . The first line is the method’s prototype.indexOf(’a’). but it is worth the effort. In this case. which is at index 3. it starts at the twoeth letter (the first n) and finds the second a.

count contains the result: the total number of a’s. we can rewrite the letter-counter: int index = 0.charAt(index) == ’a’) { . For example.subtracts one. while (index < length) { if (fruit. you can try it. } index = index + 1. I’m not going to tell you what the result is. encapsulate this code in a method named countLetters. } System.charAt(index) == ’a’) { count = count + 1. As an exercise. while (index < length) { if (fruit.7 Looping and counting 79 8. it is not clear whether the increment will take effect before or after the value is printed. If you really want to know. -. you might see something like: System.println(i++). and generalize it so that it accepts the string and the letter as arguments.println(count). called a counter. int count = 0.length(). to discourage you even more. I discourage you from using them. The variable count is initialized to zero and then incremented each time we find an ’a’ (to increment is to increase by one.7 Looping and counting The following program counts the number of times the letter ’a’ appears in a string: String fruit = "banana". The ++ operator adds one to the current value of an int or char.out.8. In fact. As a second exercise. rather than checking the characters one by one. Looking at this. rewrite the method so that it uses indexOf to locate the a’s. 8. int length = fruit. int index = 0. and unrelated to excrement. Using the increment operators. booleans or Strings. When we exit the loop. it is the opposite of decrement. Neither operator works on doubles.out. Because expressions like this tend to be confusing. it is legal to increment a variable and use it in an expression at the same time. Technically. This program demonstrates a common idiom. which is a noun).8 Increment and decrement operators Incrementing and decrementing are such common operations that Java provides special operators for them.

This is often a difficult bug to track down. } It is a common error to write something like index = index++.80 count++. For example: String name1 = "Alan Turing". but you shouldn’t mix them. like == and >.equals (name2)) { System. 8. but name still contains "Alan Turing". String name2 = "Ada Lovelace". or you can write index++. you get a new String as a return value.compareTo (name2). 8. When you invoke toUpperCase on a String. so the compiler will not warn you. Remember. we have to use the equals and compareTo methods.println("The names are the same. It would be nice if we could use the comparison operators. // WRONG!! Strings and things Unfortunately.9 Strings are immutable As you read the documentation of the String methods. or to see which comes first in alphabetical order. The effect of this statement is to leave the value of index unchanged. String upperName = name. upperName contains the value "ALAN TURING". because strings are immutable. if (name1. you can write index = index+1. because it sounds like they have the effect of changing (or mutating) an existing string. neither these methods nor any others can change a string. For example: String name = "Alan Turing". you might notice toUpperCase and toLowerCase."). but we can’t.toUpperCase(). In order to compare Strings.10 Strings are incomparable It is often necessary to compare strings to see if they are the same.out. After the second line is executed. Actually. . } index++. this is syntactically legal. These methods are often a source of confusion. } int flag = name1.

Otherwise.println("name2 comes before name1.11 Glossary 81 if (flag == 0) { System. index: A variable or value used to select one of the members of an ordered set. true if the strings contain the same characters. exception: A run time error. To compare two things. Just for completeness. counter: A variable used to count something. so for now. you have to invoke a method on one of them and pass the other as an argument."). to use the == operator with Strings. and false otherwise. Using compareTo is often tricky. The return value from compareTo is a weird. The objects we have used so far are Strings. Rocks. If the strings are equal. } else if (flag > 0) { System. decrement: Decrease the value of a variable by one. because the second letter of “Ada” comes before the second letter of “Alan” by 8 letters.println("The names are the same. 8. too. so once you get it you are all set. usually initialized to zero and then incremented.11 Glossary object: A collection of related data that comes with a set of methods that operate on it. like a character from a string."). traverse: To iterate through all the elements of a set performing a similar operation on each. and I never remember which way is which without looking it up. The decrement operator in Java is --. But what that means will not make sense until later.out.println("name1 comes before name2. the difference is negative.out. but very seldom correct. In this case the return value is positive 8. ."). don’t do it. Exceptions cause the execution of a program to terminate. Bugs. and the other GridWorld objects. The increment operator in Java is ++. } The syntax here is a little weird. It is the difference between the first characters in the strings that differ. the difference is positive. If the first string (the one on which the method is invoked) comes first in the alphabet. } else if (flag < 0) { System.out.8. it is 0. increment: Increase the value of a variable by one. I should admit that it is legal. but the good news is that the interface is pretty standard for comparing many types of objects. The return value from equals is straightforward enough.

Encapsulate the following code fragment. } i = i + 1. and what the type of the result is.12 Exercises The purpose of this exercise is to review encapsulation and general- Exercise 8.println(count). you should indicate whether it is legal to use the + operator with these types. int count = 0. c. Exercise 8. if (c == ’(’) { count = count + 1. transforming it into a method that takes a String as an argument and that returns the final value of count.charAt(i). a. } else if (c == ’)’) { count = count . Make a bigger copy of the following table and fill it in. a.2 The point of this exercise is to explore Java types and fill in some of the details that aren’t covered in the chapter. while (i < len) { char c = and write a main method that contains expressions that combine various types using the + operator. } System. Create a new program named Test. At the intersection of each pair of types. Now that you have generalized the code so that it works on any String. b. For example.1. int len = s. describe what the resulting method does (without getting into the details of how). what happens when you “add” a String and a char? Does it perform addition or concatenation? What is the type of the result? (How can you determine the type of the result?) b. boolean char int String boolean char int String . int i = 0. what could you do to generalize it more? String s = "((3 + 7) * 2)".1 ization.length(). what operation is performed (addition or concatenation).82 Strings and things 8. In a sentence or two.out.

12 Exercises 83 c.5 What is the output of the following program? . the method will output 71.out. System. Exercise 8. System. int firstDigit = number/10. explain what the program actually does and modify it so that it does the right thing.1. as if there were no other choice? How many seem like arbitrary choices from several equally reasonable possibilities? How many seem stupid? d.println(i + " total = total + ch. then see if you can figure out what is going on.4 A friend of yours shows you the following method and explains that if number is any two-digit number. He claims that if number is 17. Try it out and see what the error message is. } } " + ch). } return total. x++ is legal. the statement x++ is exactly equivalent to x = x + 1. Exercise 8.length() . int lastDigit = number%10. i--. while (i >= 0 ) { char ch = s. Here’s a puzzler: normally.out. } public static void main(String[] args) { System.println(mystery("Allen")). it’s not! In that case. But if x is a char. Think about some of the choices the designers of Java made when they filled in this table.charAt(i). Exercise 8. String total = "". but x = x + 1 causes an error.println(lastDigit + firstDigit). Is he right? If not. public class Mystery { public static String mystery(String s) { int i = s.8. int number = 17. the program will output the number backwards.3 What is the output of this program? Describe in a sentence what mystery does (not how it works). How many of the entries seem unavoidable.out.

Once you have a working palindrome checker. we might say. } else { enigma(x/2).out. . c.print(x%2). and any other word is a palindrome if the first letter is the same as the last and the middle is a palindrome. figure out a strategy for checking palindromes iteratively. Hint: it might be useful to adopt the definition that the empty string is a palindrome. Optional: Appendix C provides code for reading a list of words from a file. System. Implement your strategy in a method called isPalindromeIter. Hint: read the documentation of the substring method in the String The usual definition of a palindrome is a word that reads the same both forward and backward. } } Explain in 4-5 words what the method enigma really does.” An alternative way to define a property like this is to specify a way of testing for the property.6 a.84 public class Enigma { public static void enigma(int x) { if (x == 0) { return. Read a list of words and print the palindromes. Run a few tests to make sure you understand how substring works before you try to write middle. Write a method named first that takes a String and returns the first letter. There are several possible approaches. so make sure you have a solid plan before you start writing code. For example. On a piece of paper. Exercise 8.println(""). e. } public static void main(String[] args) { enigma(5). h. like “otto” and “palindromeemordnilap. and one named last that returns the last letter.out. } System. Strings and things b. “a single letter is a palindrome.” Write a recursive method named isPalindrome that takes a String and that returns a boolean indicating whether the word is a palindrome or not. g. f. and a two-letter word is a palindrome if the letters are the same. Write a method named middle that takes a String and returns a substring that contains everything except the first and last characters. What happens if you invoke middle on a string that has only two letters? One letter? No letters? d. Create a new program named Palindrome. look for ways to simplify it by reducing the number of conditions you check.

Generalize the Captain Crunch method so that instead of adding 13 to the letters.getLocation().10 If you did the GridWorld exercises in Chapter 5. dimpsy a. deinos. one red and one blue.7 A word is said to be “abecedarian” if the letters in the word appear in alphabetical order. acknow. you might enjoy this exercise. Exercise 8. You should assume that the String contains upper and lower case letters. Describe a process for checking whether a given word (String) is abecedarian. like “llaammaa” or “ssaabb”.12 Exercises 85 Exercise 8. Before you change anything. To test that conjecture. Your process can be iterative or recursive. The goal is to use trigonometry to get the Bugs to chase each other. adempt. named ChaseRunner. dehort. it adds any given amount. ’a’ becomes ’n’ and ’b’ becomes ’o’. the following are all 6-letter English abecedarian words. You should not encode the spaces. but no other punctuation. Now you should be able to encode things by adding 13 and decode them by adding -13. check that you can compile and run it. The Captain Crunch decoder ring works by taking each letter in a string and adding 13 to it. I would like a program that reads words from the dictionary one at a time and checks them for dupledromity.9 a.8 A dupledrome is a word that contains only double letters. dehors. The letters “wrap around” at the end. Write a method that takes a String and that returns a new String containing the encoded version. b. Exercise 8. For example. Make a copy of BugRunner. acorsy. adipsy. For example. I conjecture that there are no dupledromes in common English use. bijoux. Implement your process in a method called isAbecedarian. deflux. • Create two Bugs. Lower case letters should be tranformed into other lower case letters. .getCol().8. behint. chintz. • Write a method called distance that takes two Bugs and computes the distance between them. b. and import it into your development environment. befist. diluvy. Remember that you can get the x-coordinate of a Bug like this: int x = bug. abdest. Exercise 8. upper into upper. and spaces. cestuy. assuming that the word contains only lower-case letters. so ’z’ becomes ’m’. Try it. beknow. Write a method called isDupledrome that takes a String and returns a boolean indicating whether the word is a dupledrome.

• Write a method called moveBugs that takes two Bugs and an integer n. but remember that the result is in radians. you could encapsulate the repeated code in a method. for Bugs. so you have to convert to degrees. and then moves the first one. if you have redundant code in distance and turnToward. or use a while loop. When they are all working.atan2. • Test each of your methods as you develop them. For example. You can write this method recursively. look for opportunities to improve them. 0 degress is North. not East.86 Strings and things • Write a method called turnToward that takes two Bugs and turns one to face the other. • Write a method called moveToward that takes two Bugs. HINT: use Math. if it can. . Also. turns the first to face the second. and moves each Bug toward the other n times.

All import statements appear at the beginning of the program. graphics. which contains almost all of the classes we have seen so far.awt. import java. which is why most of our programs haven’t required an import statement. • They have no attributes.awt package.Point.Rectangle. and java.1 Points and Rectangles Although Strings are objects. outside the class definition. etc. They are values that contain data.awt. Like other values. which contains classes that pertain to the Java Abstract Window Toolkit (AWT). • You don’t have to use new to create one. just like ints and doubles. But first. In this chapter.2 Packages The Java libraries are divided into a number of packages.lang. they are not very interesting. you have to import it. which contains classes for windows.lang. they are used internally to perform computations.awt. 9. buttons. we use two objects from the Java libraries. because • They are immutable. The classes in java. . In order to use a class defined in another package. Point and Rectangle are in the java. I want to make it clear that these points and rectangles are not graphical objects that appear on the screen.Chapter 9 Mutable objects 9. Point and Rectangle. including java. so to import them we need: import java. like Math and String are imported automatically.

Diagrams like this that show the state of the program are called state diagrams. you have to tell me which car is yours. that value is a reference. The arguments are the coordinates of the new point. In mathematical notation. The result of new is a reference to the new point.88 Mutable objects 9.3 Point objects A point is two numbers (coordinates) that we treat collectively as a single object. y) indicates the point x units to the right and y units up from the origin. values. blank = new Point(3. As the program runs. (3. To create a new point. which is shown graphically with an arrow. In Java. x 3 blank y 4 As usual. shown in the figure. (0. Each car is an instance of the type “car. 9. 4). and objects in a program are called the state.4 Instance variables The pieces of data that make up an object are called instance variables because each object. It’s like the glove compartment of a car. points are often written in parentheses. the state changes. and (x. the name of the variable blank appears outside the box and its value appears inside the box. and provides arguments. 4). so blank contains a reference to the newly-created object. Taken together. If you ask me to get something from the glove compartment of your car. There is a standard way to diagram this assignment. you have to use new: Point blank. a point is represented by a Point object. The names x and y are the names of the instance variables. which is an instance of its type. The second line invokes new. so you should think of a state diagram as a snapshot of a particular point in the execution. The big box shows the newly-created object with the two values in it. The arrow points to the object we’re referring to. . has its own copy of the instance variables.” and each car has its own glove compartment. specifies the type of the new object. with a comma separating the coordinates. all the variables. The first line is a conventional variable declaration: blank has type Point. For example. In this case. 0) indicates the origin.

y). You can use dot notation as part of any Java expression. .p1.x . In Java this is done using “dot notation. Other than that.6 Rectangles Rectangles are similar to points. so the following are legal. except that they have four instance variables: x. the second line calculates the value 25.sqrt(dx*dx + dy*dy). we can rewrite the distance method from Section 6.y + ")"). For example: public static void printPoint(Point p) { System. return Math. " + blank. There is no conflict between the local variable named x and the instance variable named x. width and height. I added them as a reminder that the instance variables in a Point are integers. The first line prints 3.y).” In this case we assign that value to a local variable named x. Java already has a method for printing Points. If you invoke printPoint(blank).y . The purpose of dot notation is to identify which variable you are referring to unambiguously. If you invoke System.2 so that it takes two Points as parameters instead of four doubles.” int x = blank. System.y.out. public static double distance(Point p1. you get java.awt. double dy = (double)(p2. " + p. everything is pretty much the same.y * blank.x.y=4] This is a standard format Java uses for printing objects. int distance = blank.9.x * blank.x). The expression blank.x + ".out.x + blank. and get the value of x. Point p2) { double dx = (double)(p2.println(blank.println(blank). 4). it prints (3. } The typecasts are not really necessary.x means “go to the object blank refers to.x + ".p1.5 Objects as parameters 89 Similarly. if you want to read a value from an instance variable. you have to specify the object you want to get it from. y. 4.out. 9. It prints the name of the type.Point[x=3.5 Objects as parameters You can pass objects as parameters in the usual way.println("(" + p. 9. As a second example. } This method takes a point as an argument and prints it in the standard format. Actually. followed by the names and values of the instance variables.


Mutable objects

This example creates a Rectangle object and makes box refer to it. Rectangle box = new Rectangle(0, 0, 100, 200); This figure shows the effect of this assignment.

x box y

0 0

width 100 height 200

If you print box, you get java.awt.Rectangle[x=0,y=0,width=100,height=200] Again, this is the result of a Java method that knows how to print Rectangle objects.


Objects as return types

You can write methods that return objects. For example, findCenter takes a Rectangle as an argument and returns a Point that contains the coordinates of the center of the Rectangle: public static Point findCenter(Rectangle box) { int x = box.x + box.width/2; int y = box.y + box.height/2; return new Point(x, y); } Notice that you can use new to create a new object, and then immediately use the result as a return value.


Objects are mutable

You can change the contents of an object by making an assignment to one of its instance variables. For example, to “move” a rectangle without changing its size, you can modify the x and y values: box.x = box.x + 50; box.y = box.y + 100; The result is shown in the figure:

x box


width 100 height 200

y 100

We can encapsulate this code in a method and generalize it to move the rectangle by any amount:

9.9 Aliasing


public static void moveRect(Rectangle box, int dx, int dy) { box.x = box.x + dx; box.y = box.y + dy; } The variables dx and dy indicate how far to move the rectangle in each direction. Invoking this method has the effect of modifying the Rectangle that is passed as an argument. Rectangle box = new Rectangle(0, 0, 100, 200); moveRect(box, 50, 100); System.out.println(box); prints java.awt.Rectangle[x=50,y=100,width=100,height=200]. Modifying objects by passing them as arguments to methods can be useful, but it can also make debugging more difficult because it is not always clear which method invocations do or do not modify their arguments. Later, I will discuss some pros and cons of this programming style. Java provides methods that operate on Points and Rectangles. You can read the documentation at java/awt/Point.html and api/java/awt/Rectangle.html. For example, translate has the same effect as moveRect, but instead of passing the Rectangle as an argument, you use dot notation: box.translate(50, 100); The effect is the same.



Remember that when you assign an object to a variable, you are assigning a reference to an object. It is possible to have multiple variables that refer to the same object. For example, this code: Rectangle box1 = new Rectangle(0, 0, 100, 200); Rectangle box2 = box1; generates a state diagram that looks like this:

box1 box2

x y

0 0

width 100 height 200

box1 and box2 refer to the same object. In other words, this object has two names, box1 and box2. When a person uses two names, it’s called aliasing. Same thing with objects. When two variables are aliased, any changes that affect one variable also affect the other. For example:

92 System.out.println(box2.width); box1.grow(50, 50); System.out.println(box2.width);

Mutable objects

The first line prints 100, which is the width of the Rectangle referred to by box2. The second line invokes the grow method on box1, which expands the Rectangle by 50 pixels in every direction (see the documentation for more details). The effect is shown in the figure:

box1 box2

x −50 y −50

width 200 height 300

Whatever changes are made to box1 also apply to box2. Thus, the value printed by the third line is 200, the width of the expanded rectangle. (As an aside, it is perfectly legal for the coordinates of a Rectangle to be negative.) As you can tell even from this simple example, code that involves aliasing can get confusing fast, and can be difficult to debug. In general, aliasing should be avoided or used with care.



When you create an object variable, remember that you are creating a reference to an object. Until you make the variable point to an object, the value of the variable is null. null is a special value (and a Java keyword) that means “no object.” The declaration Point blank; is equivalent to this initialization Point blank = null; and is shown in the following state diagram:

The value null is represented by a small square with no arrow. If you try to use a null object, either by accessing an instance variable or invoking a method, you will get a NullPointerException. The system will print an error message and terminate the program. Point blank = null; int x = blank.x; blank.translate(50, 50); // NullPointerException // NullPointerException

On the other hand, it is legal to pass a null object as an argument or receive one as a return value. In fact, it is common to do so, for example to represent an empty set or indicate an error condition.

9.11 Garbage collection



Garbage collection

In Section 9.9 we talked about what happens when more than one variable refers to the same object. What happens when no variable refers to an object? For example: Point blank = new Point(3, 4); blank = null; The first line creates a new Point object and makes blank refer to it. The second line changes blank so that instead of referring to the object, it refers to nothing (the null object).

x 3 blank y 4
If no one refers to an object, then no one can read or write any of its values, or invoke a method on it. In effect, it ceases to exist. We could keep the object in memory, but it would only waste space, so periodically as your program runs, the system looks for stranded objects and reclaims them, in a process called garbage collection. Later, the memory space occupied by the object will be available to be used as part of a new object. You don’t have to do anything to make garbage collection work, and in general you will not be aware of it. But I thought you should know.


Objects and primitives

There are two kinds of types in Java, primitive types and object types. Primitives, like int and boolean begin with lower-case letters; object types begin with upper-case letters. This distinction is useful because it reminds us of some of the differences between them: • When you declare a primitive variable, you get storage space for a primitive value. When you declare an object variable, you get a space for a reference to an object. In order to get space for the object itself, you have to use new. • If you don’t initialize a primitive type, it is given a default value that depends on the type. For example, 0 for ints and true for booleans. The default value for object types is null, which indicates no object. • Primitive variables are well isolated in the sense that there is nothing you can do in one method that will affect a variable in another method. Object variables can be tricky to work with because they are not as well isolated. If you pass a reference to an object as an argument, the method you invoke

state diagram: A snapshot of the state of a program.println(riddle(x. System. You cannot add new primitives to the Java language (unless you get yourself on the standards committee). garbage collection: The process of finding objects that have no references and reclaiming their storage space.14 Exercises Exercise 9. Point blank = new Point(1. AWT: The Abstract Window Toolkit. instance variable: One of the named data items that make up an object. instance: An example from a category.1 a.13 Glossary package: A collection of classes. but you have to be aware of it. a reference appears as an arrow. My cat is an instance of the category “feline things. b. 9. shown graphically.out. blank)).94 Mutable objects might modify the object. For the following program.” Every object is an instance of some class. There is one other difference between primitives and object types. In a state diagram. but you can create new object types! We’ll see how in the next chapter. that can be a good thing. The Java classes are organized in packages. 2). state: A complete description of all the variables and objects and their values.println(x). Each object (instance) has its own copy of the instance variables for its class. in which case you will see the effect. What is the output of this program? public static void main(String[] args) { int x = 5. aliasing: The condition when two or more variables refer to the same object. reference: A value that indicates an object. System. 9. draw a stack diagram showing the local variables and parameters of main and riddle. Of course. . one of the biggest and most commonlyused Java packages.out. and show any objects those variables refer to. at a given point during the execution of a program.

2.y).println(blank. a. return new Point(x. } public static void main(String[] args) { Point blank = new Point(5. At the end of main.x). double dist = distance(center.p2.y . } 95 The point of this exercise is to make sure you understand the mechanism for passing Objects as parameters. int y = box.println(blank. Exercise 9.sqrt(dx*dx + dy*dy).width/2.y.14 Exercises System.height/2. return x + p.x + p. 4. b. System. } Exercise 9. Point center = findCenter(rect). blank). Include all local variables and the objects they refer to. Point p2) { int dx = p1. draw a stack diagram showing the state of the program just before distance returns. } public static int riddle(int x. c. Rectangle rect = new Rectangle( Read the documentation at http://download. Draw a state diagram that shows the state of the program just before the end of main.out.x. y). are p1 and p2 aliased? Why or why not? . Include all variables and parameters and the objects those variables refer to. What is the output of the following program? b. 8).3 The method grow is part of the Rectangle class.out. Point p) { x = x + 7.out.y.y + box. } public static Point findCenter(Rectangle box) { int x = box. What is the output of this program? public static double distance(Point p1. For the following program. return Math.x + box. html#grow(int.println(dist). 4) . int dy = p1.2 a.

html. For example: BigInteger small = BigInteger. The following code converts an integer to a BigInteger: int x = 17.4 You might be sick of the factorial method by now. Instead we have to use methods like add. At some point around 15. Read the documentation of BigIntegers at http://download. Point p1 = findCenter(box1).width/2.valueOf(17). but the one I recommend uses valueOf. BigInteger total = small. Print a table of the integers from 0 to 30 along with their factorials. Because BigIntegers are not primitive types.grow( and write an iterative version of factorial.y + box. f.x + ". There is no upper bound except the limitations of memory size and processing speed. } Mutable objects Exercise 9. 7. e. the usual math operators don’t work.println("(" + p. Point p2 = findCenter(box1).valueOf(1700000000). } public static Point findCenter(Rectangle box) { int x = box. invoke add on one and pass the other as an argument. 9).add(big). Why not? c.out. Type in this code and try it out. 4. like multiply and pow. you will probably see that the answers are not right any more.valueOf(x). BigInteger big = BigInteger. printPoint(p1). b. " + p. .oracle.height/2. box1. but we’re going to do one more version.96 public static void printPoint(Point p) { System.math. you have to add import java. BigInteger big = BigInteger. Create a new program called Big.BigInteger to the beginning of your program.y + ")"). There are several ways to create a BigInteger. d. BigIntegers are Java objects that can represent arbitrarily big integers. To use BigIntegers.x + box. 1). int y = box. printPoint(p2). Try printing a BigInteger. Try out some of the other methods. y). To add two BigIntegers. } public static void main(String[] args) { Rectangle box1 = new Rectangle(2. com/javase/6/docs/api/java/math/BigInteger. a. return new Point(x.

n/2).6 If you are interested in graphics. but don’t use pow. You can leave the parameter alone—it will still be an integer.5 Many encryption techniques depend on the ability to raise large integers to an integer power. the result is t squared // if n is odd. // if n is even. h. Rewrite it so that the result is a BigInteger.9. The last number. now is a good time to read Appendix D and do the exercises there. int n) { if (n==0) return 1. Exercise 9. Here is a method that implements a (reasonably) fast technique for integer exponentiation: public static int pow(int x. } else { return t*t*x. which would spoil the fun. You can use the BigInteger methods add and multiply. but my machine is pretty slow. .14 Exercises 97 g. Exercise 9. 999!. } } The problem with this method is that it only works if the result is smaller than 2 billion. though. has 2565 digits. Convert factorial so that it performs its calculation using BigIntegers and returns a BigInteger as a result. the result is t squared times x if (n%2 == 0) { return t*t. // find x to the n/2 recursively int t = pow(x. so it took a while. Is it correct up to 30? How high can you make it go? I calculated the factorial of all the numbers from 0 to 999. Try printing the table again with your modified factorial method. The parameters should still be integers.

98 Mutable objects .

so you will get a preview now and more details later.add(new Location(7. } } Everything here should be familiar. BoxBug alice = new BoxBug(6).java: import info. alice. which is similar to Point.pdf.Color.add(new Location(5.Chapter 10 GridWorld: Part 2 Part 2 of the GridWorld case study uses some features we haven’t seen yet.gridworld. import There are instructions here that might help: http://www. import ap/compsci_a/ap07_gridworld_installation_guide. public class BoxBugRunner { public static void main(String[] args) { ActorWorld world = new ActorWorld(). world.gif. When you unpack this code. with the possible exception of Location. Copy these files into your working folder and import them into your development environment. BoxBug. Here is the code from BoxBugRunner. BoxBugRunner.awt.gridworld. world.collegeboard. you should have a folder named GridWorldCode that contains projects/boxBug.setColor(Color. bob).ActorWorld. and BoxBug.grid. .ORANGE).Location. which contains BoxBug. 8). BoxBug bob = new BoxBug(3). 5). alice).java contains the class definition for BoxBug.

. which means that a BoxBug is a kind of Bug. If it hits a wall or completes one side of the box. Did you get the behavior you expected? Exercise 10. it moves and increments steps. private int sideLength. and then come back for more fun. Here is the act method for BoxBug: public void act() { if (steps < sideLength && canMove()) { move(). Every Bug has variables named sideLength. } GridWorld: Part 2 } The first line says that this class extends Bug. The next line defines a constructor.100 public class BoxBug extends Bug { private int steps. } } If the BoxBug can move. When you create a Bug by invoking new. steps++. Go do them. turn(). which keeps track of how many steps the Bug has taken so far. The parameter of the constructor is the side length. 10. Run the program and see what it does. and has not taken the required number of steps. public BoxBug(int length) { steps = 0.1 Termites I wrote a class called Termite that extends Bug and adds the ability to interact with flowers. and steps. steps = 0. sideLength = length.1 Now you know enough to do the exercises in the Student Manual. it turns 90 degrees to the right and resets steps to 0. which determines the size of the box it draws. Part 2. } else { turn(). Java invokes this constructor. The next two lines are instance variables. which is a special method that initializes the instance variables. Bug behavior is controlled by the act method.

plus these: /* * Returns true if the termite has a flower.10. which turns left or right 45 degrees at random. if there is one. * */ public void throwFlower(). */ public boolean hasFlower(). so the effect of * dropping a flower is delayed until the termite moves. * and if the termite doesn’t already have a flower. And finally. /* * Drops the flower in the termites current location. */ public boolean seeFlower(). .com/code/ http://thinkapjava.gif http://thinkapjava. /* * Creates a flower unless the termite already has one. */ public void pickUpFlower(). canMove returns false if there is a flower (or any other actor) in the next location. For Termites. Termites have a version of turn that takes an integer number of degrees as a parameter. download these files and import them into your development environment: http://thinkapjava. Termite overrides some Bug methods to change their behaviors. */ public void createFlower(). /* * Throws the flower into the location the termite is Termites have all the same methods as /* * Returns true if the termite is facing a flower. /* * Picks up the flower the termite is facing. Termites have randomTurn. * * Note: only one Actor can occupy a grid In addition.1 Termites 101 To run it. */ public void dropFlower().

java: public class TermiteRunner { public static void main(String[] args) { ActorWorld world = new ActorWorld().java demonstrates the methods that interact with flowers.setColor(Color. world. bob. Termite alice = new Termite(). if (seeFlower()) { pickUpFlower().add(bob). class EternalFlower extends Flower { public void act() {} } If you run TermiteRunner. int n) { for (int i=0. i< Here is the code from TermiteRunner. TermiteRunner creates an ActorWorld with 20 EternalFlowers and two Termites. } } } Everything here should be familiar. Here is the class definition: public class MyTermite extends Termite { public void act() { if (getGrid() == null) return. i++) { you should see two termites moving at random among the flowers. world.add(new EternalFlower()). MyTermite.add(alice). 20). } GridWorld: Part 2 public static void makeFlowers(ActorWorld world. makeFlowers(world. Termite bob = new Termite(). An EternalFlower is a Flower that overrides act so the flowers don’t get darker. } if (hasFlower()) { .

2 Langton’s Termite . The total number of flowers should stay the same (including the ones MyTermites are holding). • Move forward. moving the flowers around. } } 103 MyTermite extends Termite and overrides act. If it has a flower. } randomTurn().java to implement this model. Modify TermiteRunner. } if (canMove()) { move(). Mitchell Resnick describes a simple model of termite behavior: • If you see a flower. Exercise 10.2 The purpose of this exercise is to explore the behavior of Termites that interact with flowers. MyTermites should move around at random. drop the one you have. in that case. Unless you already have a flower.2 Langton’s Termite dropFlower(). but the result is large-scale organization. What effect do you think this change will have on the behavior of MyTermites? Try it out. but over time the flowers accumulate in a small number of piles. • Turn left or right at random. Then run it again. it picks it up. This behavior is an an emergent property. Small changes can have unpredicable results! 10. pick it up. Again. it drops it. Modify MyTermite. Turtles and Traffic Jams.10. Experiment with different rules and see what effect they have on the system. which you can read about at . If MyTermite sees a flower. MyTermites follow simple rules using only small-scale information. often just one. if you can. In Termites. the total number of flowers does not to create MyTermites instead of Termites.

104 GridWorld: Part 2 .

Java invokes a special method called a constructor to initialize the instance variables. we will look at some examples of class definitions that create useful new object types.Chapter 11 Create your own objects 11. In this chapter. . hence. with the same name as the class. when we defined the class named Hello. You provide one or more constructors as part of the class definition. Way back in Section 1. • Every object belongs to some object type. since there is no reason to create a Hello object. • When you invoke new to create an object. which helps distinguish them from primitive types and variable names.5. Here are some syntax issues about class definitions: • Class names(and hence object types) always begin with a capital letter. • Typically all the methods that operate on a type go in the class definition for that type. Here are the most important ideas in this chapter: • Defining a new class also creates a new object type with the same name. and it is not clear what it would be good for if we did. you create a new object type. • A class definition is like a template for objects: it determines what instance variables the objects have and what methods can operate on them. We didn’t create any variables with type Hello. we also created an object type named Hello. and we didn’t use new to create any Hello objects. it is an instance of some class.1 Class definitions and object types Every time you write a class definition. but we could have! That example doesn’t make much sense.

minute and second. For } All by itself. Just to keep things interesting. but it will not be executed. one class is designated as the startup class. the next step is usually to define a constructor for the new class. with the suffix . operated on) as a single unit. Another example. We have already seen two types like this. we need to create instance variables to hold them. The various pieces of information that form a time are the hour. The first step is to decide what type each variable should be. the Time class is defined in the file named Time. like this: class Time { int hour. is Time.0 After declaring the instance variables. It seems clear that hour and minute should be integers. Because every Time object will contain these data. double second. 11. Time. this code fragment is a legal class definition. • In any program. Point and Rectangle. let’s make second a double. Other classes may have a method named main. . The state diagram for a Time object would look like this: hour minute 0 0 second 0. which we will implement ourselves. which is where the execution of the program begins. so we can record fractions of a second.106 Create your own objects • You usually put one class definition in each file. The startup class must contain a method named main.2 Time A common motivation for creating a new Object type is to take several related pieces of data and encapsulate them into an object that can be manipulated (passed as an argument. and the name of the file must be the same as the name of the class. Instance variables are declared at the beginning of the class definition. which is used to record the time of day. outside of any method definition. let’s look at an example of a user-defined type. With those issues out of the way.

0. This constructor does not take any arguments. as indicated by the empty parentheses (). The name this is a special keyword that is the name of the object we are creating. you can read and write the instance variables of this.3 Constructors 107 11. A common error when writing constructors is to put a return statement at the end. = 0. You can use this the same way you use the name of any other object. you are not even allowed to make an assignment to it! this is created by the system.3 Constructors The usual role of a constructor is to initialize the instance variables. = 0. between public and Time. For example: . with three exceptions: • The name of the constructor is the same as the name of the class. The syntax for constructors is similar to that of other methods. Java knows which constructor to invoke by matching the arguments of new with the parameters of the constructors.minute this. which means that you can provide multiple constructors with different parameters. 11. For example. Resist the temptation.second } { 0.11. Here is an example for the Time class: public Time() this. Each line of the constructor initializes an instance variable to an arbitrary default value(in this case.4 More constructors Constructors can be overloaded. Notice that where you would expect to see a return type. • Constructors have no return type and no return value. • The keyword static is omitted. all you have to do is store values in its instance variables. It is very common to have one constructor that takes no arguments(shown above). there is nothing. and one constructor that takes a parameter list that is identical to the list of instance variables. just like other methods. That’s how we(and the compiler) can tell that this is a constructor. and you can pass this as an argument to other methods. But you do not declare this and you do not use new to create it.hour = this. In fact. midnight).

mechanical process. int minute. double second) { this. you will see that both classes provide constructors like this. All the constructor does is copy the information from the parameters to the instance variables. double second. The following program demonstrates two ways to create and initialize Time objects: class Time { int hour. int minute. = 0.minute this. this. } public static void main(String[] args) { // one way to create and initialize a Time object Time t1 = new Time(). If you go back and look at the documentation for Points and Rectangles.minute = minute. So far this might not seem very interesting. minute. this. 11.hour = hour. = 0.second = second. } The names and types of the parameters are exactly the same as the names and types of the instance variables.minute = minute. and in fact it is not.108 Create your own objects public Time(int hour. Once you have written two.hour = this. this. you will find that you can churn them out in your sleep. or to collect all the information before creating the object.0. public Time() this. you never invoke them directly.second = second. Overloading constructors provides the flexibility to create an object first and then fill in the blanks. just by looking at the list of instance variables. this. when you invoke new. double second) { this. .hour = hour.5 Creating a new object Although constructors look like methods.second } { 0. Instead. public Time(int hour. Writing constructors is a boring. the system allocates space for the new object and then invokes your constructor to initialize the instance variables.

11. 8.11. we provide no arguments. if we pass either t1 or t2 as an argument. you usually want to write a method called something like printTime: public static void printTime(Time t) { System. This way of initializing the instance variables is more concise (and slightly more efficient). Also.10. we expect a leading 0 as a place-keeper. since it is not as clear which values are assigned to which instance variables. 3.minute + ":" + t. System.14159. in fact.6 Printing an object The output of this program is: Time@80cc7c0 Time@80cc807 When Java prints the value of a user-defined object type. In most languages. 109 In main.minute = 8.second). we want something like 11:08:03. System. it prints the name of the type and a special hexadecimal(base 16) code that is unique for each object.println(t. if the number of minutes or seconds is less than 10. . it is not quite in the standard format. so Java invokes the first constructor. } Compare this method to the version of printTime in Section 3. but it can be harder to read. In other words. This code is not meaningful in itself.hour = 11. The next few lines assign values to each of the instance variables.out. in case you want to keep track of individual objects. Although this is recognizable as a time. we provide arguments that match the parameters of the second constructor.14159. The second time we invoke new.out.out.second = 3.6 Printing an object t1. figure out the flow of execution through this program. is 11:8:3.hour + ":" + t. The output of this method. it can vary from machine to machine and even from run to run. } } As an exercise. In order to print objects in a way that is more meaningful to users (as opposed to programmers). the first time we invoke new. In Java there are no simple ways.println(t1). t1. // another way to do the same thing Time t2 = new Time(11. we might want to drop the decimal part of the seconds. t1. For example. But it can be useful for debugging.println(t2). there are simple ways to control the output format for numbers.14159).

110 Create your own objects Java provides very powerful tools for printing formatted things like times and dates. you will have a choice of several possible interfaces. we can still write methods that manipulate Time objects. and also for interpreting formatted input. The only result of invoking a pure function is the return value.minute) return false.8 Pure functions A method is considered a pure function if the result depends only on the arguments. Time time2) { if (time1. if (time1. return false. Technically.minute) return true. if (time1.second) return true. this is a type of modifier. Unfortunately. 11.minute > time2. which compares two Times and returns a boolean that indicates whether the first operand comes after the second: public static boolean after(Time time1.7 Operations on objects Even though we can’t print times in an optimal format. If you want. One example is after. I will demonstrate several of the possible interfaces for methods that operate on objects.hour) return true. modifier: Takes objects as arguments and modifies some or all of them. In the next few sections.hour) return false. these tools are not very easy to use. and it has no side effects like modifying an argument or printing something. } What is the result of this method if the two times are equal? Does that seem like the appropriate result for this method? If you were writing the documentation for this method. The return value is either a primitive or a new object created inside the method.hour < time2. so you should consider the pros and cons of each of these: pure function: Takes objects and/or primitives as arguments but does not modify the objects.second > time2. Often returns void. you can take a look at the documentation for the Date class in the java. For some operations. if (time1.hour > time2. so I am going to leave them out of this book.minute < time2. would you mention that case specifically? . if (time1.util package. though. 11. fill-in method: One of the arguments is an “empty” object that gets filled in by the method.

or extra minutes into the hours column. Here is an example of how to use this method. corrected version of this method.second + t2. return sum. if it is 9:14:30.minute -= 60. } Although this method returns a Time object. sum.hour = t1. Time doneTime = addTime(currentTime. which calculates the sum of two times. In that case. then you could use addTime to figure out when the bread will be done.second -= 60.hour += 1. because it is easy to get confused. Here’s a second. } if (sum. sum. printTime(doneTime).hour. Can you think of one? The problem is that this method does not deal with cases where the number of seconds or minutes adds up to more than 60.8 Pure functions 111 A second example is addTime. sum.11. 14.hour.0) { sum. we have to “carry” the extra seconds into the minutes column.minute. public static Time addTime(Time t1. Time breadTime = new Time(3. Time t2) { Time sum = new Time(). For example.second = t1.hour + t2.second.minute. it is not a constructor. sum. Time t2) { Time sum = new Time().minute += 1. Here is a rough draft of this method that is not quite right: public static Time addTime(Time t1.second >= 60. sum.second + t2.minute + t2. sum.minute = t1. and your breadmaker takes 3 hours and 35 minutes. if (sum.hour + t2. 35. .second = t1. 0.minute = t1. sum.hour = t1. sum.0).0).minute + t2. You should go back and compare the syntax of a method like this with the syntax of a constructor. Time currentTime = new Time(9.second. } return sum. breadTime).0.minute >= 60) { sum. there are cases where the result is not correct. On the other hand. The output of this program is 12:49:30. If currentTime contains the current time and breadTime contains the amount of time it takes for your breadmaker to make bread. you could use addTime to figure out when the bread will be done.0. 30. which is correct.

+= and -=.minute -= 60. which adds a given number of seconds to a Time object. time.112 Create your own objects } Although it’s correct. They are similar to ++ and --. This code demonstrates two operators we have not seen before. } } This solution is correct. I will suggest an alternative approach to this problem that will be much shorter. } while (time. Can you think of a solution that does not require iteration? .hour += 1. is equivalent to sum. } if (time. double secs) { time. and(2) the amount of the increment does not have to be 1. Is this method correct? What happens if the argument secs is much greater than 60? In that case. The statement sum. time.second -= 60. a rough draft of this method looks like: public static void increment(Time time.minute += 1.9 Modifiers As an example of a modifier. the remainder deals with the same cases we saw before.0. we have to keep doing it until second is below 60. time.second += secs. consider increment. } } The first line performs the basic operation.second = sum. We can do that by simply replacing the if statements with while statements: public static void increment(Time time. double secs) { time.minute -= 60.minute += 1. it is not enough to subtract 60 once. These operators provide a concise way to increment and decrement variables.0.0. if (time. except(1) they work on doubles as well as ints.second -= 60.second -= 60.second += secs.minute >= 60) { time. while (time. Later.60.second >= 60. Again. but not very efficient.second . it’s starting to get big.0) { time. 11.0) { time.minute >= 60) { time. time.hour += 1.second >= 60.

11. sum.minute = t1.hour + t2. Instead of creating a new object every time addTime is invoked. planning In this chapter I have demonstrated an approach to program development I refer to as rapid prototyping with iterative improvement. Time sum) { sum.hour. if (sum. Nevertheless.second + t2. called functional programming languages.hour = t1. it is worth spending a little run time to avoid a lot of debugging time. we could require the caller to provide an “empty” object where addTime should store the result. 11. Compare the following with the previous version: public static void addTimeFill(Time t1.second -= 60.10 Fill-in methods 113 11.minute. and resort to modifiers only if there is a compelling advantage.11 Which is best? Anything that can be done with modifiers and fill-in methods can also be done with pure functions. In fact. . This approach might be called a functional programming style.minute -= 60. and some cases where functional programs are less efficient. there are programming languages.0. Some programmers believe that programs that use pure functions are faster to develop and less error-prone than programs that use modifiers.12 Incremental development vs.hour += 1. that only allow pure functions. In each case.0) { sum. although it can be confusing enough to cause subtle errors.second >= 60.minute += 1. there are times when modifiers are convenient.second. sum. sum. In general.11.minute + t2.10 Fill-in methods Occasionally you will see methods like addTime written with a different interface(different arguments and return values). Time t2. I recommend that you write pure functions whenever it is reasonable to do so. sum. This can be slightly more efficient. For the vast majority of programming. } } One advantage of this approach is that the caller has the option of reusing the same object repeatedly to perform a series of additions.minute >= 60) { sum.second = t1. } if (sum.

minute =(int)(secs / 60. As an exercise. as usual. this. secs -= this. } This is much shorter than the original version. and it is much easier to demonstrate that it is correct(assuming. correcting flaws as I found them.minute * 60. Although this approach can be effective.minute.hour =(int)(secs / 3600. In this case the insight is that a Time is really a three-digit number in base 60! The second is the “ones column. this. Assuming you are convinced. which is why we had to “carry” from one column to the next. that the methods it invokes are correct). we were effectively doing addition in base 60. and the hour is the “3600’s column. } This constructor is a little different from the others. return seconds. } Now all we need is a way to convert from a double to a Time object. return new Time(seconds). but it might make more sense to write it as a third constructor: public Time(double secs) { this. Time t2) { double seconds = convertToSeconds(t1) + convertToSeconds(t2).second.hour * 60 + t. rewrite increment the same way.” When we wrote addTime and increment.” the minute is the “60’s column”.hour * 3600. Thus an alternative approach to the whole problem is to convert Times into doubles and take advantage of the fact that the computer already knows how to do arithmetic with doubles. we can use these methods to rewrite addTime: public static Time addTime(Time t1. it can lead to code that is unnecessarily complicated—since it deals with many special cases—and unreliable—since it is hard to convince yourself that you have found all the errors.0.0). in which a little insight into the problem can make the programming much easier. You might have to think a bit to convince yourself that the technique I am using to convert from one base to another is correct. . Here is a method that converts a Time into a double: public static double convertToSeconds(Time t) { int minutes = t.114 Create your own objects I wrote a rough draft(or prototype) that performed the basic calculation. We could write a method to do it. and then tested it on a few cases. secs -= this. double seconds = minutes * 60 + t.0). An alternative is high-level planning. since it involves some calculation along with assignments to the instance variables.second = secs.

are the most difficult to express algorithmically. But if we have the insight to treat times as base 60 numbers. For example. and long division are all algorithms. They are mechanical processes in which each step follows from the last according to a simple set of rules. you have written an algorithm. In my opinion. it is embarrassing that humans spend so much time in school learning to execute algorithms that. our intuition for dealing with times is better. without difficulty or conscious thought.” Using the conversion methods would be much easier.13 Generalization In some ways converting from base 60 to base 10 and back is harder than just dealing with times. But if you were “lazy. when you learned to multiply single-digit numbers. For example. 11. Some of the things that people do naturally. you can write n − 1 as the first digit and 10 − n as the second digit. subtraction with borrowing. Ironically.14 Algorithms When you write a general solution for a class of problems. quite literally. and make the investment of writing the conversion methods (convertToSeconds and the third constructor). In effect. and more reliable. fewer opportunities for error). you probably memorized the multiplication table. On the other hand.” you probably cheated by learning a few tricks. you memorized 100 specific solutions. First. but did not define it carefully. It is not easy to define. to find the product of n and 9. so I will try a couple of approaches. sometimes making a problem harder(more general) makes it easier(fewer special cases. so that knowledge is not really algorithmic. One of the characteristics of algorithms is that they do not require any intelligence to carry out. intellectually challenging. easier to read and debug. we get a program that is shorter. and a central part of what we call programming. That’s an algorithm! Similarly. Base conversion is more abstract. This trick is a general solution for multiplying any single-digit number by 9. Understanding natural .11. The naive approach would be to implement subtraction complete with “borrowing. the process of designing algorithms is interesting. consider some things that are not algorithms. the techniques you learned for addition with carrying.13 Generalization 115 11. as opposed to a specific solution to a single problem. require no intelligence. For example. It is also easier to add more features later. imagine subtracting two Times to find the duration between them. I mentioned this word in Chapter 1.

each tile contains a letter. This type of method is usually not the best choice. modifier: A method that changes one or more of the objects it receives as parameters. at least not in the form of an algorithm. and in the rest of the world by J. England..S. In this chapter we learned that a class definition is also a template for a new type of object. We all do it. Berkshire. which is used to spell words. 11. is a registered trademark owned in the U. Later you will have the opportunity to design simple algorithms for a variety of problems.W. fill-in method: A type of method that takes an “empty” object as a parameter and fills in its instance variables instead of generating a return value. Every object is an instance of some class. 11.16 Exercises Exercise 11. instance: A member of a class. 1 Scrabble . and a score. which is used to determine the value of a word. algorithm: A set of instructions for solving a class of problems by a mechanical process. The instance variables should be a character named letter and an integer named value. and usually returns void. Spear & Sons Limited of Maidenhead. but so far no one has been able to explain how we do it.15 Glossary class: Previously. I defined a class as a collection of related methods. and that has no side-effects other than returning a value.116 Create your own objects language is a good example. startup class: The class that contains the main method where execution of the program begins. Write a definition for a class named Tile that represents Scrabble tiles. constructor: A special method that initializes the instance variables of a newly-constructed object. a subsidiary of Mattel Inc. function: A method whose result depends only on its parameters.1 In the board game Scrabble1 . project: A collection of one or more class definitions (one per file) that make up a program. a.A and Canada by Hasbro Inc. functional programming style: A style of program design in which the majority of methods are functions.

} // abs is a function that returns a primitive public static double abs(Complex c) { return Math. Exercise 11.real = real.imag = -c. d.real + " + " + c.0. // simple constructor public Complex() { this. This class should provide two constructors.println(c.real * c.out. this.imag = 0. Write a method named testTile that creates a Tile object with the letter Z and the value 10.imag = imag.imag.real + c. and then uses printTile to print the state of the object. 2/3 is a rational number.2 Write a class definition for Date. month and day. Examine the following program and make sure you understand what it does: public class Complex { double real. For example.sqrt(c. double imag) { this. The second should take parameters named year. The first should take no parameters.0. } public static void printComplex(Complex c) { System. and use them to initialize the instance variables. Write a constructor that takes parameters named letter and value and initializes the instance variables. You can use either constructor. this. For this assignment. } // constructor that takes arguments public Complex(double real.16 Exercises 117 b.imag + "i"). month and day.11. you are going to write a class definition for rational numbers. .imag * c. c. Add code to main that creates a new Date object named birthday. a. imag. Exercise 11. The new object should contain your birthdate. } // conjugate is a modifier public static void conjugate(Complex c) { c. Write a method named printTile that takes a Tile object as a parameter and prints the instance variables in some reader-friendly format.imag). The point of this exercise is to practice the mechanical part of creating a new class definition and code that tests it.real = 0.3 A rational number is a number that can be represented as the ratio of two integers. an object type that contains three integers. year. and you can think of 7 as a rational number with an implicit 1 in the denominator.

Complex s = Complex. Add lines to main to test the new method. // use the second constructor Complex y = new Complex(3.printComplex(x). h. x. Complex b) { return new Complex( that defines a class named Rational. you have a minimal testable(debuggable) program.conjugate(x).printComplex(y). i. j. This method should be a modifier. } } b. At this stage.abs(y)). Write a main method that creates a new object with type Rational. System. 4.real = 1. Complex.imag = 2. test the new method. y). Remember the swap pattern we have seen before.imag). x. Write a constructor that takes no arguments and that sets the two instance variables to zero.add(x.118 } Create your own objects // add is a function that returns a new Complex object public static Complex add(Complex a.0). d.imag + b. sets its instance variables to some values.printComplex(s). Complex. c. Complex. g.out. and prints the object. . it does not modify the object. e. f. Create a new program called Rational. Write a second constructor for your class that takes two arguments and that uses them to initalize the instance variables. a. } public static void main(String args[]) { // use the first constructor Complex x = new Complex(). As always.0. so it should return void. Write a method called invert that inverts the number by swapping the numerator and denominator. Test it and. Write a method called negate that reverses the sign of a rational number. Add lines to main to test the new method.println(Complex.0. Complex. debug it. if necessary. Write a method called toDouble that converts the rational number to a double(floating-point number) and returns the result.0. Write a method called printRational that takes a Rational object as an argument and prints it in some reasonable format.real + b.real. A Rational object should have two integer instance variables to store the numerator and denominator of a rational number. This method is a pure function.

This method should be a pure function. You can use any one you want. l. should contain the sum of the arguments. modifiers and pure functions.16 Exercises 119 k.10). it should not modify the instance variables of the object on which it is invoked. The return object.11. The purpose of this exercise is to write a class definition that includes a variety of methods. including constructors. but you should make sure that the result of the operation is reduced so that the numerator and denominator have no common divisor (other than 1). Write a method called add that takes two Rational numbers as arguments and returns a new Rational object. . There are several ways to add fractions. not surprisingly. You may want to write a method called gcd that finds the greatest common divisor of the numerator and the denominator (See Exercise 6. Write a modifier named reduce that reduces a rational number to its lowest terms by finding the GCD of the numerator and denominator and then dividing top and bottom by the GCD.


Create your own objects

Chapter 12

An array is a set of values where each value is identified by an index. You can make an array of ints, doubles, or any other type, but all the values in an array have to have the same type. Syntactically, array types look like other Java types except they are followed by []. For example, int[] is the type “array of integers” and double[] is the type “array of doubles.” You can declare variables with these types in the usual ways: int[] count; double[] values; Until you initialize these variables, they are set to null. To create the array itself, use new. count = new int[4]; values = new double[size]; The first assignment makes count refer to an array of 4 integers; the second makes values refer to an array of doubles. The number of elements in values depends on size. You can use any integer expression as an array size. The following figure shows how arrays are represented in state diagrams:






The large numbers inside the boxes are the elements of the array. The small numbers outside the boxes are the indices used to identify each box. When you allocate a new array, the elements are initialized to zero.


Accessing elements

To store values in the array, use the [] operator. For example count[0] refers to the “zeroeth” element of the array, and count[1] refers to the “oneth” element.

122 You can use the [] operator anywhere in an expression: count[0] = 7; count[1] = count[0] * 2; count[2]++; count[3] -= 60;


All of these are legal assignment statements. Here is the effect of this code fragment:




1 −60
2 3

By now you should have noticed that the four elements of this array are numbered from 0 to 3, which means that there is no element with the index 4. This should sound familiar, since we saw the same thing with String indices. Nevertheless, it is a common error to go beyond the bounds of an array, which will cause an ArrayOutOfBoundsException. As with all exceptions, you get an error message and the program quits. You can use any expression as an index, as long as it has type int. One of the most common ways to index an array is with a loop variable. For example: int i = 0; while (i < 4) { System.out.println(count[i]); i++; } This is a standard while loop that counts from 0 up to 4, and when the loop variable i is 4, the condition fails and the loop terminates. Thus, the body of the loop is only executed when i is 0, 1, 2 and 3. Each time through the loop we use i as an index into the array, printing the ith element. This type of array traversal is very common. Arrays and loops go together like fava beans and a nice Chianti.


Copying arrays

When you copy an array variable, remember that you are copying a reference to the array. For example: double[] a = new double [3]; double[] b = a; This code creates one array of three doubles, and sets two different variables to refer to it. This situation is a form of aliasing.

a 0.0 b



12.3 for loops


Any changes in either array will be reflected in the other. This is not usually the behavior you want; instead, you should make a copy of the array, by allocating a new array and copying each element from one to the other. double[] b = new double [3]; int i = 0; while (i < 4) { b[i] = a[i]; i++; }


for loops

The loops we have written so far have a number of elements in common. All of them start by initializing a variable; they have a test, or condition, that depends on that variable; and inside the loop they do something to that variable, like increment it. This type of loop is so common that there is an alternative loop statement, called for, that expresses it more concisely. The general syntax looks like this: for (INITIALIZER; CONDITION; INCREMENTOR) { BODY } This statement is exactly equivalent to INITIALIZER; while (CONDITION) { BODY INCREMENTOR } except that it is more concise and, since it puts all the loop-related statements in one place, it is easier to read. For example: for (int i = 0; i < 4; i++) { System.out.println(count[i]); } is equivalent to int i = 0; while (i < 4) { System.out.println(count[i]); i++; } As an exercise, write a for loop to copy the elements of an array.




Arrays and objects

In many ways, arrays behave like objects: • When you declare an array variable, you get a reference to an array. • You have to use new to create the array itself. • When you pass an array as an argument, you pass a reference, which means that the invoked method can change the contents of the array. Some of the objects we have looked at, like Rectangles, are similar to arrays, in the sense that they are named collection of values. This raises the question, “How is an array of 4 integers different from a Rectangle object?” If you go back to the definition of “array” at the beginning of the chapter, you will see one difference, which is that the elements of an array are identified by indices, whereas the elements(instance variables) of an object have names (like x, width, etc.). Another difference between arrays and objects is that all the elements of an array have to be the same type. Although that is also true of Rectangles, we have seen other objects that have instance variables with different types(like Time).


Array length

Actually, arrays do have one named instance variable: length. Not surprisingly, it contains the length of the array(number of elements). It is a good idea to use this value as the upper bound of a loop, rather than a constant value. That way, if the size of the array changes, you won’t have to go through the program changing all the loops; they will work correctly for any size array. for (int i = 0; i < a.length; i++) { b[i] = a[i]; } The last time the body of the loop gets executed, i is a.length - 1, which is the index of the last element. When i is equal to a.length, the condition fails and the body is not executed, which is a good thing, since it would cause an exception. This code assumes that the array b contains at least as many elements as a. As an exercise, write a method called cloneArray that takes an array of integers as a parameter, creates a new array that is the same size, copies the elements from the first array into the new one, and then returns a reference to the new array.

the size of the array.random(). Check out the documentation of the random method in the Math class. Java provides a method that generates pseudorandom numbers. but for our purposes. Each time you invoke random you get the next number in a pseudorandom sequence. and that returns a random double x so that low ≤ x < high. the same number of times. so they are said to be deterministic. How would you generate a random number between low and high? How would you generate a random integer? Exercise 12. and returns a reference to the new array. and that returns a random integer between low and high(including both). To see a sample.7 Array of random numbers If your implementation of randomInt is correct. One way to test your method is to generate a large number of random values. at least approximately. we would like the computer to be unpredictable. low and high. Games are an obvious example.0. i++) { double x = Math.0 and an upper bound like high. To be precise. One of them is to generate random numbers and use them to determine the outcome of the program. store them in an array. Making a program truly nondeterministic turns out to be not so easy.println(x). determinism is a good thing. and count the number of times each value occurs. The return value is a double between 0. low and high. } To generate a random double between 0.6 Random numbers Most computer programs do the same thing every time they are executed. 12.1 Write a method called randomDouble that takes two doubles. which are not truly random in the mathematical sense. but there are many more. The following method takes a single argument.out.0. since we expect the same calculation to yield the same result. every value should appear. fills it with random values. If you generate a long series of numbers. public static int[] randomArray(int n) { int[] a = new int[n]. i < 10. For some applications. run this loop: for (int i = 0. Exercise 12.2 Write a method called randomInt that takes two arguments.12. though. then every value in the range from low to high should have the same probability. but there are ways to make it at least seem nondeterministic.6 Random numbers 125 12. it is greater than or equal to 0.0 and 1. they will do. . Usually. System. It allocates a new array of integers. you can multiply x by high.0 and strictly less than 1.

i++) { a[i] = randomInt(0. the teacher might present the results to the class in the form of a histogram. etc. On my machine the output is 27 6 54 62 54 2 44 81 which is pretty random-looking. } } The following code generates an array and prints it: int numValues = 8. Your results may differ. 100). Also. and that might turn out to be useful. Then you can combine them into a solution. it is not always obvious what sort of things are easy to write. which is a set of counters that keeps track of the number of times each value appear. } return a. i++) { System.length. but a good approach is to look for subproblems that fit a pattern you have seen before.length. 12. To test this method. The next few sections develop code to generate a histogram. printArray(array). . } Arrays The return type is int[].8 Counting A good approach to problems like this is to think of simple methods that are easy to write. we might have ten counters to keep track of how many students scored in the 90s. public static void printArray(int[] a) { for (int i = 0.println(a[i]).out. i<a. which means that this method returns an array of integers. and they would be pretty bad exam scores. Of course.126 for (int i = 0. but as you gain experience you will have a better idea. it is convenient to have a method that prints the contents of an array. int[] array = randomArray(numValues). it is not easy to know ahead of time which methods are likely to be useful. the 80s. For exam scores. If these were exam scores. i<a.

2).12. Would you want to write: int int int .. like an array or a string..9 The histogram 127 Back in Section 8. 80). 3). = inRange(scores. 100). 90). = inRange(scores. 1. 0. = inRange(scores. Here is a method called inRange that counts the number of elements in an array that fall in a given range. = inRange(scores. 0. 60).” The elements of this pattern are: • A set or container that can be traversed. for (int i=0. . count2 = inRange(scores. 2. count1 = inRange(scores. count3 = inRange(scores. 12. i++) { if (a[i] >= low && a[i] < high) count++. all 100 possible values. I wasn’t very careful about whether something equal to low or high falls in the range. 99. 1).7 we looked at a loop that traversed a string and counted the number of times a given letter appeared. int high) { int count = 0. • A counter that keeps track of how many elements pass the test. } In my description of the method. 70. Now we can count the number of scores in the ranges we are interested in: int[] int a int b int c int d int f scores = randomArray(30). but it is acceptable as long as the number of ranges want is small. public static int inRange(int[] a. } return count.length. the container is an array of integers. But now imagine that we want to keep track of the number of times each score appears. The parameters are the array and two integers that specify the lower and upper bounds of the range. but you can see from the code that low is in and high is out. 100). 90. i<a. The test is whether or not a given score falls in a given range of values. = inRange(scores. • A test that you can apply to each element in the container.9 The histogram The code we have so far is a bit repetitious. int count0 = inRange(scores. int low. That should keep us from counting any elements twice. 70). 60. 80. In this case. You can think of this program as an example of a pattern called “traverse and count.

12. It would be better to make a single pass through the array. that computation is trivial. i++) { int index = scores[i]. because we can use the value itself as an index into the array of counters. Here is code that traverses an array of scores. Immediately. inside the loop. once. } The only tricky thing here is that we are using the loop variable in two roles: as in index into the array. the 80s. What we really want is a way to store 100 integers. it traverses the entire array. i < scores. we initialize the array outside the loop. In this example. that is. the 90s. Every time it invokes inRange.3 Encapsulate this code in a method called scoreHist that takes an array of scores and returns a histogram of the values in the array. it is not as efficient as it could be. Modify the method so that the histogram has only 10 counters. i++) { counts[i] = inRange(scores. and count the number of scores in each range of 10 values.length. i+1). etc. In this case. } Exercise 12. preferably so we can use an index to access each one. int[] counts = new int [100]. for (int i = 0. counts[index]++. and each value is identified by an index. i<100. . 12. and as the parameter to inRange. then. where all the values have the same type. that gets to be a lot of traversals. compute which range it falls in. i.10 A single-pass solution Although this code works. you should be thinking “array!” The counting pattern is the same whether we use a single counter or an array of counters. Then we could increment the appropriate counter. and generates a histogram.128 Arrays I don’t think so. for (int i = 0.11 Glossary array: A named collection of values. collection: Any data structure that contains a set of items or elements. and for each value. we invoke inRange and store the result: int[] counts = new int [100]. As the number of ranges increases.

they think variables and methods should be named after fruit. HINT: See Exercise 6. 9 -10 -number of elements in the array that are <= 0 number of elements in the array that are == 1 number of elements in the array that are == 2 number of elements in the array that are == 9 number of elements in the array that are >= 10 Exercise 12. Instead.. if it does. For each variable. but which are actually the product of a deterministic computation. The histogram should contain 11 elements with the following contents: element 0 -1 -2 -.1. index: An integer variable or value used to indicate an element of an array.5 Write a method that takes an array of integers and an integer named target as arguments. public static int banana(int[] a) { int grape = 0. and that returns the first index where target appears in the array.7 Some programmers disagree with the general rule that variables and methods should be given meaningful names. and -1 otherwise.. identify the role it plays.12 Exercises Exercise 12.12. Exercise 12.4 Write a class method named areFactors that takes an integer n and an array of integers. For each of the following methods. histogram: An array of integers where each integer counts the number of values that fall into a certain range. pseudorandom: A sequence of numbers that appear to be random. and that returns true if the numbers in the array are all factors of n (which is to say that n is divisible by all of them). 12. write one sentence that describes abstractly what the method does. int i = 0. i++.12 Exercises 129 element: One of the values in an array.length) { grape = grape + a[i]. deterministic: A program that does the same thing every time it is invoked. The [] operator selects elements of an array. while (i < a.6 Write a method called arrayHist that takes an array of integers and that returns a new histogram array. } return grape. } . Exercise 12.

} public static void main(String[] args) { int[] bob = make(5). int p) { int i = 0. int pear = 0. i++) { fus = fus + zoo[i]. i++. c. for (int i=0. i++) { if (a[i] == p) return i. } return pear. } return a. i++) { a[i] = i+1. .8 a. i++) { jub[i] *= 2.length.length. } return fus. i<jub.130 public static int apple(int[] a. } return -1. while (i < a. Describe in a few words what mus does. i<n. } Arrays The purpose of this exercise is to practice reading code and recognizing the solution patterns we have seen.length) { if (a[i] == p) pear++. i<zoo. Exercise 12. } public static int grapefruit(int[] a. } public static void dub(int[] jub) { for (int i=0. } } public static int mus(int[] zoo) { int fus = 0. public static int[] make(int n) { int[] a = new int[n].length. int p) { for (int i = 0. What is the output of the following program? b. Draw a stack diagram that shows the state of the program just before mus returns. i<a. for (int i=0.

and that swaps the elements at the given indices. Methods like maxInRange can be awkward to use.12. Write a method called max that takes an array as a parameter and that uses maxInRange to find and return the largest value. but it is a useful exercise. Write a recursive version of find using the wrapper-helper pattern. Write a method called sortArray that takes an array of integers and that uses indexOfMaxInRange and swapElement to sort the array from largest to smallest. We will see this pattern again in Section ??. or -1 if it does not appear. 0. To find the largest element in an array. It should return the index of the first location where the target integer appears in the array. we have to provide a range that includes the entire array. we know immediately that the sole element in the range must be the maximum.length-1). If there is more than one element in the range. Write a method called swapElement that takes an array of integers and two indices. b. Exercise 12. Methods like max are sometimes called wrapper methods because they provide a layer of abstraction around an awkward method and provide an interface to the outside world that is easier to use. and then find the maximum of each of the piece-maxima.12 Exercises dub(bob). Write a method called maxInRange that takes an array of integers and a range of indices(lowIndex and highIndex). c.9 Many of the patterns we have seen for traversing arrays can also be written recursively. Exercise 12.10 One not-very-efficient way to sort the elements of an array is to find the largest element and swap it with the first element.11 Write a method called letterHist that takes a String as a parameter and that returns a histogram of the letters in the String. and so on. Write a method called indexOfMaxInRange that takes an array of integers. find the maximum in each of the pieces. This method should be recursive.out. b. It is not common to do so. double max = maxInRange(array. considering only the elements between lowIndex and highIndex. finds the largest element in the given range. The zeroeth element of . a. if lowIndex == highIndex. and that finds the maximum value in the array. If the length of the range is 1. find should take an array of integers and a target integer. So that’s the base case. System. a. that is. and returns its index. You can modify your recursive version of maxInRange or you can write an iterative version from scratch. including both ends. a. then find the second-largest element and swap it with the second. The method that actually performs the computation is called the helper method. we can break the array into two pieces. } 131 Exercise 12. c.println(mus(bob)).

boob. deed. appeases. Toto Write a method called isDoubloon that returns true if the given word is a doubloon and false otherwise. Write a method called testWord that takes these two Strings and returns true if the set of tiles can be used to spell the word. peep. Exercise 12. like "jib". or Java. Otto. Think of an algorithm for testWord that deals with wild cards. murmur. Emmett. there are some blank tiles that can be used as wild cards. noon. the following are all the doubloons I found in my dictionary. using English. Abba.132 Arrays the histogram should contain the number of a’s in the String(upper and lower case). intestines. Anna. arraigning. Exercise 12. Mimi. beriberi. Dada. and the object of the game is to use those letters to spell words. Don’t get bogged down in details of implementation like how to represent wild cards.13 In Scrabble each player has a set of tiles with letters on them. The scoring system is complicated. reappear. Caucasus. appearer. the 25th element should contain the number of z’s. Your solution should only traverse the String once. redder. Exercise 12. pseudocode. but as a rough guide longer words are often worth more than shorter words.14 In real Scrabble. like "qijibo" and you are given another String to test. sees. horseshoer. Shanghaiings. . coco. Hannah. For example. Isis. papa. bilabial. that is. appall. a blank tile can be used to represent any letter. You might have more than one tile with the same letter. but you can only use each tile once.12 A word is said to be a “doubloon” if every letter that appears in the word appears exactly twice. Imagine you are given your set of tiles as a String. Just describe the algorithm. mama.

2. Diamonds and Clubs(in descending order in Bridge). One problem with this . or within another if statement. The suits are Spades. 8. There are 52 cards in a deck. Depending on what game you are playing. and having learned about arrays and objects. it is pretty obvious what the instance variables should be: rank and suit. or else this chapter might not make much sense. you can have objects that contain objects. It is not as obvious what type the instance variables should be.Chapter 13 Arrays of Objects 13. and so on. each of which belongs to one of four suits and one of 13 ranks. etc. Jack. If we want to define a new object to represent a playing card. you can have arrays that contain arrays. containing things like "Spade" for suits and "Queen" for ranks. 6. 3. Having seen this pattern.2 Card objects If you are not familiar with common playing cards. 7. now would be a good time to get a deck. you should not be surprised to learn that you can have arrays of objects. Hearts. One of the first examples we saw was using a method invocation as part of an expression. 5. 4. Another example is the nested structure of statements: you can put an if statement within a while loop. using Card objects as an example. the rank of the Ace may be higher than King or lower than 2. 13. you can also have objects that contain arrays(as instance variables). 9. The ranks are Ace. 10. One possibility is Strings. Queen and King. In the next two chapters we will look at some examples of these combinations.1 Composition By now we have seen several examples of composition(the ability to combine language features in a variety of arrangements). In fact.

The mapping for ranks is fairly obvious. They are part of the program design. The first argument. but they never appear explicitly in the code.134 Arrays of Objects implementation is that it would not be easy to compare cards to see which had higher rank or suit. the first step is usually to declare the instance variables and write constructors. } this. int rank) { this. What a computer scientist means by “encode” is something like “define a mapping between a sequence of numbers and the things I want to represent.suit = 0. The class definition for the Card type looks like this: class Card { int suit. or translate into a secret code. I am providing two constructors. and for face cards: Jack → 11 Queen → 12 King → 13 The reason I am using mathematical notation for these mappings is that they are not part of the Java program. To create an object that represents the 3 of Clubs. } } As usual. public Card() { this.rank = rank. each of the numerical ranks maps to the corresponding integer. 3).” For example. By “encode. The second step is often to write the standard . public Card(int suit. An alternative is to use integers to encode the ranks and suits. one of which takes a parameter for each instance variable and the other of which takes no parameters. Spades Hearts Diamonds Clubs → → → → 3 2 1 0 The obvious feature of this mapping is that the suits map to integers in order. this. so we can compare suits by comparing integers.” I do not mean what some people think.rank = 0. which is to encrypt.suit = suit. rank. 0 represents the suit Clubs. 13. we would use new: Card threeOfClubs = new Card(0.3 The printCard method When you create a new class.

” The output of this code . and assignment. The effect of this statement is identical to that of the separate declaration. "Diamonds".suit]). "9". suits[0] = "Clubs". "Ace". "10". all we need is another array of Strings to decode the ranks: String[] ranks = { "narf". as I will discuss in more detail later. suits[3] = "Spades". This is true of all arrays of objects. "Queen". "Diamonds". "Spades" }. "King" }. "2". "10".13. suits[2] = "Hearts".3 The printCard method 135 methods that every object should have. "8". We could have started at 0. "5". "Hearts". we can select the appropriate Strings by using the suit and rank as indices. A state diagram of this array might look like: suits "Clubs" "Diamonds" "Hearts" "Spades" The elements of the array are references to the Strings. public static void printCard(Card c) { String[] suits = { "Clubs".out. and 3 as 3. of course. suits[1] = "Diamonds". "2". Then we can set the values of the elements of the array. including one that prints the object. we want to map the integer codes onto words. "Ace".rank] + " of " + suits[c. For now. "4". which will never be used. A natural way to do that is with an array of Strings. "King" }. "7". but it is best to encode 2 as 2. as usual. "3". "Jack". "Queen". rather than Strings themselves. The only valid ranks are 1–13. I will start with printCard. String[] ranks = { "narf".suit] means “use the instance variable suit from the object c as an index into the array named suits. "4". This wasted element is not necessary. "6". Creating an array and initializing the elements is such a common operation that Java provides a special syntax for it: String[] suits = { "Clubs". } the expression suits[c. Using these arrays. In order to print Card objects in a way that humans can read easily. System. "8". The reason for the "narf" is to act as a place-keeper for the zeroeth element of the array. etc. "6". and one or two that compare objects. allocation. "5". "3". "7". In the method printCard. "Hearts".println(ranks[c. "Spades" }. and select the appropriate string. You can create an array of Strings the same way you create an array of primitive types: String[] suits = new String [4]. "Jack". "9".

").” I mean that his car and mine are the same make and model. } In this case. 11). we can use sameCard to see if they represent the same card: Card card1 = new Card(1. Card card2 = card1. When you talk about objects. if I say “Chris and I have the same car. } This type of equality is called shallow equality because it only compares the references. If I say “Chris and I have the same mother. Arrays of Objects 13.out. there is a similar ambiguity.rank == c2. if (sameCard(card1. } Now if we create two different objects that contain the same data. or they are actually the same Card object? To see if two references refer to the same object. card2)) { System.suit && c1. card1 and card2 are two different objects that contain the same data . For example: Card card1 = new Card(1.4 The sameCard method The word “same” is one of those things that occur in natural language that seem perfectly clear until you give it some thought.println("card1 and card2 are the same card.suit == c2. we can use the == operator. not the contents of the objects. 11).136 Card card = new Card(1.println("card1 and card2 are the same object. 11). if (card1 == card2) { System. and then you realize there is more to it than you expected. public static boolean sameCard(Card c1. To compare the contents of the objects—deep equality—it is common to write a method with a name like sameCard. So the idea of “sameness” is different depending on the context. but they are two different cars. For example.rank).out. does that mean they contain the same data(rank and suit). if two Cards are the same.” I mean that his mother and mine are one and the same. printCard(card). Card c2) { return(c1."). Card card2 = new Card(1. For example. is Jack of Diamonds. 11).

In order to make cards comparable. which is why we cannot compare apples and oranges. Instead of comparing the contents of the String (deep equality). and the 3 of Diamonds is higher than the 3 of Clubs. These operators(< and > and the others) don’t work for object types. there are conditional operators that compare values and determine when one is greater or less than another. we have to decide which is more important. the boolean type is unordered. It will take two Cards as parameters and return 1 if the first card wins. the integers and the floatingpoint numbers are totally ordered. Some sets are completely ordered. the fruits are unordered. For example. It is sometimes confusing to keep those return values straight. but the other has a higher suit. The set of playing cards is partially ordered. it checks whether the two Strings are the same object(shallow equality). and 0 if they tie(indicating deep equality). which means that sometimes we can compare cards and sometimes not. it comes sorted with all the Clubs together. followed by all the Diamonds. we will use this method to sort a deck of cards.5 The compareCard method 137 suit card1 1 card2 suit 1 rank 11 rank 11 so the condition is true. which means that there is no meaningful way to say that one element is bigger than another. To be honest. rank or suit. and so on. 13. Later. But which is better.5 The compareCard method For primitive types.10 I said that you should never use the == operator on Strings because it does not do what you expect. the choice is completely arbitrary.13. For example. we cannot say that true is greater than false. For Strings Java provides a compareTo method. What does the state diagram look like when card1 == card2 is true? In Section 8. I will say that suit is more important. -1 if the second card wins. which we will call compareCard. First we compare the suits: . With that decided. I know that the 3 of Clubs is higher than the 2 of Clubs. For Cards we have to write our own. the 3 of Clubs or the 2 of Diamonds? One has a higher rank. For the sake of choosing. but they are pretty standard for comparison methods. because when you buy a new deck of cards. In Java. Some sets are unordered. we can write compareCard. For example. which means that you can compare any two elements and tell which is bigger.

Arrays of Objects If neither statement is true.rank. that is the correct syntax for accessing the rank of the “twoeth” card in the deck(really the third—we started at zero. The values of the array elements are initialized to null. rank <= 13. suit <= 3. remember?).suit) return -1.rank) return -1. If neither of these is true. the ranks must be equal. rank++) { deck[index] = new Card(suit. aces will appear lower than deuces(2s). Here is some code that creates a new deck of 52 cards: Card[] deck = new Card [52]. and we have to compare ranks: if (c1. then the suits must be equal. rank). deck[2]. fix it so that aces are ranked higher than Kings. and encapsulate this code in a method.rank < c2. You can access the elements of the array in the usual way: if (deck[3] == null) { System. 13.138 if (c1. it does not contain any Card objects. suit++) { for (int rank = 1.suit < c2. // NullPointerException Nevertheless. if (c1.6 Arrays of cards The reason I chose Cards as the objects for this chapter is that there is an obvious use for an array of cards—a deck. so we return 0. Here is the state diagram for this object: 0 1 2 3 51 deck The important thing to see here is that the array contains only references to objects. In this ordering. if (c1. This is another example of composition. . you will get a NullPointerException.rank) return 1.rank > c2.println("No cards yet!").suit > c2.suit) return 1. for (int suit = 0. } But if you try to access the instance variables of the non-existent Cards. The easiest way to populate the deck with Card objects is to write a nested loop: int index = 0. As an exercise.out. the combination of the syntax for accessing an element of an array and an instance variable of an object.

} } 139 The outer loop enumerates the suits. 13. a linear search and a bisection search.7 The printDeck method Whenever you are working with arrays. For each suit.1 Encapsulate this deck-building code in a method called buildDeck that takes no parameters and that returns a fully-populated array of Cards. 13.length. Since the outer loop iterates 4 times.13. I used the variable index to keep track of where in the deck the next card should go. i++) { printCard(deck[i]). an element of deck has type Card. which searches through an array of Cards to see whether it contains a certain card. the total number of times the body is executed is 52(13 times 4). } } Since deck has type Card[]. from 1 to 13. We have seen the pattern for traversing an array several times. so the following method should be familiar: public static void printDeck(Card[] deck) { for (int i=0. from 0 to 3. and the inner loop iterates 13 times. Therefore. It may not be obvious why this method would be useful. but it gives me a chance to demonstrate two ways to go searching for things.8 Searching The next method I want to write is findCard. i<deck.7 The printDeck method index++. the inner loop enumerates the ranks. deck[i] is a legal argument for printCard. it is convenient to have a method that will print the contents of the array. . The following state diagram shows what the deck looks like after the first two cards have been allocated: 0 1 2 3 51 deck suit rank 0 1 suit rank 0 2 Exercise 13.

We have to look at every card. This is legal and common. although it can sometimes make code hard to read. there is no way to search that is faster than this. In the case of a deck of cards. If the cards in the deck are not in order. flip to somewhere later in the dictionary and go to step 2. If you ever get to the point where there are two adjacent words on the page and your word comes between them. If it is not in the deck. we return -1. If we find it we return the index where the card appears. Card card) { for (int i = 0. if we know that the cards are in order. The best way to write a bisection search is with a recursive method. If the loop terminates without finding the card.length. flip to somewhere earlier in the dictionary and go to step 2. It might seem odd to have a variable with the same name as a type(the card variable has type Card). we know the card is not in the deck and return -1. } The arguments of findCard are named card and deck. . If the word you are looking for comes before the word on the page. you probably use an algorithm that is similar to a bisection search: 1. public static int findCard(Card[] deck. If you found the word you are looking for. I think it works. i++) { if (sameCard(deck[i]. 5. If the word you are looking for comes after the word on the page. it involves traversing the deck and comparing each card to the one we are looking for. That’s because bisection is naturally recursive. which means that we do not have to traverse the entire deck if we find the card we are looking for. we can write a version of findCard that is much faster. 2. but that contradicts our assumption that the words are in alphabetical order. i< deck. The only alternative is that your word has been misfiled somewhere. you don’t search linearly through every word. Start in the middle somewhere. 3. you can conclude that your word is not in the dictionary. The reason is that the words are in alphabetical order. stop.140 Arrays of Objects Linear search is the more obvious of the two. As a result. In this case. though. since otherwise there is no way to be certain the card we want is not there. But when you look for a word in a dictionary. 4. Choose a word on the page and compare it to the word you are looking for. card)) return i. } return -1. The method returns as soon as it discovers the card.

To search the array. int low. With that line added. the method works correctly: public static int findBisect(Card[] deck. int low. it will recurse forever. int high) { System. mid-1). card.println(low + ". 4. if the card is not in the deck. int high) { int mid =(high + low) / 2. } else if (comp > 0) { return findBisect(deck. low. I called it once and stored the result. search in the range from low to mid-1. search in the range from mid+1 to high. " + high). 2. Card card. Although this code contains the kernel of a bisection search. Steps 3 and 4 look suspiciously like recursive invocations. 3. it is still missing a piece. The easiest way to tell that your card is not in the deck is if there are no cards in the deck. of course. low and high.13.compareCard(card). if (comp == 0) { return mid. indicating the segment of the array that should be searched(including both low and high). mid+1. } else { return findBisect(deck. high). . If you found it. 1.8 Searching 141 The trick is to write a method called findBisect that takes two indices as parameters. Here’s what this all looks like translated into Java code: public static int findBisect(Card[] deck. Well. stop. If the card at mid is lower than your card. int comp = compareCard(deck[mid]. } } Rather than call compareCard three times. card. if (high < low) return -1. card).out. choose an index between low and high(call it mid) and compare it to the card you are looking for. int comp = deck[mid]. which is the case if high is less than low. but what I mean is that there are no cards in the segment of the deck indicated by low and high. We need a way to detect this condition and deal with it properly (by returning -1). If the card at mid is higher than your card. int mid =(high + low) / 2. Card card. As it is currently written. there are still cards in the deck.

In fact. by looking at a few cases and examining the code. 12 -1 These tests don’t prove that this program is correct. and even more so for large arrays. typically 6 or 7. bisection is much faster than a linear search. } else if (comp > 0) { return findBisect(deck.println(findBisect(deck. I got the following: 0. 24 13. I tried out the following code: Card card1 = new Card(1.142 Arrays of Objects if (comp == 0) { return mid. Two common errors in recusive programs are forgetting to include a base case and writing the recursive call so that the base case is never reached. in which case Java will(eventually) throw a StackOverflowException. mid+1. card. In general. The number of recursive invocations is fairly small.out. Either error will cause an infinite recursion. 24 13. 24 22. } } I added a print statement at the beginning so I could watch the sequence of recursive invocations and convince myself that it would eventually reach the base case. 51 0. 24 19. card1. 24 23 Then I made up a card that is not in the deck(the 15 of Diamonds). 51)). 14 13. 11). 17 13. low. System. and tried to find it. . card. high). you might be able to convince yourself. 24 13. That means we only had to invoke compareCard 6 or 7 times. mid-1). 51 0. } else { return findBisect(deck. no amount of testing can prove that a program is correct. 0. And got the following output: 0. On the other hand. compared to up to 52 times if we did a linear search.

For example. then the current value is irrelevant. but which describes the function of the program at a higher level. and I sometimes think of it as an abstract parameter. is a very important part of thinking like a computer scientist. as a subdeck. All variables have values all the time. as a single parameter that specifies a subdeck.10 Glossary encode: To represent one set of values using another set of values. But if the program guarantees that the current value of a variable is never read before it is written.” 13.” This kind of thinking. So you are not literally sending a subset of the deck.9 Decks and subdecks 143 13. Two references that point to objects that have the same value. you are really sending the whole deck. it makes sense to think of it. abstractly. they are given default values.” is something that is not literally part of the program text. But as long as the recipient plays by the rules. A more general definition of “abstraction” is “The process of modeling a complex system with a simplified description in order to suppress unnecessary details while capturing relevant behavior.9 Decks and subdecks Looking at the interface to findBisect public static int findBisect(Card[] deck. Sometimes. abstract parameter: A set of parameters that act together as a single parameter. . The reason I put “empty” in quotation marks was to suggest that it is not literally accurate. int low. in which a program comes to take on meaning beyond what is literally encoded. When you create them. int high) it might make sense to think of three of the parameters. Abstractly. shallow equality: Equality of references. abstraction is a central idea in computer science(as well as many other fields). Card card. there is nothing that prevents the invoked method from accessing parts of the array that are out of bounds. So there is no such thing as an empty object. the word “abstract” gets used so often and in so many contexts that it comes to lose its meaning. it makes sense to think of such a variable as “empty.13. This way of thinking is quite common. There is one other example of this kind of abstraction that you might have noticed in Section 11. deck. deep equality: Equality of values. low and high.7. What I mean by “abstract. when I referred to an “empty” data structure. by constructing a mapping between them. Two references that point to the same object. Nevertheless. when you invoke a method and pass an array and the bounds low and high.

You can assume that the String contains the name of a card in a valid format. for all other cards the score is the same as the rank. Jack. You should assume that the ranks of the cards are encoded according to the mapping in Section 13. The score for each card is as follows: aces count as 1.2 Imagine a card game in which the objective is to get a collection of cards with a total score of 21. 13. . the method should return a null object. The total score for a hand is the total of the scores for all the cards.” and between the word “of” and the suit. Exercise 13. 10.5 Write a method called isFlush that takes an array of Cards as a parameter and that returns true if the hand contains a flush. Exercise 13. The purpose of this problem is to review the concept of parsing and implement a method that parses a specific set of strings. If the string does not contain a legal card name.2.144 Arrays of Objects abstraction: The process of interpreting a program (or anything else) at a higher level than what is literally represented by the code. as if it had been produced by printCard. Write a method called handScore that takes an array of cards as an argument and that adds up(and returns) the total score. Exercise 13. and false otherwise. In other words.4 Write a method called suitHist that takes an array of Cards as a parameter and that returns a histogram of the suits in the hand. 3) has a total score of 1 + 10 + 10 + 3 = 24. A flush is a poker hand that contains five or more cards of the same suit.3 The printCard method in Section 13.3 takes a Card object and returns a string representation of the card. Example: the hand(Ace. the string will contain a single space between the rank and the word “of. all face cards count as ten.11 Exercises Exercise 13. Write a class method for the Card class called parseCard that takes a String and returns the corresponding card. Your solution should only traverse the array once. with Aces encoded as 1.

} } The name of the instance variable is cards to help distinguish the Deck object from the array of Cards that it contains. For that we could write another constructor that creates a standard 52-card deck and populates it with Card objects: public Deck() { cards = new Card[52]. but I also mentioned that it is possible to have an object that contains an array as an instance variable. but in this case it uses new to create the array of cards. that contains an array of Cards as an instance variable.Chapter 14 Objects of Arrays 14. for (int suit = 0. public Deck(int n) { cards = new Card[n]. we worked with an array of objects. Here is a state diagram showing what a Deck object looks like with no cards allocated: deck cards As usual. It doesn’t create any cards to go in it. int index = 0. suit++) { . the constructor initializes the instance variable. called a Deck. suit <= 3. In this chapter we are going to create a new object. though.1 The Deck class In the previous chapter. The class definition looks like this class Deck { Card[] cards.

we have to use deck. To invoke it. But a computer program would have the annoying property of doing a perfect shuffle every time.146 for (int rank = 1. an array. that is. except that we had to change the syntax to make it a constructor. The second change is that we can no longer use deck. not an array. Therefore.6 we saw how to generate random numbers.printCard(deck. For some of the other[i]). Looking at the methods we have written so far. } } } Objects of Arrays Notice how similar this method is to findCard takes a Card and a Deck as arguments.2 Shuffling For most card games you need to be able to shuffle the deck. one obvious candidate is printDeck(Section 13. but it is not. It contains an array.length. it is not obvious whether they should be included in the Card class or the Deck[i] to access an element of the array. which is usually by dividing the deck in two and then reassembling the deck by choosing alternately from each deck. because deck is a Deck object now. but it is not obvious how to use them to shuffle a deck. As an exercise. we use new: Deck deck = new Deck(). put the cards in a random order. after about 7 iterations the order of the deck is pretty well randomized. Here’s how it looks.7). rank). rank <= 13. In Section 12. i++) { Card. Now that we have a Deck class. rewritten to work with a Deck object: public static void printDeck(Deck deck) { for (int i=0. move findCard into the Deck class and rewrite it so that the first parameter is a Deck object rather than an array of Cards. from Card[] to Deck. rank++) { cards[index] = new Card(suit. 14. index++. } } The most obvious thing we have to change is the type of the parameter. The last change is that the invocation of printCard has to say explicitly that printCard is defined in the Card class. Since humans usually don’t shuffle perfectly.length to extract the array from the Deck object and get the length of the array. One possibility is to model the way humans shuffle. For example. For the same reason. we have to write deck. itself. it makes sense to put all the methods that pertain to Decks in the Deck class definition. rather than just deck[i]. you could reasonably put it in either i<deck.length to get the length of the array. which is not .

Here is pseudocode for selection sort: for (int i=0. During the ith.3 Sorting Now that we have messed up the deck.length. To sketch the program. I am using a combination of Java statements and English words that is sometimes called pseudocode: for (int i=0. we need something like randomInt.html or do a web search with the keywords “perfect shuffle. Does it matter which one you choose? Which is faster? I will leave the remaining implementation of these methods as an exercise. Here is an outline of how this algorithm works. and swapCards which takes two indices and switches the cards at the indicated positions. You can also figure out swapCards yourself. In after 8 perfect shuffles. and at each iteration choose two cards and swap them.length. we need a way to put it back in order. The only tricky thing is to decide whether to swap just the references to the cards or the contents of the cards. i<deck. 14. In this case. which chooses a random integer between the parameters low and high. i<deck. you would find the deck back in the same order you started in. This algorithm is sometimes called selection sort because it works by traversing the array repeatedly and selecting the lowest remaining card each time. i++) { // find the lowest card at or to the right of i // swap the ith card and the lowest card } . You can probably figure out how to write randomInt by looking at Section 12.3 Sorting 147 really very random.14. we find the lowest card to the right of i and swap it with the ith card.” A better shuffling algorithm is to traverse the deck one card at a time. see http://www.wiskit.length // swap the ith card and the randomly-chosen card } The nice thing about using pseudocode is that it often makes it clear what methods you are going to need. there is an algorithm for sorting that is very similar to the algorithm for shuffling. i++) { // choose a random number between i and deck. For a discussion of that claim. although you will have to be careful about possibly generating indices that are out of range. During the first iteration we find the lowest card and swap it with the card in the 0th position.

so we only need one new one.e. the one I will demonstrate.148 Objects of Arrays[i] = deck. } return sub. Once again. they are aliased.length. i<sub. i++) { sub. In this case we can use swapCards again. the subdeck gets populated with copies of the references from the deck. I am going to leave the implementation up to the reader. which might extend Deck. for (int i =[low+i]. is to represent a hand with a Deck object that happens to have fewer than 52 cards. subdeck. 14. Because we provide an argument with new. int low. The result is a hand with 5 cards that are shared with the original deck. deck cards sub cards . int high) { Deck sub = new Deck(high-low+1). We might want a method. This sort of computation can be confusing.4 Subdecks How should we represent a hand or some other subset of a full deck? One possibility is to create a new class called Hand. i. called findLowestCard. that takes a Deck and a range of indices. that takes an array of cards and an index where it should start looking. the pseudocode helps with the design of the helper methods. Inside the for loop. Drawing a picture is usually the best way to avoid them. Another and lead to “off-by-one” errors. The following is a state diagram of a subdeck being created with the parameters low=3 and high=7. which only allocates the array and doesn’t allocate any cards. and that returns a new Deck that contains the specified subset of the cards: public static Deck subdeck(Deck deck. the contructor that gets invoked will be the first one. } The length of the subdeck is high-low+1 because both the low card and high card are included.

Beware of misleading analogies. The total time. The round-robin convention is intended to mitigate imperfect shuffling and make it more difficult for the dealer to cheat. we can create and shuffle a deck: Deck deck = new Deck(). and the rest into the pack. To sort n items. When you thought about dealing. the next 5 cards in the other. This code puts the first 5 cards in one hand. it has to traverse the array n times.14. That may not seem impressive. then aliasing is less dangerous. 4). but then realized that it is unnecessary for a computer program. Assuming that we have a method called shuffleDeck that takes a deck as an argument and shuffles it. mergesort takes time proportional to n log n. Then. Deck pack = subdeck(deck. .5 Shuffling and dealing In Section 14. This example is a useful reminder of one of the dangers of engineering metaphors: sometimes we impose restrictions on computers that are unnecessary. In this section I will sketch a more efficient algorithm called mergesort. 51). Neither of these is an issue for a computer.2 I wrote pseudocode for a shuffling algorithm. But if the objects in question are immutable. the difference between n2 and n log n can be enormous. is proportional to n2 . because we unthinkingly extend a metaphor past its breaking point. Instead we will create each card once and then treat it as an immutable object. So for Cards aliasing is a reasonable choice. 14. we saw a simple sorting algorithm that turns out not to be very efficient.6 Mergesort In Section 14. and each traversal takes an amount of time that is proportional to n. did you think we should give out one card at a time to each player in the round-robin style that is common in real card games? I thought about it. In this case. In order to sort n items. 5. therefore. since changes in one subdeck will be reflected in others. 14. 10.5 Shuffling and dealing 149 I have suggested that aliasing is not generally a good idea. Deck hand2 = subdeck(deck. shuffleDeck(deck). we can use subdeck: Deck hand1 = subdeck(deck. to deal out several hands. or expect capabilities that are lacking. which is not the behavior you would expect from real cards and decks.3. but as n gets big. there is probably no reason ever to change the rank or suit of a card. 0. 9). Try out a few values of n and see.

int j = 0. d2 wins. and then use the sort routine from the previous chapter to sort the two halves. Here’s what this looks like in pseudocode: public static Deck merge(Deck d1. The result should be a single sorted deck. 3. if d2 is empty. If you can get that working. Repeat step two until one of the decks is empty. compare the two cards // add the winner to the new deck } return result. Place both decks face up in front of you.150 Objects of Arrays The basic idea behind mergesort is this: if you have two subdecks. and the index j for the second deck int i = 0. // otherwise. // the index k traverses the result deck for (int k = 0. } The best way to test merge is to build and shuffle a Try this out with a deck of cards: 1. Compare the top card from each deck and choose the lower one. 2. Then take the remaining cards and add them to the merged k++) { // if d1 is empty.length + d2. Flip it over and add it to the merged deck. Deck d2) { // create a new deck big enough for all the cards Deck result = new Deck(d1. try a simple implementation of mergeSort: public // // // // } static Deck mergeSort(Deck deck) { find the midpoint of the deck divide the deck into two subdecks sort the subdecks using sortDeck merge the two halves and return the result . use subdeck to form two(small) hands.length). // use the index i to keep track of where we are in // the first deck. Form two subdecks with about 10 cards each and sort them so that when they are face up the lowest cards are on top.length. Then you can pass the two halves to merge to see if it works. it is easy(and fast) to merge them into a single. k<result. sorted deck. each of which has been sorted. d1

rather than a deck and an index range(see Section 13. right? You just assumed that the sortDeck method would work because you already debugged it. The recursive version of mergesort should look something like this: public static Deck mergeSort(Deck deck) { // if the deck is 0 or 1 cards. In order to make it work. there are two ways to think about recursive programs: you can think through the entire flow of execution. but which helps another.7 Glossary 151 Then. 14. Good luck! 14. it can return it unmodified. more useful. it is necessary in order to achieve the performance advantage I promised.8). At the point where you sort the subdecks.” I have deliberately constructed this example to encourage you to make the leap of faith. you have to add a base case so that it doesn’t recurse forever. Well. why should you invoke the old. When you were using sortDeck to sort the subdecks. you have to give some thought to getting the base case right and making sure that you reach it eventually. A simple base case is a subdeck with 0 or 1 cards. Well. method. but other than that. writing the recursive version should be no problem.14. Which version is more errorprone? Which version do you think is more efficient? .7 Glossary pseudocode: A way of designing programs by writing rough drafts in a combination of English and Java. return it // // // // find the midpoint of the deck divide the deck into two subdecks sort the subdecks using mergesort merge the two halves and return the result } As usual. helper method: Often a small method that does not do anything enormously useful by itself. though. or you can make the “leap of faith. If mergesort receives such a small subdeck.1 Write a version of findBisect that takes a subdeck as an argument. since it is already sorted. actually. you didn’t feel compelled to follow the flow of execution. the real fun begins! The magical thing about mergesort is that it is recursive. There is no reason to read the program differently. all you did to make mergeSort recursive was replace one sorting algorithm with another.8 Exercises Exercise 14. if you get that working. slow version of sort? Why not invoke the spiffy new mergeSort you are in the process of writing? Not only is that a good idea.

rather than the contents of the two objects. This is not only faster. Write a method called shuffleDeck that uses the algorithm in Section 14. You might want to use the randomInt method from Exercise 12. named Deck. For example.1. It is probably a good idea to make this transformation one method at a time. when we pass a “deck” as a parameter. which means that after each hand. you will implement the new representation of a deck. Move them there and make any changes necessary to get the program to compile and run again. In this chapter. You can use the version of printDeck in Section to the program.4 In order to make life more difficult for card-counters.2. This is an example of an incremental algorithm. d. b. On the other hand. an object type named Deck that contains an array of cards as an instance variable. you can make most of the changes with searchand-replace commands.1 as an example. HINT: it should switch the references to the two cards. but it makes it easier to deal with the case where cards are aliased.2.3 The goal of this exercise is to implement the shuffling and sorting algorithms from this chapter. the used cards are returned to the deck and. if you are confident you know what you are doing. a. Add a second file. a. c. Write a method called swapCards that takes a deck(array of cards) and two indices. c. Of the methods currently in the Card class. Type in the constructors for the Deck class as shown in Section 14. Look over the program and identify every place where an array of Cards is being used to represent a deck. d. and that switches the cards at those two locations. b. many casinos now use automatic shuffling machines that can do incremental shuffling. Exercise 14. Exercise 14. Write a method called findLowestCard that uses the compareCard method to find the lowest card in a given range of the deck(from lowIndex to highIndex. Write a method called sortDeck that arranges a deck of cards from lowest to highest.2 In the previous version of the Card class. a deck is implemented as an array of Cards. including both). This file will contain the definition of the Deck class. . the new cards are inserted in random locations. In this exercise. Modify the program throughout so that it uses a Deck object instead. we developed an alternative representation for a deck.152 Objects of Arrays Exercise 14. instead of reshuffling the entire deck. the actual type of the parameter is Card[]. and test the program after each change. decide which ones would be more appropriate as members of the new Deck class. Write a method called incrementalShuffle that takes a Deck and a Card and that inserts the card into the deck at a random location.

d. in increasing order of value: pair: two cards with the same rank two pair: two pairs of cards with the same rank three of a kind: three cards with the same rank straight: five cards with ranks in sequence flush: five cards with the same suit full house: three cards with one rank. Write a method called isThreeKind that takes a hand and returns a boolean indicating whether the hand contains Three of a Kind.” that means that if you have a card with rank 2. think of algorithms to check for various poker hands if there are wild cards. deck = mergeSort(deck). You might find it useful to write some general-purpose helper methods that can be used for more than one test.5 The goal of this exercise is to write a program that generates random poker hands and classifies them. Exercise 14. the one that divides the deck in half. b. Write methods that test for the other poker hands. As a warmup. and uses merge to create a new. Remember that sortDeck is a modifier and mergeSort is a function. so that we can estimate the probability of the various poker hands. players get seven cards each. a. I’ll tell you everything you need to know. write a program that uses shuffleDeck and subdeck to generate and print four random poker hands with five cards each. uses sortDeck to sort the two halves.14. you can use it to represent any card in the deck. Be sure to test it before trying to use it as part of a mergeSort. c.6 As a special challenge. In some poker games. Did you get anything good? Here are the possible poker hands. For example. e. fully-sorted deck. a. Write a method called isFlush that takes a Deck as a parameter and returns a boolean indicating whether the hand contains a flush.8 Exercises 153 Exercise 14. two cards with another four of a kind: four cards with the same rank straight flush: five cards in sequence and with the same suit b. f. Write the fully recursive version of mergeSort. Some are easier than others. write the method called merge. Don’t worry if you don’t play poker. Using the pseudocode in Section 14. c. Write the simple version of mergeSort. which means that they get invoked differently: sortDeck(deck).6. Estimate the probability of getting one of those hands. Exercise 14. Modify your program to generate seven-card hands and recompute the probabilities. Write a loop that generates a few thousand hands and checks whether they contain a flush or three of a kind.7 The goal of this exercise is to implement mergesort. if “deuces are wild. // modifies existing deck // replaces old deck with new . and they form a hand with the best five of the seven.

154 Objects of Arrays .

I will cover inheritance later in this chapter.1 Programming languages and styles There are many programming languages in the world.1. In this chapter we will write some object methods. Existing Java programs and libraries are written in a mixture of all three styles. but here are some of its characteristics: • Object definitions(classes) usually correspond to relevant real-world objects. So far all the methods we have written have been class methods. and object-oriented. . Recently object-oriented programming has become quite popular. For example. and almost as many programming styles(sometimes called paradigms). but they tend to be more object-oriented than the programs in this book. I hope that by exposing you to a variety of styles I have given you the tools you need to understand and evaluate these claims. • The language feature most associated with object-oriented programming is inheritance. • The majority of methods are object methods(the kind you invoke on an object) rather than class methods(the kind you just invoke). the creation of the Deck class was a step toward object-oriented programming. it is possible to write Java programs in any style. in Chapter 14. functional. The style I have demonstrated in this book is pretty much procedural. It’s not easy to define what object-oriented programming is. Although Java is usually thought of as an object-oriented language.Chapter 15 Object-oriented programming 15. and there are people who claim that it is superior to other styles in various ways. Three styles that have appeared in this book are procedural.

In fact.3 The current object When you invoke a method on an object.imag = 0. y is the imaginary part. A complex number is the sum of a real part and an imaginary part. without having to specify the name of the object. We have already seen this used in constructors.156 Object-oriented programming 15. Class methods are identified by the keyword static in the first line. The following is a class definition for a new object type called Complex: class Complex { // instance variables double real.0. you can think of constructors as being a special kind of object method. } this.0. For example. that object becomes the current object. charAt and the other methods we invoked on String objects are all object methods. imag. 15. object methods are often shorter than the corresponding class methods. and vice versa. where x is the real part. Thus.real = 0. and many computations are performed using complex arithmetic. Any method that does not have the keyword static is an object method. i · i = −1. Complex numbers are useful for many branches of mathematics and engineering. it’s an object method. Inside the method. and is usually written in the form x + yi.2 Object and class methods There are two types of methods in Java. Although we have not written any object methods. and i represents the square root of -1. 15. Anything that can be written as a class method can also be written as an object method. So far. . you can refer to the current object using the keyword this. we have invoked some.4 Complex numbers As a running example for the rest of this chapter we will consider a class definition for complex numbers. Whenever you invoke a method “on” an object. For reasons that will be clear soon. Sometimes it is just more natural to use one or the other. Also. called class methods and object methods. // constructor public Complex() { this. every method we have written has been a class method. you can refer to the instance variables of the current object by name.

The two constructors are the usual kind: one takes no parameters and assigns default values to the instance variables. or anywhere else we want to create Complex objects. The next version of abs is an object method. x.imag = 2. } I removed the keyword static to indicate that this is an object method. Thus. In main. 4. The abs method is a pure function that computes the absolute value.0). I could have used the keyword this: // object method public double abs() { . If I wanted to make it explicit. Inside the method.sqrt(c. As we have seen before. I can refer to the instance variables real and imag by name without having to specify an object. The absolute value of a complex number is defined to be x2 + y 2 . we have the option of creating the object and then setting the instance variables.5 A function on Complex numbers Let’s look at some of the operations we might want to perform on complex numbers. the Complex object it receives as a parameter.sqrt(real*real + imag*imag).imag = imag. the keyword this is used to refer to the object being initialized. I eliminated the unnecessary parameter. Written as a class method. 15.0. } This version of abs calculates the absolute value of c.0. this.imag). Complex y = new Complex(3. or doing both at the same time: Complex x = new Complex(). it looks like this: // class method public static double abs(Complex c) { return Math. the other takes parameters that are identical to the instance variables. it does not receive any parameters: // object method public double abs() { return Math. The instance variables are doubles that contain the real and imaginary parts.15. } } 157 There should be nothing surprising here. it calculates the absolute value of the current object(the object the method was invoked on).real = real.real = 1.real + c. double imag) { this. x.0. Also.5 A function on Complex numbers // constructor public Complex(double real. Java knows implicitly that I am referring to the instance variables of the current object.real * c.imag * c.

Written as an object method.sqrt(this. } To invoke this method.real + b. which is a modifier method that transforms a Complex number into its complex conjugate. As a class method. this looks like: public static void conjugate(Complex c) { c. You can add complex numbers by adding the real parts and adding the imaginary parts.7 A modifier As yet another example. that looks like: public static Complex add(Complex a. you invoke it on one of the operands and pass the other as an argument.0).abs(). Complex b) { return new Complex(a. we’ll look at conjugate.imag = -c.real. the current object is sometimes called an implicit parameter. The complex conjugate of x + yi is x − yi.0. it looks like . From these examples you can see that the current object(this) can take the place of one of the parameters. } Again. To invoke this method. we can refer to the instance variables of the current object implicitly. y). } As an object method.imag.imag + b.158 Object-oriented programming return Math. 4. but to refer to the instance variables of b we have to name b explicitly using dot notation. For this reason. 15. it would take only one argument.real.imag).imag). Complex sum = x. imag + b.imag * this.real + this.6 Another function on Complex numbers Another operation we might want to perform on complex numbers is addition. Written as a class method. 15. we would pass both operands as arguments: Complex sum = add(x. To invoke this method. which it would add to the current object: public Complex add(Complex b) { return new Complex(real + b. double result = y. a.imag).real * this. for example Complex y = new Complex(3.add(y). we invoke it on an object. } But that would be longer and not really any clearer.

toString().println(x). You can invoke toString in the usual way: Complex x = new Complex(1. you can override the default behavior by providing a new method with the behavior you want. and it takes no parameters. } By now you should be getting the sense that converting a method from one kind to another is a mechanical process. simple operations that apply to a single object can be written most concisely as object methods(even if they take some additional arguments).6). With a little practice.0 + 2. . Here is what toString might look like for the Complex class: public String toString() { return real + " + " + imag + "i". it seems odd to invoke the method on one of the operands and pass the other as an argument. String s = x. naturally. In this case. 2. This version of toString does not look good if the imaginary part is negative. do both objects refer to the same location in memory.8 The toString method 159 public void conjugate() { imag = -imag. To me. you will be able to do it without giving it much thought.out. When you define a new object type. As an exercise. what you are really asking is.9 The equals method When you use the == operator to compare two objects. which is good because you should not be constrained to writing one kind of method or the other.8 The toString method Every object type has a method called toString that generates a string representation of the object.0). write a better version.0i. I think that add should be written as a class method because it is a symmetric operation of two operands. For example. or you can invoke it indirectly through println: System. 15. and it makes sense for both operands to appear as parameters. 15. On the other hand. “Are these two things the same object?” That is.15. When you print an object using print or println. the output is 1. Java invokes the object’s toString method. The default version of toString returns a string that contains the type of the object and a unique identifier(see Section 11. } The return type for toString is String. You should be equally familiar with both so that you can choose whichever one seems most appropriate for the operation you are writing.0.

equals(y) consistently return true or consistently return false. For example. • It is consistent: for any reference values x and y.equals(y) returns true and y. For example. then x. you can provide your own definition of equality by providing an object method called equals.equals(z) should return true. and let’s make it a modifier. The definition of equals I provided satisfies all these conditions except one. equals is always an object method that returns a boolean. that is not the appropriate definition of equality.real && imag == b. The documentation of equals in the Object class provides some guidelines you should keep in mind when you make up your own definition of equality: The equals method implements an equivalence relation: • It is reflexive: for any reference value x. Which one? As an exercise. real = real/d. if x. They don’t have to be the same object. It may not be obvious why this is useful. to normalize a complex number. When you define a new object type.equals(null) should return false. public void normalize() { double d = this.equals(z) returns true. imag = imag/d.equals(x) returns true. and z. • It is transitive: for any reference values x.160 Object-oriented programming For many types. • For any reference value x. } By convention. x. this looks like: public boolean equals(Complex b) { return(real == b. x.imag). 15. it is legal and common to invoke one object method from another. but it is.10 Invoking one object method from another As you might expect.equals(x) should return true.equals(y) should return true if and only if y.abs(). fix it. two complex numbers are equal if their real parts are equal and their imaginary parts are equal. you divide both parts by the absolute value. y. } . • It is symmetric: for any reference values x and y. For the Complex class. Let’s write the method normalize as an object method. multiple invocations of x. x.

11 Oddities and errors If you have both object methods and class methods in the same class definition. The primary advantage of this feature is that you can add new methods or instance variables to an existing class without modifying the existing class.” Also. as long as they do not have the same number and types of parameters. by “nonstatic variable” it means “instance variable. it is an error to use the keyword this.11 Oddities and errors 161 The first line finds the absolute value of the current object by invoking abs on the current object. followed by all the object methods and then all the class methods. you might get “Can’t make a static reference to nonstatic variable.. the existing class is sometimes called the parent class. 15. Java decides which version to invoke by looking at the arguments you provide.12 Inheritance The language feature that is most often associated with object-oriented programming is inheritance. A common way to organize a class definition is to put all the constructors at the beginning. As with other kinds of overloading. which means that there is no “current object” when it is invoked.15. . In this case I named the current object explicitly. This is particularly useful for Java classes. Exercise 15. Rewrite normalize as a pure function..1 method. Then rewrite it as a class 15. but I could have left it out. The reason inheritance is called “inheritance” is that the new class inherits all the instance variables and methods of the existing class. If you invoke one object method within another. Now that we know what the keyword static means. you cannot refer to instance variables without using dot notation and providing an object name. Extending this metaphor.” This is not one of the better error messages. For example. Java assumes that you are invoking it on the current object. If you try. Inheritance is the ability to define a new class that is a modified version of a previously-defined class. you might get an error message like: “Undefined variable: this. since you can’t modify them even if you want to. Since there is no current object in a class method. it is easy to get confused. If you try.” But once you know what it means. you have probably figured out that main is a class method. since it uses some non-standard language. you know what it means. You can have an object method and a class method with the same name.

we are going to create a new class called DrawableRectangle that will have all the instance variables and methods of a Rectangle. which refers to the instance variables x. Java would know to use the method defined in the parent class. . width and height.13 Drawable rectangles An an example of inheritance. width. } } Yes.*.drawRect(x. int x. y. you could use the following: public static void draw(Graphics g.162 Object-oriented programming 15.y = 10. To create and draw a DrawableRectangle. which is where Rectangle and Graphics are defined. dr.height = 200. The first line imports the java. we are going to take the existing Rectangle class and make it “drawable. The keyword extends is used to identify the class we are inheriting from. It might seem odd to use new for a class that has no constructors. We can set the instance variables of dr and invoke methods on it in the usual way. but remember that they are inherited from the parent class.draw(g). Java invokes the method we defined in DrawableRectangle. DrawableRectangle inherits the default constructor of its parent class. class DrawableRectangle extends Rectangle { public void draw(Graphics g) { g. int height) { DrawableRectangle dr = new DrawableRectangle().x = 10. If we invoked grow or some other Rectangle method on dr. dr. The class definition looks like this: import java. When we invoke draw.awt. height).awt package. dr. y. dr. that’s really all there is in the whole class definition. int y. int width. The rest is the definition of the draw method. It might seem odd to refer to instance variables that don’t appear in this class definition.” That is. so there is no problem there. which is called the parent class. } The parameters of draw are a Graphics object and the bounding box of the drawing area(not the coordinates of the rectangle). dr.width = 200. The next line indicates that DrawableRectangle inherits from Rectangle. plus an additional method called draw that will take a Graphics object as a parameter and draw the rectangle.

14 The class hierarchy In Java. a common alternative is composition. Designing objects and the relationships among them is the topic of objectoriented design. which is referred to by the keyword this in Java or “the current object” in English. . in java. since it is sometimes not clear. Some inheritance chains are longer. For example. No matter how long the chain. Object methods do not have the keyword static. including almost all of the classes we have written and many Java classes. since you can customize the behavior of existing classes without having to modify them. 15. for example. Also. like Rectangle. All the classes in Java can be organized into a “family tree” that is called the class hierarchy. It contains no instance variables. which extends Container. If you look at the documentation of Frame. Any class that does not explicitly name a parent inherits from Object by default. Also. inheritance can make programs difficult to read. when a method is invoked. which is beyond the scope of this book. among others. 15. published by O’Reilly Media. many of the things that can be done using inheritance can be done almost as elegantly (or more so) without it. On the other hand. but it does provide the methods equals and toString. For example. Object usually appears at the top.14 The class hierarchy 163 15. Many classes extend Object. where to find the definition. Some programs that would be complicated without it can be written concisely and simply with it.15 Object-oriented design Inheritance is a powerful feature. Frame extends Window. though. The most basic class is called Object. inheritance can facilitate code reuse.15. all classes extend some other class. Object is the ultimate parent of all classes.16 Glossary object method: A method that is invoked on an object. which extends Component. you will see the part of the hierarchy that makes up Frame’s pedigree. Class methods are not invoked on objects and they do not have a current object. where new objects are composed of existing objects. and that operates on that object. class method: A method with the keyword static. I recommend Head First Design Patterns. which extends Object.awt. with all the “child” classes below. But if you are interested. adding new capability without inheritance.

} Exercise 15. public boolean equals(Complex b) { return(real == b. and make the necessary changes in main. } Exercise 15. b. 15. a. Try invoking class methods as if they were object methods and vice-versa. explicit: Anything that is spelled out completely.imag). what kind of computations can be expressed most naturally using each style)? . Think about the pros and cons of class and object methods. Make a few mistakes.sqrt(c. all references to the instance variables have to be explicit.imag * c.3. this: The keyword that refers to the current object. Within an object method.real && imag == b.17 Exercises Exercise 15. Try to get a sense for what is legal and what is not.4 This exercise is a continuation of Exercise 11.real * c. The purpose is to practice the syntax of object methods and get familiar with the relevant error messages.real + c. the current object is referred to by this. you can refer to the instance variables implicitly(without naming the object).imag). public static double abs(Complex c) { return Math. and for the error messages that you get when you mess things up. Inside the method. c. implicit: Anything that is left unsaid or implied. Which is more concise(usually)? Which is a more natural way to express computation(or. maybe more fairly.2 Transform the following class method into an object method.3 Transform the following object method into a class method.164 Object-oriented programming current object: The object on which an object method is invoked. Within a class method. Transform the methods in the Rational class from class methods to object methods.

A typical. If you find yourself in this situation. you are likely to write more code than you can debug. Add a small number of lines of code at a time. bad program development plan goes something like this: 1. 2. 4. Spend an hour finding run time errors. To debug effectively. Spend an hour finding syntax errors.Appendix A Program development plan If you are spending a lot of time debugging. Repeat until the program does what it is supposed to do. the only solution is to remove code until you have a working program again. If you write more than one method. Write an entire method. Start with a working program that does something visible. or even an entire method. Spend three hours finding semantic errors. Try to compile the program. Beginning programmers are often unwilling to do this. The problem. it is probably because you do not have an effective program development plan. is the first two steps. Write several more methods. 2. because their carefully crafted code is precious to them. 5. and test the program after every change. and then gradually build the program back up. 6. before you start the debugging process. of course. like printing something. 3. . 3. you have to be ruthless! Here is a better program development plan: 1.

} Of course.out. public static boolean isIn(char c. In my programming career. I have wasted way too much time debugging a method. return false.println("isIn"). Of course. or somewhere else in a working program. the answer isn’t correct. System.println(test). This approach to programming can save a lot of time.println("in the String " + s). and print the word isIn and the value false. Also.out. System. String s) { System. it never would have happened. return false. because each version of the program produces a visible result.out. you will be confronted with the conflict(and have a chance to correct it) before you have written a lot of erroneous code. and do something visible: public static boolean isIn(char c. to test the method we have to invoke it. If I had used this development plan. In main. "banana").166 Program development plan After every change. We’ll start with a case where the character appears in the String(so we expect the result to be true). Because you only add a few lines of code at a time.out. One problem with this approach is that it is often difficult to figure out a path from the starting place to a complete and correct program. If your mental model is erroneous. I will demonstrate by developing a method called isIn that takes a String and a character. } . you are constantly testing your mental model of how the program works.println("isIn looking for " + c). the program should produce some visible effect that demonstrates the new code. } If everything goes according to plan. public static void main(String[] args) { boolean test = isIn(’n’. it is easy to find syntax errors. but at this point we know that the method is getting invoked and returning a value. run. this code will compile. String s) { System. 2. we need to create a simple test case. and that returns a boolean: true if the character appears in the String and false otherwise. only to discover that it was never getting invoked. run. The next step is to check the parameters the method receives. The first step is to write the shortest possible method that will compile. 1.

println("in the String " + s).out. } return false.println(letter). String s) { System. System.length()) { char letter = s. So far we haven’t given much thought to what this method is going to do. public static boolean isIn(char c. The point is to confirm that they are what we think they are. As usual. if (letter == c) { . System. The simplest algorithm is a linear search. 3.println("isIn looking for " + c).3. System. } Now when we run the program it prints the characters in the String one at a time. while (index < s.out. we can take advantage of the code from Section 8. Now the output looks like this: isIn looking for n in the String banana Printing the parameters might seem silly. since we know what they are supposed to be.charAt(index).out.out.out.out. it is a great idea to reuse code fragments rather than writing them from scratch. The second statement confirms that we are looking in the right place. int index = 0.167 The first print statement allows us to confirm that isIn is looking for the right letter.length()) { char letter = s.charAt(index). String s) { System. int index = 0. In general. 4. we’ll proceed by adding just a few lines at a time: public static boolean isIn(char c.println("in the String " + s).println("isIn looking for " + c). At this point we probably need to figure out an algorithm. To traverse the String. we have already written the code that traverses the vector. which traverses the vector and compares each element to the target word. Happily.println(letter). index = index + 1. we can confirm that the loop examines all the letters in the String. System. while (index < s. If all goes well.

so that when the new code executes it produces a visible effect.out. Then we should check some of the typical troublemakers.println("found it"). If we find it. First. we should confirm that the method returns false if the character is not in the String. } return false. .println(letter).out. String s) { System. we return true. we print something. then the correct return value is false. } As we traverse the String.println("isIn looking for " + c).out. } index = index + 1. "". The next step is to make sure that the other test cases work correctly. but it can’t tell you if the method is correct.charAt(index). or a String with a single character. return true. this kind of testing can help find bugs if there are any. like an empty String. we compare each letter to the target character. } If we find the target character. int index = 0. } index = index + 1.out. 5. } return false. As always.168 Program development plan System. System. if (letter == c) { System.println("in the String " + s). we should get isIn looking for n in the String banana b a n found it true 6. If we run the program at this point. At this point we are pretty close to working code. System. while (index < s. If we get all the way through the loop without finding it. The next change is to return from the method if we find what we are looking for: public static boolean isIn(char c.out.println("found it").length()) { char letter = s.

no one needs this: // if letter equals c. while (index < s. the only statement that can cause a run-time error is s. If there is anything about the code that is not obvious. To check for run time errors. The final step is to examine the code and see if you can convince yourself that it is correct. because it compiles. it is a good idea for methods to make sure their parameters are legal. String s) { int index = 0. Removing the comments allows you to see the code most clearly. The structure of the while loop ensures that index is always between 0 and s. return true if (letter == c) { return true. But if this is the final version of the method. } return false. } index = index + 1. to warn about conditions that could cause errors. If we check all the problem conditions. 8.charAt(index). before each method. public static boolean isIn(char c. } You should use comments to explain non-obvious code.length-1. This statement will fail if s is null or if the index is out of bounds. Since we get s as a parameter. all we can do is check. it is a good idea to write an abstract description of what the method does. and you are convinced that it is correct. and to document any assumptions that are built into the code. The penultimate step is to remove or comment out the print statements. In this method.169 7. if (letter == c) { return true.length()) { char letter = s. Also. you should find every statement that can cause an error and figure out what conditions cause the error. or prove that they cannot happen. For example. . } Commenting out the print statements is a good idea if you think you might have to revisit this method later. In general. then we can prove that this method will not cause a run time error. you should add comments to explain it. At this point we know that the method is syntactically correct.charAt(index). you should remove them. Resist the temptation to translate the code line by line. we can’t be sure that it is not null. which can help you spot any remaining problems.

170 Program development plan We haven’t proven yet that the method is semantically correct. and returning true if it finds the target. we know that if the loop exits. we have avoided many possible errors. We also know that it is comparing characters successfully. For example. we already know that the method is getting parameters correctly and that the loop traverses the entire String. Short of a formal proof. the target is not in the String. . Finally. that is probably the best we can do. but by proceeding incrementally.

• Run-time errors are produced by the run-time system if something goes wrong while the program is running. there are some techniques that are applicable in more than one situation. Most run-time errors are Exceptions. B.1 Syntax errors The best kind of debugging is the kind you don’t have to do. Example: an infinite recursion eventually causes a StackOverflowException.Appendix B Debugging There are a few different kinds of errors that can occur in a program. The key is to start with a working program and add small amounts of code at a time. Nevertheless. Example: an expression may not be evaluated in the order you expect. and it is useful to distinguish between them in order to track them down more quickly. In the previous section. • Semantic errors are problems with a program that compiles and runs. For each situation. The first step in debugging is to figure out which kind of error you are dealing with. yielding an unexpected result. but doesn’t do the right thing. • Syntax errors are produced by the compiler and usually indicate that there is something wrong with the syntax of the program. Although the following sections are organized by error type. when there is an error. you might find yourself in one of the following situations. I suggested a program development plan that minimizes the number of errors you will make and makes it easy to find them when you do. That way. . Example: omitting the semi-colon at the end of a statement. I make some suggestions about how to proceed. you will have a pretty good idea where it is. because you avoid making errors in the first place.

start examining the code for the common syntax errors. Check for semi-colons at the end of statements(and no semi-colons after squiggly-braces). I suggest that you only fix one error at a time. that doesn’t mean there are 100 errors in your program. it often gets thrown off track for a while. and then recompile the program. Generally the error will be prior to the location of the error message. If the compiler reports 100 error messages. All program statements should be within a method definition. If you are building the program incrementally. Use the information the compiler gives you as a guideline. All method definitions should be nested within a class definition. and it reports spurious errors. 2. At the same time. First of all. Check every character. you should have a good idea about where the error is. so if you see something that looks like a syntax error. Of course. remember that the book might be wrong. You may find that one semicolon “fixes” 100 errors. . take a breath and look more broadly at the entire program. the message will tell you where in the program the problem occurred. For example. I won’t say that good indentation makes it easy to find syntax errors. you might as well fix more than one bug per compilation attempt. only the first error message is reliable. Remember that upper case letters are not the same as lower case letters. if you get an error message at a method invocation. it might be. which is not necessarily where the error is. In general. If nothing else. 3. I’m getting a weird compiler message and it won’t go away. Now is a good time to go through the whole program and make sure it is indented properly.172 Debugging The compiler is spewing error messages. but often there is a kernel of information there that is carefully hidden. Actually. 1. if you see several legitimate error messages. but sometimes it fails. It will be in the last line you added. If you are copying code from a book. It tries to recover and pick up again after the first error. broaden the search. but if you don’t see an error where the compiler is pointing. Now. it tells you where the compiler was when it noticed a problem. but there are cases where it will be somewhere else entirely. the actual error may be in the method definition. If you don’t find the error quickly. start by comparing your code to the book’s code very carefully. When the compiler encounters an error. but bad indentation sure makes it harder. read the error message carefully. Check that all parentheses and brackets are balanced and properly nested. It is written in terse jargon.

Delete about half of the code and repeat. If you are working on • Delete about half the code from Bob.old. If you try that in a class method. If you are invoking a fruitful Make sure that the expression on the left is a variable name or something else that you can assign a value to(like an element of an array). you will get a confusing message like. and have right type. 6. make sure you are not trying to do something with the result.” If nothing works. 5. then you know the error is in the other half. Bob. Check your development environment to make sure the program you are editing is the program the compiler is compiling. that might be because you and the compiler are not looking at the same code. Bring back about half of the code you deleted and repeat. Make sure that any strings in the code have matching quotation marks. if you have examined the code thoroughly. the error must be in this half. it is time for desperate measures. 9. make sure you are invoking it on an object with the right type. For each assignment try putting an obvious and deliberate syntax error right at the beginning of the program. . make sure you are doing something with the result. If you are invoking a class method from outside the class where it is defined. “Static reference to non-static variable. – If the program compiles now. make sure you specify the class name.B. and that the object you are invoking the method on is the right type. If the compiler says there is an error and you don’t see it. Otherwise. Now compile again. Make sure that you use double-quotes for Strings and single quotes for characters. If you are invoking a void method. I can’t get my program to compile no matter what I do. – If the program still doesn’t compile. If you are invoking an object method. 8. Inside an object method you can refer to the instance variables without specifying an object. If the compiler doesn’t find the new error. • Make a copy of the file you are working on.. make sure that the type on the left is the same as the type on the right. move on to the next section. If you are not sure. Try compiling again. there is probably something wrong with the way you set up the project. 7. make sure that the arguments you provide are in the right order. You should start over with a program that you can compile and then gradually add your code back..1 Syntax errors 173 For each method invocation. make a copy called Bob.

2 Run-time errors My program hangs.174 Debugging • Once you have found and fixed the error. Fortunately.” If you are not getting a StackOverflowException. but you suspect there is a problem with a recursive method. though. If a program stops and seems to be doing nothing. Error messages give you evidence that something is wrong. like “class Golfer must be declared abstract.lang. For really sticky syntax problems. It does not define int compareTo(java. I think deleting is more reliable—you don’t have to worry about the syntax of the comments. the compiler is wrong. • If there is a particular loop that you suspect is the problem. but they can be misleading. you can still use the techniques in the infinite recursion section. and their “advice” is often wrong. The solution in this case is to make sure Golfer has a method called compareTo that takes an Object as a parameter. If that happens. add a print statement immediately before the loop that says “entering the loop” and another immediately after that says “exiting the loop.” Run the program. This process is called “debugging by bisection. and by making the program smaller you make it more readable. we say it is “hanging. you’ve got an infinite loop. • If neither of those things works. but it still doesn’t work. B. Go to the section titled “Infinite loop. go to the section titled “Infinite recursion.” Often that means that it is caught in an infinite loop or an infinite recursion. you can comment out chunks of code instead of deleting them. a little bit at a time.Object) from interface java. Some compiler messages come with tidbits of advice.” • Most of the time an infinite recursion will cause the program to run for a while and then produce a StackOverflowException. . and if you are reading this book. In general.Comparable. start testing other loops and other recursive methods.” As an alternative.lang. start bringing back the code you deleted. If you get the first message and not the second. you probably don’t know what that is or how to do it. I did what the compiler told me to do.” It sounds like the compiler is telling you to declare Golfer as an abstract class. don’t let the compiler lead you by the nose.

println("x: " + x).println("y: " + y). . then it is possible that you don’t understand the flow of execution in your program. and the value of the condition.out. there should be some condition that will cause the method to return without making a recursive invocation. System. the condition should be false.” Infinite loop If you think you have an infinite loop and think you know what loop is causing the problem. add print statements to the beginning of each method with a message like “entering method foo. Flow of execution If you are not sure how the flow of execution is moving through your program. Go to the section titled “Flow of execution. } Now when you run the program you will see three lines of output for each time through the loop. and you will see the parameters.out. you will be able to see the values of x and y and you might figure out why they are not being updated correctly. then you need to rethink the algorithm and identify a base case. System.B.println("condition: " +(x > 0 && y < 0)). but the program doesn’t seem to be reaching it. If the parameters are not moving toward the base case. If the loop keeps going. The last time through the loop. while (x > 0 && y < 0) { // do something to x // do something to y System. If there is a base case. you will get some ideas about why not.” where foo is the name of the method. For example. Now when you run the program you will see a few lines of output every time the method is invoked.2 Run-time errors 175 • If none of these suggestions helps.out. If you know that a method is causing an infinite recursion. add a print statement at the end of the loop that prints the values of the variables in the condition. Infinite recursion Most of the time an infinite recursion will cause the program to run for a while and then produce a StackOverflowException. If not. In other words. start by checking to make sure that there is a base case. add a print statement at the beginning of the method that prints the parameters.

You should figure out what variable is null and then figure out how it got to be that way. Remember that when you declare a variable with an object type. add a print statement immediately before it to print the value of the index and the length of the array. and a stack trace. Is the array the right size? Is the index the right value? Now work your way backwards through the program and see where the array and the index come from. Find the nearest assignment statement and see if it is doing the right thing.println(blank. One of the problems with using print statements for debugging is that you can end up buried in output. There are two ways to proceed: either simplify the output or simplify the program.out.length-1. check whether the parameters are reasonable. and then the method that invoked it. If you can find the site where the problem is. go to the place where the method is invoked and see where the values are coming from. it traces the stack of method invocations that got you to where you are. it is initially null. . NullPointerException: You tried to access an instance variable or invoke a method on an object that is currently null. When you run the program. The first step is to examine the place in the program where the error occurred and see if you can figure out what happened. until you assign a value to it. In other words. and check for one of the classic errors—providing parameters in the wrong order.” I added so many print statements I get inundated with output. When I run the program I get an Exception. the Java run-time system prints a message that includes the name of the exception. The stack trace includes the method that is currently running. System.176 Debugging Now when you run the program it will print a trace of each method as it is invoked. If something goes wrong during run time. and then the method that invoked that. It is often useful to print the parameters each method receives when it is invoked.x). For example. and so on. If either one is a parameter. StackOverFlowException: See “Infinite recursion. this code causes a NullPointerException: Point blank. ArrayIndexOutOfBoundsException: The index you are using to access an array is either negative or greater than array. the line of the program where the problem occurred.

3 Semantic errors 177 To simplify the output. For example. Similarly. Only you know what the program was supposed to do. but not when it has an odd number. Add a print statement to the beginning of the suspect methods. For example. it is not really a good way to debug. that can tip you off. One of the things that makes this hard is that computers run so fast. because the compiler and the run-time system provide no information about what is wrong. there are several things you can do. • Is something happening that shouldn’t? Find code in your program that performs that function and see if it is executing when it shouldn’t. In some ways semantic errors are the hardest. As you develop a program.3 Semantic errors My program doesn’t work. sort a small array. . The first step is to make a connection between the program text and the behavior you are seeing. If the program takes input from the user. clean up the program. you will conceive ways to visualize the execution of the program. If you make a change that you think doesn’t affect the program. if you find that a program works when the array has an even number of elements. and develop code that generates concise. if you suspect that the error is in a deeply-nested part of the program. and only you know that it isn’t doing it. and it does. You need a hypothesis about what the program is actually doing. Often the process of finding the minimal test case leads you to the bug. First. informative visualizations.B. rewriting a piece of code can help you find subtle bugs. that gives you a clue about what is going on. You will often wish that you could slow the program down to human speed. give it the simplest input that causes the error. For example. If you suspect a large method. Second. Here are some questions to ask yourself: • Is there something the program was supposed to do. B. try splitting it into smaller methods and testing them separately. you can remove or comment out print statements that aren’t helping. or combine them. or format the output so it is easier to understand. To simplify the program. try rewriting that part with simpler structure. but doesn’t seem to be happening? Find the section of the code that performs that function and make sure it is executing when you think it should. but there is no straightforward way to do that. if you are sorting an array. Remove dead code and reorganize the program to make it as easy to read as possible. scale down the problem the program is working on. and even if there were.

you need to have a mental model of how programs work. see the section titled “Flow of Execution.178 Debugging • Is a section of code producing an effect that is not what you expected? Make sure that you understand the code in question. it checks shallow equality. Writing complex expressions is fine as long as they are readable. instead of the equality operator. For example: rect. you can solve the problem. It is often a good idea to break a complex expression into a series of assignments to temporary variables. which may not be what you want. very often the problem is not in the program. you will inherit the default behavior from the parent class.getHeight())). and check the results. Read the documentation for the methods you invoke. • When you apply the equality operator.setLocation(rect. for user-defined objects). in the condition of an if. while or for statement. In order to program.getLocation().getWidth(). If you meant to check deep equality. =. To make sure you understand the flow of execution in your program. -rect. Can be rewritten as . it’s in your mental model. ==. • Some Java libraries expect user-defined objects to define methods like equals. you should use the equals method(or define one. there should be only a small amount of new code that is not known to be correct. because you may be executing inherited code without realizing it.translate (-rect. you might get an expression that is syntactically legal. If you encounter a problem. but they can be hard to debug. to an object. especially if it involves invocations to Java methods. ==. If you don’t define them yourself. you should be building and testing components as you develop the program. Try out the methods by invoking the methods directly with simple test cases. Once you find the discrepancy between your model and reality.” I’ve got a big hairy expression and it doesn’t do what I expect. but it doesn’t do what you expect. The best way to correct your mental model is to break the program into its components(usually the classes and methods) and test each component independently. Here are some common semantic errors that you might want to check for: • If you use the assignment operator. If your program that doesn’t do what you expect. Of course. • Inheritance can lead to subtle semantic errors.

x+a.getLocation(). b. if you are translating the x expression 2π into Java.max(a. int dy = -rect. I’ve got a method that doesn’t return what I expect.width. it will also be more readable for other people who haven’t memorized the rules of precedence.PI.y. b. int y2 = Math.x+b. For example.x+b. Math.x) Math. Math.min(a.B. you don’t have a chance to print the return value before returning.y+b.max(a.min(a.y+b. b. . and easier to debug. Another problem that can occur with big expressions is that the order of evaluation may not be what you expect. because we can check the types of the intermediate variables and display their values. rect.getHeight(). use parentheses. So this expression computes xπ/2. y2-y1). instead of public Rectangle intersection(Rectangle a.max(a.translate(dx.width.x.min(a. int y2 = Math. b. b. A good way to debug expressions is to add parentheses to make the order of evaluation explicit. you might write double y = x / 2 * Math. For example. Point newLocation = location. The explicit version is easier to read. Rectangle b) { return new Rectangle( Math.min(a. Any time you are not sure of the order of evaluation. If you have a return statement with a complex expression.width).x. b. Again.3 Semantic errors 179 int dx = -rect. x2-x1. Point location = rect. because the variable names provide additional documentation.x+a. and are evaluated from left to right. dy).max(a.y). b.width)-Math. double y = x /(2 * Math. Not only will the program be correct(in the sense of doing what you intend).y+a. int x2 = Math. } Now you have the opportunity to display any of the intermediate variables before returning.PI).y). Rectangle rect = new Rectangle(x1.min(a. Rectangle b) { int x1 = Math. b. return rect.x).min(a. } You could write public Rectangle intersection(Rectangle a.x. you can use a temporary variable. b. y1. That is not correct.y.height).getWidth().y+a.height.y) ). because multiplication and division have the same precedence.height)-Math.setLocation(newLocation).x).y. b.height.

showers. You should understand the problem well enough to describe it concisely. • Superstitious beliefs(“the computer hates me”) and magical thinking(“the program only works when I wear my hat backwards”). What is it doing? What are some possible causes of that behavior? When was the last time you had a working program. run-time. just before you fall asleep. but if you use print(at least in some environments) the output gets stored without being displayed until the next newline character gets output.180 Debugging My print statement isn’t doing anything If you use the println method. • Random walk programming(the attempt to program by writing every possible program and choosing the one that does the right thing). A fresh pair of eyes is just the thing. try changing some or all of the print statements to println. I’m really. If you find yourself suffering from any of these symptoms. I often find bugs when I am away from the computer and I let my mind wander. really stuck and I need help First of all. When you bring someone in to help. You program should be as simple as possible. causing the following symptoms: • Frustration and/or rage. make sure you have exhausted the techniques described here. think about the program. Even the best programmers occasionally get stuck. get up and go for a walk. and in bed. Sometimes you work on a program so long that you can’t see the error. or semantic? . try getting away from the computer for a few minutes. When you are calm. you may never see the stored output. the output gets displayed immediately. I really need help. It happens. • What kind of bug is it? compiler. If you suspect that this is happening to you. If the program terminates without producing a newline. Computers emit waves that affect the brain. Before you bring someone else in. You should have print statements in the appropriate places(and the output they produce should be comprehensible). No. and what did you do next? Sometimes it just takes time to find a bug. be sure to give them the information they need. Some of the best places to find bugs are trains. and you should be working on the smallest input that causes the error.

you might have to rethink the algorithm. and what you could have done to find it faster..3 Semantic errors 181 • If the bug occurs at compile-time or run-time. you will be able to find the bug more quickly.” 3. 5. When you are really stuck on a problem. and what have you learned? Often you will find that by the time you have explained the problem to someone else. how the error manifested itself. you will see the answer. But not always. Thank the rubber duck. “Rubber duck. This phenomenon is so pervasive that some people recommend a debugging technique called “rubber ducking.B.” Here’s how it works: 1. Here’s what’s happening. See the solution. or adjust your mental model of the program. put the rubber duck on the desk in front of you and say. I found the bug! Most often. why you made the error in the first place. In these cases. Explain the problem to the rubber duck. I am stuck on a problem.. what is the error message. or there is an error in your algorithm. work through some test cases by hand. When you fix a bug. or what is the new test case that fails? • What have you tried so far. it is obvious how to fix it. 4. or draw diagrams to represent the computation. and what part of the program does it indicate? • What was the last thing you did before this error occurred? What were the last lines of code that you wrote. . Next time you see something similar. Take some time away from the computer to think about the program. Buy a standard-issue rubber duck. when you find a bug. Take a second to think about what kind of bug it was. 2. don’t just dive in and start making new errors. Sometimes what seems to be a bug is really an indication that you don’t really understand the program.

182 Debugging .

The output is: java.out.Appendix C Input and Output in Java System objects System is the name of the Java class that contains methods and objects used to get input from the keyboard. When you invoke print and to create a new InputStreamReader. when Java prints an object. you will probably get something different. the package in which that type is defined. print text on the screen.out: System. Interestingly. On my machine the identifier is 80cc0e5.PrintStream@80cc0e5 As usual. you can print that has type BufferedInputStream. but if you run the same makes it possible to get input from the keyboard. Then you use in to create a new BufferedReader: BufferedReader keyboard = new BufferedReader(in).io. System.out is the name of the object we use to to display text on the screen. which is PrintStream.out). it does not make it easy to get input from the keyboard. you have to use System. you invoke them on the object named System. and a unique identifier for the object.println(System. and do file input/output(I/0). it prints the type of the object. . System. java. There is also an object named System. Keyboard input First. InputStreamReader in = new InputStreamReader( Unfortunately.

IOException is required by the compiler.readLine(). called readLine.out. The object types FileReader and BufferedReader are part of the insanely complicated class hierarchy Java uses to do incredibly common. System. there is not much value in the details of how this code fragment works. File input Here is an example that reads words from a file.println(s).println(s). Again. it should say so. For example: String s = keyboard. the declaration throws FileNotFoundException. } public static void processFile(String filename) throws FileNotFoundException. . IOException { FileReader fileReader = new FileReader(filename).out. System. There is a rule in Java that if a method might cause an exception. } } This program reads each line of the named file(/usr/dict/words) into a String and then prints the line. and they might cause an IOException. public static void main(String[] args) throws FileNotFoundException. There are things that can go wrong when you invoke readLine. reads a line from the keyboard and prints the result. while (true) { String s = in. if (s == null) break. You can think of throwing an exception as similar to throwing a tantrum. There is only one problem. The syntax looks like this: public static void main(String[] args) throws IOException { // body of main } This indicates that main might “throw” an IOException. Other than that. IOException { processFile("/usr/dict/words"). BufferedReader in = new BufferedReader(fileReader). simple things.readLine(). that gets input from the keyboard and converts it into a String.184 Input and Output in Java The point of all this manipulation is that there is a method you can invoke on a BufferedReader.

Here is a complete example: import java.setVisible(true). this code from http://thinkapjava. } } You can download GraphicsDemo.Graphics. gd. . gd. In main we create a GraphicsDemo object. This appendix provides examples and exercises that demonstrate Java graphics. 100. 400). GraphicsDemo extends Frame.1 Java 2D Graphics There are a number of ways to create graphics in Java. 200. and then make the Frame visible. set its width and height. A Frame appears as a window on the screen.setSize(400. import java. some more complicated than others. public class GraphicsDemo extends Frame { public static void main(String[] args) { GraphicsDemo gd = new GraphicsDemo().com/code/ The first lines import the classes we need from java. 200).Frame.awt.awt. which means that a GraphicsDemo object is a kind of Frame that has all of the Frame methods. The simplest is to use java.awt.Graphics.fillOval(100. } public void paint(Graphics g) { g.awt.Appendix D Graphics

com/javase/6/docs/api/java/awt/Graphics. D.html. . Other methods include drawLine.2 Graphics methods To draw things on the screen. The previous example uses fillOval. If you run this code. fillOval takes four integers as arguments. The bounding box itself is not drawn. Cartesian coordinates increase to the right and up. By convention. You can read the documentation of these methods at http://download. bounding box inscribed oval The usual way to specify a bounding box is to give the location of the upper-left corner and the width and height. drawRect and more. which is the rectangle in which the oval will be drawn (as shown in the figure). you should see a black circle on a gray background. The usual way to specify a location is to use a coordinate system. only the oval is. D.186 Graphics paint is a special method that gets invoked by the system when the Frame needs to be drawn. as shown in the figure. where each location is identified by an x-coordinate (distance along the x-axis) and a y-coordinate. These arguments specify a bounding box. you invoke methods on the graphics object.3 Coordinates You are probably familiar with Cartesian coordinates in two dimensions. oracle.

we .4 Color To choose the color of a shape. We can use the oval we just drew as the face. invoke setColor: g. Other special colors include: black blue cyan darkGray gray lightGray magenta orange pink red white yellow You can create other colors by specifying red. each pixel corresponds to a dot on the screen.5 Mickey Mouse Let’s say we want to draw a picture of Mickey Mouse. Color. draw the flag of Japan.awt. 0) positive y negative y By convention. a red circle on white background that is wider than it is tall.html. Coordinates are always integers. green and blue (RGB) values. If you want to use a floating-point value as a is a special value provided by the Color class. D. To make the code more readable. everything that gets drawn will be this color. Java follows this convention. and then add ears. to use it you have to import java.4 Color Cartesian coordinates positive y Java graphical coordinates 187 positive x origin (0. setColor changes the current color. You can control the Coordinates are measured in pixels. 0) negative x positive x origin (0.Color.setBackground. until you invoke setColor again. computer graphics systems to use a variation on Cartesian coordinates in which the origin is in the upper-left corner of the window. A typical screen is about 1000 pixels wide. background color of the Frame by invoking As an exercise. and the direction of the positive y-axis is See http://download. you have to round it off (See Section D.

java. The next three lines create a smaller rectangle for the ears.translate(dx*2. and more ears all the way down until the smallest ears are only 3 pixels wide. The result should look like Mickey Moose: . dx.x. half. 0). The result looks like this: You can download this code from http://thinkapjava. bb.y. and ears on those ears.1 Modify Mickey. We translate the rectangle up and left for the first ear.width/2. bb. Rectangle bb) { half).188 will use Rectangles to represent bounding boxes.height).x. -dx/2). } The first line draws the face. half). public void fillOval(Graphics g.translate(-dx/2. Graphics int dx = bb.width.height/2.fillOval(bb. bb.y. fillOval(g. Exercise to draw ears on the ears. } And here’s a method that draws Mickey: public void mickey(Graphics g. dy). bb. Rectangle bb) { fillOval(g. Rectangle half = new Rectangle(bb. then right for the second ear. fillOval(g. Here’s a method that takes a Rectangle and invokes fillOval. bb). int dy = bb. half.

Change the size of the Frame and run your program again. meaning that there is the same amount of space on each side. Create a new program named Snowperson. e. (Snowpeople exhibit a sexual dimorphism in which females are roughly 10% smaller than males.5 Mickey Mouse 189 Hint: you should only have to add or modify a few lines of code. To start. one-third of the width. The method named anim is there for your entertainment. it should have the same position and location as the bounding box).java.) Their widths should be proportional to their heights. You should remove it. the snowperson should adjust so that the snowperson always touches the top and bottom of the screen. the other should be 90% of the window height. The pair should be centered. c. it should draw a single oval that fills the entire bounding box (in other words. Modify drawSnowperson so that it draws three ovals stacked on top of each other like a snowperson.2 The purpose of this exercise is to practice using methods as a way of organizing and encapsulating complex tasks. Look over the source code as it currently exists and make sure you understand all the code in . One of them should be the same height as the window. Run it. Modify draw so that it draws two snowpeople side by side. a. b. A new window should appear with a bunch of blue circles and a bunch of red circles. no matter what the size the Frame is. The height and width of the snowperson should fill the bounding f. Again. and the three ovals touch. d. and their bounding boxes should be adjacent (which means that the drawn ovals probably will not quite touch). You can download a solution from http://thinkapjava. Change the size of the Frame and run your program again. but we will not be using it for this assignment. Exercise D. The size and proportion of the oval should adjust so that.D. Type in the code or get it from . Create a new method named drawSnowperson that takes the same parameters as draw. and centered. g. and the proportion of the three ovals stays the same. the oval is the same height.

and say that below that size. now let’s imagine that instead of making a particular snowperson pregnant. it would never stop. m. and that draws a simple face within the given bounding box. l. Modify drawSnowperson so that it invokes drawShirt in order to emblazon something on the chest (middle oval) of each snowperson. you can. You can use any of the drawing commands. as you resize the window. Modify draw so that after drawing Mrs. What would that line do? It would invoke drawSnowperson! Can you do that? Can you invoke a method from within itself? Well. Snowperson. Snowperson pregnant: I realize that this is a little risqu´.3 a. and the t-shirt. i. yes. Give the Snowpeople T-shirts: Add a new method called drawShirt that takes the usual parameters and that draws some sort of T-shirt logo within the bounding box. Adding something to drawSnowperson affects all snowpeople. but you can get as elaborate as you like. and replace the contents of draw with a single line that invokes moire. Add the following code to your project. What if we draw a big snowperson. j. k. and all the features should fit within the oval (with the possible exception of ears). n. . we want to make all snowpeople pregnant. we would add a line to drawSnowperson. b. Then we have to put an even smaller snowperson in the small abdomen oval. and so on and so on.190 Graphics h. it invokes drawSnowperson to put a small snowperson in the abdomen. Notice that adding something to draw affects just one snowperson. the proportions of the face should not change. it is safe to add code at the end of the method so that after drawing the ovals. and the face. Modify drawSnowperson so that it invokes drawFace in order to fill in the top oval (the face).java. Ok. Instead of adding a line to draw. it draws a baby snowperson inside her abdomen oval. We would be drawing smaller and smaller snowpeople until doomsday! One solution is to pick a minimum snowperson size. we refuse to draw any more snowpeople. but there e is a point. Two eyes will suffice. Make Mrs. The problem is. and then put a small snowperson in the abdomen oval. although you might want to avoid drawString because it is not easy to guarantee that the string will fit within the bounding box. but you have to be careful. Exercise D. The bounding box you pass to drawFace should be the same as the bounding box that created the face oval. Now that you have that line. SO DON’T DO THIS YET!!! Think for a minute. Add faces: Write a method called drawFace that takes the same parameters as drawSnowperson. Add a line at the beginning of drawSnowperson that checks the height of the bounding box and returns immediately if it is less than 10. Again. Create a new program named Moire.

while (i<bb.width) { bb. i.y.D.advanced. Look at the code before you run it and draw a sketch of what you expect it to do. see the following: http://math. as in the following figure.html d.5 Mickey Mouse public static void moire(Graphics g. Did you get what you expected? For a partial explanation of what is going on. Rectangle bb) { int i = 1. Write a method named radial that draws a radial set of line segments as shown in the figure.drawOval (bb. .x. Now run it. Modify the program so that the circles are drawn in the center of the screen and concentric. Unlike in the figure. i = i + 2. Play around and see what you can create. See what happens to the image. e concentric circles radial Moire pattern f.hws. the distance between the circles should be small enough that the Moir´ interference is apparent. but they should be close enough together to create a Moir´ pattern. e. } } 191 c.html i). Modify the program so that the space between the circles is larger or smaller. e g. Just about any kind of graphical pattern can generate Moir´-like interference e patterns.

192 Graphics .

Sign up to vote on this title
UsefulNot useful