Ebook Java, Java, Java: Object-Oriented problem solving (Third edition) - Part 1 include of the following topics: Chapter 0 Computers, Objects, and Java; Chapter 1 Java Program Design and Development; Chapter 2 Objects: Using, Creating, and Defining; Chapter 3 Methods: Communicating with Objects; Chapter 4 Input/Output: Designing the User Interface; Chapter 5 Java Data and Operators; Chapter 6 Control Structures; Chapter 7 Strings and String Processing; Chapter 8 Inheritance and Polymorphism.
Java, Java, Java Object-Oriented Problem Solving Third Edition R Morelli and R Walde Trinity College Hartford, CT June 25, 2017 This work is licensed under a Creative Commons Attribution 4.0 International License (CC BY 4.0) This book was previously published by Pearson Education, Inc Preface to the Open Source Edition Java, Java, Java, 3e was previously published by Pearson Education, Inc The first edition (2000) and the second edition (2003) were published by Prentice-Hall In 2010 Pearson Education, Inc reassigned the copyright to the authors, and we are happy now to be able to make the book available under an open source license This PDF edition of the book is available under a Creative Commons Attribution 4.0 International License, which allows the book to be used, modified, and shared with attribution: (https://creativecommons.org/licenses/by/4.0/) – Ralph Morelli and Ralph Walde – Hartford, CT – December 30, 2016 i ii Preface to the Third Edition We have designed this third edition of Java, Java, Java to be suitable for a typical Introduction to Computer Science (CS1) course or for a slightly more advanced Java as a Second Language course This edition retains the “objects first” approach to programming and problem solving that was characteristic of the first two editions Throughout the text we emphasize careful coverage of Java language features, introductory programming concepts, and object-oriented design principles The third edition retains many of the features of the first two editions, including: • Early Introduction of Objects • Emphasis on Object Oriented Design (OOD) • Unified Modeling Language (UML) Diagrams • Self-study Exercises with Answers • Programming, Debugging, and Design Tips • From the Java Library Sections • Object-Oriented Design Sections • End-of-Chapter Exercises • Companion Web Site, with Power Points and other Resources The In the Laboratory sections from the first two editions have been moved onto the book’s Companion Web Site Table shows the Table of Contents for the third edition What’s New in the Third Edition The third edition has the following substantive changes: • Although the book retains its emphasis on a “running example” that is revisited in several chapters, the CyberPet examples have been replaced with a collection of games and puzzle examples The CyberPet examples from earlier editions will be available on the Companion Web Site iii iv Table 1: Table of Contents for the Third Edition Chapter Chapter Chapter Chapter Chapter Chapter Chapter Chapter Chapter Chapter Chapter Chapter 10 Chapter 11 Chapter 12 Chapter 13 Chapter 14 Chapter 15 Chapter 16 Topic Computers, Objects, and Java (revised) Java Program Design and Development Objects: Defining, Creating, and Using Methods: Communicating with Objects (revised) Input/Output: Designing the User Interface (new) Java Data and Operators Control Structures Strings and String Processing Inheritance and Polymorphism (new) Arrays and Array Processing Exceptions: When Things Go Wrong Files and Streams Recursive Problem Solving Graphical User Interfaces Threads and Concurrent Programming Sockets and Networking (expanded) Data Structures: Lists, Stacks, and Queues (revised and expanded) • Chapters (Computers, Objects, and Java) and (Java Program Design and Development) have been substantially reorganized and rewritten The new presentation is designed to reduce the pace with which new concepts are introduced The treatment of objectoriented (OO) and UML concepts has also been simplified, and some of the more challenging OO topics, such as polymorphism, have been moved to a new Chapter • The new Java 1.5 Scanner class is introduced in Chapter and is used to perform simple input operations • Chapter (Input/Output: Designing the User Interface) has been completely written Rather than relying primarily on applet interfaces, as in the second edition, this new chapter provides independent introductions to both a command-line interface and a graphical user interface (GUI) Instructors can choose the type of interface that best suits their teaching style The command-line interface is based on the BufferedReader class and is used throughout the rest of the text The GUI is designed to work with either graphical applications or applets Both approaches are carefully presented to highlight the fundamentals of user-interface design The chapter concludes with an optional section that introduces file I/O using the new Scanner class • Much of the discussion of inheritance and polymorphism, which was previously woven through the first five chapters in the second edition, has been integrated into a new Chapter • An optional graphics track is woven throughout the text Beginning with simple examples in Chapters and 2, this track also includes v some of the examples that were previously presented in Chapter 10 of the second edition • Chapter 15, on Sockets and Networking, is expanded to cover some of the more advanced Java technologies that have emerged, including servlets and Java Server Pages • Chapter 16, on Data Structures, has been refocused on how to use data structures It makes greater use of Java’s Collection Framework, including the LinkedList and Stack classes and the List interface It has been expanded to cover some advanced data structures, such as sets, maps, and binary search trees The Essentials Edition An Essentials Edition of the third edition, which will include Chapters 012, will be published as a separate title The Essentials Edition will cover those topics (Chapters 0-9) that are covered in almost all introductory (CS1) courses, but it will also include topics (Exceptions, File I/O, and Recursion) that many CS1 instructors have requested Why Start with Objects? The Third Edition still takes an objects-early approach to teaching Java, with the assumption that teaching beginners the “big picture” early gives them more time to master the principles of object-oriented programming This approach seems now to have gained in popularity as more and more instructors have begun to appreciate the advantages of the object-oriented perspective Object Orientation (OO) is a fundamental problem solving and design concept, not just another language detail that should be relegated to the middle or the end of the book (or course) If OO concepts are introduced late, it is much too easy to skip over them when push comes to shove in the course The first time I taught Java in our CS1 course I followed the same approach I had been taking in teaching C and C++ — namely, start with the basic language features and structured programming concepts and then, somewhere around midterm, introduce object orientation This approach was familiar, for it was one taken in most of the textbooks then available in both Java and C++ One problem with this approach was that many students failed to get the big picture They could understand loops, if-else constructs, and arithmetic expressions, but they had difficulty decomposing a programming problem into a well-organized Java program Also, it seemed that this procedural approach failed to take advantage of the strengths of Java’s object orientation Why teach an object-oriented language if you’re going to treat it like C or Pascal? I was reminded of a similar situation that existed when Pascal was the predominant CS1 language Back then the main hurdle for beginners was procedural abstraction — learning the basic mechanisms of procedure call vi and parameter passing and learning how to design programs as a collection of procedures Oh! Pascal!, my favorite introductory text, was typical of a “procedures early” approach It covered procedures and parameters in Chapter 2, right after covering the assignment and I/O constructs in Chapter It then covered program design and organization in Chapter It didn’t get into loops, if-else, and other structured programming concepts until Chapter and beyond Today, the main hurdle for beginners is the concept of object abstraction Beginning programmers must be able to see a program as a collection of interacting objects and must learn how to decompose programming problems into well-designed objects Object orientation subsumes both procedural abstraction and structured programming concepts from the Pascal days Teaching objects-early takes a top-down approach to these three important concepts The sooner you begin to introduce objects and classes, the better the chances that students will master the important principles of object orientation Java is a good language for introducing object orientation Its object model is better organized than C++ In C++ it is easy to “work around” or completely ignore OO features and treat the language like C In Java there are good opportunities for motivating the discussion of object orientation For example, it’s almost impossible to discuss GUI-based Java applications without discussing inheritance and polymorphism Thus rather than using contrived examples of OO concepts, instructors can use some of Java’s basic features — the class library, Swing and GUI components — to motivate these discussions in a natural way Organization of the Text The book is still organized into three main parts Part I (Chapters 0-4) introduces the basic concepts of object orientation and the basic features of the Java language Part II (Chapters 5-9) focuses on remaining language elements, including data types, control structures, string and array processing, and inheritance and polymorphism Part III (Chapters 10-16) covers advanced topics, including exceptions, file I/O, recursion, GUIs, threads and concurrent programming, sockets and networking, data structures, servlets, and Java Server Pages The first two parts make up the topics that are typically covered in an introductory CS1 course The chapters in Part III are self-contained and can be selectively added to the end of a CS1 course if time permits The first part (Chapters through 4) introduces the basic concepts of object orientation, including objects, classes, methods, parameter passing, information hiding, and a little taste of inheritance, and polymorphism The primary focus in these chapters is on introducing the basic idea that an object-oriented program is a collection of objects that communicate and cooperate with each other to solve problems Java language elements are introduced as needed to reinforce this idea Students are given the basic building blocks for constructing Java programs from scratch Although the programs in the first few chapters have limited functionality in terms of control structures and data types, the priority is placed vii Table 2: A one-semester course Weeks 2-3 6–7 10 11 12 13 Topics Object Orientation, UML Program Design and Development Objects and Class Definitions Methods and Parameters Selection structure (if-else) User Interfaces and I/O Data Types and Operators Control Structures (Loops) Structured Programming String Processing (loops) Inheritance and Polymorphism Array Processing Recursion Advanced Topic (Exceptions) Advanced Topic (GUIs) Advanced Topic (Threads) Chapters Chapter Chapter Chapter Chapter Chapter Chapter Chapter Chapter Chapter Chapter Chapter 12 Chapter 10 Chapter 11 Chapter 15 on how objects are constructed and how they interact with each other through method calls and parameter passing The second part (Chapters through 9) focuses on the remaining language elements, including data types and operators (Chapter 5), control structures (Chapter 6), strings (Chapter 7), and arrays (Chapter 9) It also provides thorough coverage of inheritance and polymorphism, the primary mechanisms of object orientation: (Chapter 8) Part three (Chapters 10 through 16) covers a variety of advanced topics (Table 1) Topics from these chapters can be used selectively depending on instructor and student interest Throughout the book, key concepts are introduced through simple, easy-to-grasp examples Many of the concepts are used to create a set of games, which are used as a running example throughout the text Our pedagogical approach focuses on design Rather than starting of with language details, programming examples are carefully developed with an emphasis on the principles of object-oriented design Table2 provides an example syllabus from our one-semester CS1 course Our semester is 13 weeks (plus one reading week during which classes not meet) We pick and choose from among the advanced topics during the last two weeks of the course, depending on the interests and skill levels of the students Ralph Morelli June 25, 2017 viii 378 CHAPTER • Inheritance and Polymorphism SELF-STUDY EXERCISES EXERCISE 8.13 Define a class NimPlayer that plays the optimal strategy for OneRowNim This strategy was described in Chapter 8.6.8 Playing OneRowNim Let’s now write a main() method to play OneRowNim: ☛ ✟ public s t a t i c void main ( S t r i n g a r g s [ ] ) { KeyboardReader kb = new KeyboardReader ( ) ; OneRowNim game = new OneRowNim ( ) ; kb prompt ( ”How many computers a r e playing , , , or 2? ” ) ; i n t m = kb g e t K e y b o a r d I n t e g e r ( ) ; f o r ( i n t k = ; k < m; k++) { kb prompt ( ”What type o f player , ” + ”NimPlayerBad = , or NimPlayer = ? ” ) ; i n t c h o i c e = kb g e t K e y b o a r d I n t e g e r ( ) ; i f ( c h o i c e == ) { I P l a y e r computer = new NimPlayerBad ( game ) ; game addComputerPlayer ( computer ) ; } else { I P l a y e r computer = new NimPlayer ( game ) ; game addComputerPlayer ( computer ) ; } } game play ( kb ) ; } // m a i n ( ) Generality ✡ ✠ After creating a KeyboardReader and then creating an instance of OneRowNim, we prompt the user to determine how many computers are playing We then repeatedly prompt the user to identify the names of the IPlayer and use the addComputerPlayer() method to initialize the game Finally, we get the game started by invoking the play() method, passing it a reference to the KeyboardReader, our UserInterface Note that in this example we have declared a OneRowNim variable to represent the game This is not the only way to things For example, suppose we wanted to write a main() method that could be used to play a variety of different TwoPlayerGames Can we make this code more general? That is, can we rewrite it to work with any TwoPlayerGame? A OneRowNim object is also a TwoPlayerGame, by virtue of inheritance, and it is also a CLUIPlayableGame, by virtue of implementing that interface Therefore, we can use either of these types to represent the game Thus, one alternative way of coding this is as follows: ☛ ✟ TwoPlayerGame game = new OneRowNim ( ) ; I P l a y e r computer = new NimPlayer ( ( OneRowNim) game ) ; ( ( CLUIPlayableGame ) game ) play ( kb ) ; ✡ ✠ Here we use a TwoPlayerGame variable to represent the game However, note that we now have to use a cast expression, (CLUIPlayableGame), SECTION 8.6 • Case Study: A Two Player Game Hierarchy 379 in order to call the play() method If we don’t cast game in this way, Java will generate the following syntax error: ☛ ✟ OneRowNim j a v a : : cannot r e s o l v e symbol symbol : method play ( KeyboardReader ) l o c a t i o n : c l a s s TwoPlayerGame game play ( kb ) ; ˆ ✡ ✠ The reason for this error is that play() is not a method in the TwoPlayerGame class, so the compiler cannot find the play() method By using the cast expression, we are telling the compiler to consider game to be a CLUIPlayableGame That way it will find the play() method Of course, the object assigned to nim must actually implement the CLUIPlayableGame interface in order for this to work at run time We also need a cast operation in the NimPlayer() constructor in order to make the argument (computer) compatible with that method’s parameter Another alternative for the main() method would be the following: ☛ ✟ CLUIPlayableGame game = new OneRowNim ( ) ; I P l a y e r computer = new NimPlayer ( ( OneRowNim) game ) ; ( ( TwoPlayerGame ) game ) addComputerPlayer ( computer ) ; game play ( kb ) ; nim play ( kb ) ; ✡ ✠ By representing the game as a CLUIPlayableGame variable, we don’t need the cast expression to call play(), but we need a different cast expression, (TwoPlayerGame), to invoke addComputerPlayer() Again, the reason is that the compiler cannot find the addComputerPlayer() method in the CLUIPlayableGame interface, so we must tell it to consider game as a TwoPlayerGame, which of course it is We still need the cast operation for the call to the NimPlayer() constructor All three of the code options that we have considered will generate something like the interactive session shown in Figure 8.25 for a game in which two IPlayers play each other Given our object-oriented design for the TwoPlayerGame hierarchy, we can now write generalized code that can play any TwoPlayerGame that implements the CLUIPlayableGame interface We will give a specific example of this in the next section 8.6.9 Extending the TwoPlayerGame Hierarchy Now that we have described the design and the details of the TwoPlayerGame class hierarchy, let’s use it to develop a new game If we’ve gotten the design right, developing new two-player games and adding them to the hierarchy should be much simpler than developing them from scratch The new game is a guessing game in which the two players take turns guessing a secret word The secret word will be generated randomly from CHAPTER • Inheritance and Polymorphism ✟ 380 ☛ How many computers a r e playing , , , or 2? {\ c o l o r { cyan }2} ∗∗∗ (1) (2) (3) The Rules o f One Row Nim ∗∗∗ A number o f s t i c k s between and 11 i s chosen Two p l a y e r s a l t e r n a t e making moves A move c o n s i s t s o f s u b t r a c t i n g between and s t i c k s from t h e c u r r e n t number o f s t i c k s ( ) A p l a y e r who cannot l e a v e a p o s i t i v e number o f s t i c k s f o r t h e o t h e r p l a y e r l o s e s Player Player Sticks Sticks Sticks Sticks Sticks Sticks Sticks Sticks ✡ is is left left left left left left left left a a : : : : : : : : NimPlayerBad NimPlayer 11 Who ’ s turn : P l a y e r NimPlayerBad t a k e s s t i c k s Who ’ s turn : P l a y e r NimPlayer t a k e s s t i c k s Who ’ s turn : P l a y e r NimPlayerBad t a k e s s t i c k s Who ’ s turn : P l a y e r NimPlayer t a k e s s t i c k s Who ’ s turn : P l a y e r NimPlayerBad t a k e s s t i c k s Who ’ s turn : P l a y e r NimPlayer t a k e s s t i c k s Who ’ s turn : P l a y e r NimPlayerBad t a k e s s t i c k s Game over ! Winner i s P l a y e r Nice game ✠ Figure 8.25: A typical run of the OneRowNim using a command-line user interface a collection of words maintained by the game object The letters of the word will be hidden with question marks, as in “????????.” On each turn a player guesses a letter If the letter is in the secret word, it replaces one or more question marks, as in “??????E?.” A player continues to guess until an incorrect guess is made and then it becomes the other player’s turn Of course, we want to develop a version of this game that can be played either by two humans, or by one human against a computer—that is, against an IPlayer—or by two different IPlayers Let’s call the game class WordGuess Following the design of OneRowNim, we get the design shown in Figure 8.26 The WordGuess class extends the TwoPlayerGame class and implements the CLUIPlayableGame interface We don’t show the details of the interfaces and the TwoPlayerGame class, as these have not changed Also, following the design of NimPlayerBad, the WordGuesser class implements the IPlayer interface Note how we show the association between WordGuess and zero or more IPlayers A WordGuess uses between zero and two instances of IPlayers, which in this game are implemented as WordGuessers Let’s turn now to the details of the WordGuess class, whose source code is shown in Figures 8.27 and 8.28 The game needs to have a supply of words from which it can choose a secret word to present to the players The getSecretWord() method will take care of this task It calculates a random number and then uses that number, together with a switch statement, to select from among several words that are coded right into the switch statement The secret word is stored in the secretWord variable The currentWord variable stores the partially guessed word Initially, currentWord consists entirely of question marks As the players SECTION 8.6 • Case Study: A Two Player Game Hierarchy 381 Figure 8.26: Design of the WordGuess class as part of TwoPlayerGame hierarchy make correct guesses, currentWord is updated to show the locations of the guessed letters Because currentWord will change as the game progresses, it is stored in a StringBuffer, rather than in a String Recall that Strings are immutable in Java, whereas a StringBuffer contains methods to insert letters and remove letters The unguessedLetters variable stores the number of letters remaining to be guessed When unguessedLetters equals 0, the game is over This condition defines the gameOver() method, which is inherited from TwoPlayerGame The winner of the game is the player who guessed the last letter in the secret word This condition defines the getWinner() method, which is also inherited from TwoPlayerGame The other methods that are inherited from TwoPlayerGame or implemented from the CLUIPlayableGame are also implemented in a straightforward manner A move in the WordGuess game consists of trying to guess a letter that occurs in the secret word The move() method processes the player’s guesses It passes the guessed letter to the guessLetter() method, which checks whether the letter is a new, secret letter If so, guessLetter() takes care of the various housekeeping tasks It adds the letter to previousGuesses, which keeps track of all the players’ guesses It decrements the number of unguessedLetters, which will become when all the letters have been guessed And it updates currentWord to show where all occurrences of the secret letter are located Note how 382 CHAPTER • Inheritance and Polymorphism ☛ ✟ public c l a s s WordGuess extends TwoPlayerGame implements CLUIPlayableGame { p r i v a t e S t r i n g secretWord ; p r i v a t e S t r i n g B u f f e r currentWord ; p r i v a t e S t r i n g B u f f e r previousGuesses ; private int unguessedLetters ; public WordGuess ( ) { secretWord = getSecretWord ( ) ; currentWord = new S t r i n g B u f f e r ( secretWord ) ; previousGuesses = new S t r i n g B u f f e r ( ) ; f o r ( i n t k = ; k < secretWord l e n g t h ( ) ; k++) currentWord setCharAt ( k , ’ ? ’ ) ; u n g u e s s e d L e t t e r s = secretWord l e n g t h ( ) ; } // WordGuess ( ) public S t r i n g g e t P r e v i o u s G u e s s e s ( ) { r e t u r n previousGuesses t o S t r i n g ( ) ; } // g e t P r e v i o u s G u e s s e s ( ) public S t r i n g getCurrentWord ( ) { r e t u r n currentWord t o S t r i n g ( ) ; } // getCurrentWord ( ) p r i v a t e S t r i n g getSecretWord ( ) { i n t num = ( i n t ) ( Math random ( ) ∗ ) ; switch (num) { c a s e : r e t u r n ”SOFTWARE” ; c a s e : r e t u r n ”SOLUTION” ; c a s e : r e t u r n ”CONSTANT” ; c a s e : r e t u r n ”COMPILER” ; c a s e : r e t u r n ”ABSTRACT” ; c a s e : r e t u r n ”ABNORMAL” ; c a s e : r e t u r n ”ARGUMENT” ; c a s e : r e t u r n ”QUESTION” ; c a s e : r e t u r n ”UTILIZES” ; c a s e : r e t u r n ”VARIABLE” ; d e f a u l t : r e t u r n ”MISTAKES” ; } //s w i tc h } // getSecretWord ( ) p r i v a t e boolean g u e s s L e t t e r ( char l e t t e r ) { previousGuesses append ( l e t t e r ) ; i f ( secretWord indexOf ( l e t t e r ) == −1) r e t u r n f a l s e ; // l e t t e r i s not i n secretWord e l s e // f i n d p o s i t i o n s o f l e t t e r i n secretWord { f o r ( i n t k = ; k < secretWord l e n g t h ( ) ; k++) { i f ( secretWord charAt ( k ) == l e t t e r ) { i f ( currentWord charAt ( k ) == l e t t e r ) r e t u r n f a l s e ; //// a l r e a d y guessed currentWord setCharAt ( k , l e t t e r ) ; u n g u e s s e d L et t e r s −−; //one l e s s t o f i n d } // i f } // f o r return true ; } // e l s e } // g u e s s L e t t e r ( ) ✡ public S t r i n g g e t R u l e s ( ) { // Overridden from TwoPlayerGame r e t u r n ”\n∗∗∗ The Rules o f Word Guess ∗∗∗\n” + ” ( ) The game g e n e r a t e s a s e c r e t word \ n” + ” ( ) Two p l a y e r s a l t e r n a t e t a k i n g moves \ n” + ” ( ) A move c o n s i s t s o f guessing a l e t t e r i n t h e word \ n” + ” ( ) A p l a y e r c o n t i n u e s guessing u n t i l a l e t t e r i s wrong \ n” + ” ( ) The game i s over when a l l l e t t e r s o f t h e word a r e guessed\n” + ” ( ) The p l a y e r guessing t h e l a s t l e t t e r o f t h e word wins \ n” ; } // g e t R u l e s ( ) ✠ Figure 8.27: The WordGuess class, Part I guessLetter() uses a for-loop to cycle through the letters in the secret word As it does so, it replaces the question marks in currentWord with the correctly guessed secret letter The guessLetter() method returns false if the guess is incorrect In that case, the move() method changes the SECTION 8.6 • Case Study: A Two Player Game Hierarchy 383 ☛ ✟ public boolean gameOver ( ) { // From TwoPlayerGame r e t u r n ( u n g u e s s e d L e t t e r s