
2,990 497 22MB
Pages 1137 Page size 576.5 x 721 pts Year 2008
Pedagogical Highlights: Just the Facts, a summary of the fundamental ideas at the end of each chapter Bug Extermination, tips on some commonly occurring bugs and hints for how best to avoid them Examples that follow an easy-to-understand format: problem description, Java solution, typical output, and discussion. Programming examples are stand-alone applications that are dissected line by line Crossword puzzles that test student understanding of terminology Short answer questions that check basic comprehension Short programming problems that reinforce the concepts of the chapter Longer programming assignments that require some creativity and algorithm development The Bigger Picture, optional topics in computer science that explore a larger framework of ideas introduced in the chapter and extend beyond the study of programming “The authors have done a fantastic job in explaining object-oriented concepts in simple terms.” Shyamal Mitra, University of Texas at Austin “Sensible, clear, coherent explanations of interfaces, inheritance and polymorphism…. The examples are so interesting and fun.… The exercises are great.” Kathy Liszka, University of Akron “The text does a good job of focusing on the core concepts important to beginners, without getting bogged down with the esoteric and seldom-used aspects of Java and OOP…. The Bigger Picture sections are excellent.” Blayne Mayfield, Oklahoma State University
Java Programming: From the Ground Up
Md. Dalim #995054 12/3/08 Cyan Mag Yelo Black
Debugging and tracing exercises that can be done without a computer
Java Programming: From the Ground Up
Java Programming employs a distinctive pedagogy that is both challenging and engaging. The text begins with programming fundamentals, moves through the object-oriented paradigm, and concludes with basic graphics and event-driven programming. The modularity of the text makes the book suitable for introductory and intermediate-level programming courses while the separation of graphics from basic programming structures makes the text easily adaptable to different styles of courses. Moreover, this approach is especially helpful to beginners, who when presented with programs that mix fundamentals with GUI design, events, and OOP, have difficulty separating these concepts.
Bravaco Simonson
Ralph Bravaco
Shai Simonson
Java Programming From the Ground Up
sim23356_FM_USE.indd i
Ralph Bravaco
Shai Simonson
Stonehill College
Stonehill College
12/15/08 7:30:44 PM
JAVA PROGRAMMING: FROM THE GROUND UP Published by McGraw-Hill, a business unit of The McGraw-Hill Companies, Inc., 1221 Avenue of the Americas, New York, NY 10020. Copyright © 2010 by The McGraw-Hill Companies, Inc. All rights reserved. No part of this publication may be reproduced or distributed in any form or by any means, or stored in a database or retrieval system, without the prior written consent of The McGraw-Hill Companies, Inc., including, but not limited to, in any network or other electronic storage or transmission, or broadcast for distance learning. Some ancillaries, including electronic and print components, may not be available to customers outside the United States. This book is printed on acid-free paper. 1 2 3 4 5 6 7 8 9 0 VNH/VNH 0 9 ISBN 978–0–07–352335–4 MHID 0–07–352335–6 Global Publisher: Raghothaman Srinivasan Director of Development: Kristine Tibbetts Developmental Editor: Lora Neyens Senior Marketing Manager: Curt Reynolds Project Manager: Melissa M. Leick Senior Production Supervisor: Laura Fuller Senior Media Project Manager: Tammy Juran Associate Design Coordinator: Brenda A. Rolwes Cover Designer: Studio Montage, St. Louis, Missouri (USE) Cover Image: © Getty Images Lead Photo Research Coordinator: Carrie K. Burger Compositor: Macmillan Publishing Solutions Typeface: 10/12 Times Roman Printer: R. R. Donnelley, Jefferson City, MO Library of Congress Cataloging-in-Publication Data Bravaco, Ralph. Java programming : from the ground up / Ralph Bravaco, Charles Simonson. -- 1st ed. p. cm. Includes index. ISBN 978–0–07–352335–4 --- ISBN 0–07–352335–6 (hard copy : alk. paper) 1. Java (Computer program language) I. Simonson, Charles. II. Title. QA76.73.J38B68 2010 005.13'3--dc22 2008047782
www.mhhe.com
sim23356_FM_USE.indd ii
12/15/08 7:30:48 PM
DEDICATION For Kathryn and Emily —R.B. For Andrea, Zosh, Yair, and Yona —S.S.
sim23356_FM_USE.indd iii
12/15/08 7:30:48 PM
sim23356_FM_USE.indd iv
12/15/08 7:30:48 PM
CONTENTS Preface
xi Part
1
The Fundamental Tools 1 C h a p te r
1
An Introduction to Computers and Java 1.1 1.2 1.3 1.4 1.5 1.6
Introduction 2 What Is a Computer? 3 The Hardware 3 The Software 6 Programming and Algorithms In Conclusion 11
10
Exercises 13 The Bigger Picture: 1. Machine Language and Computer Architecture 16 2. Algorithms 16 3. Storing Integers 17 C h a p te r
2.1 2.2 2.3 2.4 2.5
23
Introduction 23 In the Beginning… 23 Data Types and Expressions 30 In the Beginning . . . Again 47 In Conclusion 50 Exercises 53 The Bigger Picture: 1. Binary Encoding I —ASCII Encoding 58 2. Binary Encoding II —Decimal Encoding 59 3. Boolean Types 60
C h a p te r
3
Variables and Assignment 3.1 Introduction 61 3.2 Variables 61
Exercises 86 The Bigger Picture: Bitwise Operators, Boolean Operators, and an Interesting Puzzle 93 C h a p te r
4
Selection and Decision: if Statements
2
Expressions and Data Types
2
3.3 Variable Declarations: How a Program Obtains Storage for Data 64 3.4 How a Program Stores Data: Initialization and Assignment 65 3.5 How a Program Uses Stored Data 67 3.6 Obtaining Data from Outside a Program 69 3.7 A Scanner Object for Interactive Input 70 3.8 Final Variables 72 3.9 Type Compatibility and Casting 73 3.10 A Few Shortcuts 76 3.11 Increment and Decrement Operators 80 3.12 An Expanded Precedence Table 82 3.13 Style 82 3.14 In Conclusion 82
61
4.1 4.2 4.3 4.4 4.5
97
Introduction 97 The if Statement 98 The if-else Statement 102 The switch Statement 115 In Conclusion 123 Exercises 127 The Bigger Picture: “Go To” Statement Considered Harmful 135
C h a p te r
5
Repetition
137
5.1 Introduction 137 5.2 The while statement 137 5.3 Loops: A Source of Power, a Source of Bugs 144 5.4 The do-while Statement 147 5.5 The for Statement 151 5.6 Nested Loops 160 v
sim23356_FM_USE.indd v
12/15/08 7:30:49 PM
vi
Contents
5.7 The break Statement Revisited 5.8 In Conclusion 171
168
Exercises 174 The Bigger Picture: 1. Floating-Point Arithmetic 185 2. Loops and Computability 188 C h a p te r
Methods 6.1 6.2 6.3 6.4 6.5
6
Exercises 224 The Bigger Picture: 1. Time Complexity 234 2. Recursion, a Preview 236
7
7.1 Introduction 239 7.2 Array Fundamentals: Declaration and Instantiation 240 7.3 Using an Array 242 7.4 Array Initialization 249 7.5 A Caveat: Using the ⴝ and the ⴝⴝ Operators 250 7.6 Arrays and Methods 252 7.7 Sorting an Array with Insertion Sort 255 7.8 Searching an Array 259 7.9 Two-Dimensional Arrays 264 7.10 A Case Study—Putting It All Together 271 7.11 In Conclusion 278 Exercises 281 The Bigger Picture: 1. Array Implementation 295 2. Sorting 296 C h a p te r
8
Recursion
298
8.1 Introduction 298 8.2 A Simple Recursive Method
Part
2
Principles of Object-Oriented Programming 347 C h a p te r
9
Objects and Classes I: Encapsulation, Strings, and Things 348
Arrays and Lists: One Name for Many Data 239
sim23356_FM_USE.indd vi
Exercises 329 The Bigger Picture: The Complexity of Recursive Algorithms 337
191
Introduction 191 Java’s Predefined Methods 192 Writing Your Own Methods 200 Method Overloading 216 In Conclusion 222
C h a p te r
8.3 Recursive Thinking 301 8.4 The Runtime Stack: Tail Recursion versus Classic Recursion 311 8.5 Quicksort—A Classic Recursive Algorithm 315 8.6 A Case Study—Designing an Anagram Generator 319 8.7 In Conclusion 326
299
9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9 9.10
Introduction 348 Objects 349 From Classes Come Objects 350 Java Libraries and Packages 352 Strings are Objects 354 The StringBuilder Class 369 The Mysterious String[] args 374 Classes for Handling Files 375 The DecimalFormat Class 381 In Conclusion 385 Exercises 387 The Bigger Picture: Bioinformatics 394
C h a p te r
10
Objects and Classes II: Writing Your Own Classes 403 10.1 10.2 10.3 10.4 10.5 10.6
Introduction 403 A Dice Class 403 A More General Look at Classes Using the Dice Class 410 A TriviaTest Class 413 Encapsulation and Information Hiding 418
408
12/15/08 7:30:49 PM
vii
Contents
12.7 12.8 12.9 12.10 12.11 12.12 12.13
10.7 The Keyword static 420 10.8 The Omnipresent main(String[] args) Method 431 10.9 The Keyword this 432 10.10 Garbage Collection 436 10.11 A Case Study: Classy Sounds 438 10.12 In Conclusion 447 Exercises 450 The Bigger Picture: Software Engineering 460
C h a p te r
11.1 11.2 11.3 11.4 11.5 11.6 11.7 11.8 11.9 11.10 11.11
Exercises 565 The Bigger Picture: Multiple Inheritance 583 C h a p te r
11
Designing with Classes and Objects Introduction 463 The Problem: A Video Poker Game Problem Statement 466 Determine the Classes 467 Determine Responsibilities of Each Class 468 Iterative Refinement 470 Some Attributes 473 Video Poker After Some Refinement 473 Implementing the Video Poker Application 474 In Conclusion 501 Appendix: The Complete Application 501
463 464
Exercises 513 The Bigger Picture: Software Design and the Model-ViewController Paradigm 520
C h a p te r
Inheritance 12.1 12.2 12.3 12.4
12 523
Introduction 523 A Basic Remote Control Unit 523 Inheritance and Encapsulation 535 The is-a Relationship: A DirectRemote is-a Remote 535 12.5 Inheritance via Factoring: Movies and Plays 535 12.6 Inheritance via Abstract Classes 540
sim23356_FM_USE.indd vii
Extending the Hierarchy 541 Upcasting and Downcasting 543 Everything Inherits: The Object Class 547 Interfaces 553 A Generic Sort 558 Composition and the has-a Relationship 561 In Conclusion 562
13
Polymorphism 589 13.1 13.2 13.3 13.4 13.5 13.6 13.7
Introduction 589 Two Simple Forms of Polymorphism 589 Dynamic (or Late) Binding 591 Polymorphism Makes Programs Extensible 598 Interfaces and Polymorphism 600 Polymorphism and the Object Class 604 In Conclusion 612 Exercises 614 The Bigger Picture: Programming Paradigms and Styles 628
Part
3
More Java Classes 637 C h a p te r
14
More Java Classes: Wrappers and Exceptions 638 14.1 14.2 14.3 14.4
Introduction 638 The Wrapper Classes 639 Exceptions and Exception Handling 651 In Conclusion 672 Exercises 676 The Bigger Picture: APIs and Exceptions
C h a p te r
686
15
Stream I/O and Random Access Files 15.1 Introduction 691 15.2 The Stream Classes
691
691
12/15/08 7:30:50 PM
viii
Contents
15.3 The Byte Stream and the Character Stream Classes 692 15.4 Console Input 695 15.5 Console Output 701 15.6 Files 703 15.7 Text File Input 705 15.8 Text File Output 711 15.9 Binary Files and Data Streams 716 15.10 Object Serialization 724 15.11 Random Access Files 728 15.12 In Conclusion 737 Exercises 742 The Bigger Picture: Streams and Networks 750
C h a p te r
16
Data Structures and Generics 758 16.1 16.2 16.3 16.4 16.5 16.6 16.7
Introduction 758 The “Old” ArrayList Class 759 Generics and ArrayList 765 A Stack 768 A Queue 781 A Linked List 791 In Conclusion 807 Exercises 810 The Bigger Picture: Abstract Data Types
C h a p te r
C h a p te r
18
Graphics: AWT and Swing
886
18.1 Introduction 886 18.2 Components and Containers 886 18.3 Abstract Windows Toolkit and Swing 889 18.4 Windows and Frames 889 18.5 Layout Managers 896 18.6 Panels 906 18.7 Some Basic Graphics 910 18.8 Displaying an Image 925 18.9 The repaint () Method 927 18.10 In Conclusion 930
C h a p te r
821
827
Introduction 827 The Collection Hierarchy 828 The Set Interface 831 Lists 849 Performance Issues: Choosing the Right Collection 858 17.6 The for-each Loop 863 17.7 In Conclusion 864
sim23356_FM_USE.indd viii
Basic Graphics, GUIs, and EventDriven Programming 885
19
Event-Driven Programming
The Java Collections Framework
Exercises 866 The Bigger Picture: Trees 877
4
Exercises 932 The Bigger Picture: Fractals and Computer Graphics 944
17
17. 1 17.2 17.3 17.4 17.5
Part
954
19.1 19.2 19.3 19.4 19.5 19.6 19.7 19.8 19.9 19.10 19.11 19.12
Introduction 954 The Delegation Event Model 955 Component and JComponent 964 Buttons 965 Labels 970 Text Fields 978 Text Areas 984 Dialog Boxes 992 Mouse Events 998 Checkboxes and Radio Buttons 1014 Menus 1019 Designing Event Listener Classes 1028 19.13 In Conclusion 1029 Exercises 1032 The Bigger Picture: Artificial Intelligence
1045
12/18/08 10:58:12 PM
Contents
C h a p te r
20.1 20.2 20.3 20.4 20.5 20.6 20.7 20.8 20.9
sim23356_FM_USE.indd ix
20.10 In Conclusion 1072 Projects 1072
20
A Case Study: Video Poker, Revisited Introduction 1054 A Quick Review 1054 A Visual Poker Game 1055 Laying Out the Frame 1058 Adding Coins 1060 The First Hand 1061 Hold Those Cards 1064 The New Hand 1064 The Complete Player Class 1066
ix
1054 Appendix A: Appendix B: Appendix C: Appendix D: Appendix E: Index
Java Keywords A-2 The ASCII Character Set A-3 Operator Precedence A-5 Javadoc A-6 Packages A-12
I-1
12/15/08 7:30:51 PM
sim23356_FM_USE.indd x
12/15/08 7:30:51 PM
PREFACE
J
ava Programming: From the Ground Up begins with the fundamentals of programming, moves through the object-oriented paradigm, and concludes with an introduction to graphics and event-driven programming. The broad coverage of topics as well as the modularity of the text makes the book suitable for both introductory and intermediatelevel programming courses. The text requires no prerequisites other than an enthusiasm for problem solving and a willingness to persevere.
KEY FEATURES OF THE TEXT The style of this text is based on the following four principles: 1. Fundamentals first Our approach is neither “objects first” nor “objects late”; it’s “fundamentals first.” Our method is bottom up, starting with the basic concepts common to most programming languages: variables, selection, iteration, and methods. Once students understand the basic control structures, they can use them to build classes. Programming tools such as iteration, selection, and recursion are not the exclusive property of the object-oriented paradigm. Virtually every programming language, from Ada to ZPL, provides these tools. The text discusses these common features first before using them to build classes. Our experience in the classroom convinces us that this bottom-up approach is pedagogically sound and the best way to teach the material. Certainly, one learns how to use the tools of carpentry before building a house. We believe that the same principle applies to building classes. You might say that we present Java from the “grounds” up. 2. Independent presentation of fundamental programming concepts, object-oriented concepts, GUIs, and event-driven paradigms The text is modular. We first tackle basic programming structures, then the fundamentals of object-oriented programming, followed by graphics, GUIs, and events. The separation of graphics from basic programming structures is especially helpful to beginners, who when presented early with programs that mix fundamentals with GUI design, events, and OOP, have difficulty separating these concepts. Because the text is modular, it is appropriate for a variety of courses. For example, a course that teaches Java as a second language can proceed directly to “Part 2: Principles of Object-Oriented Programming.” The basics common to most programming languages (selection, iteration, recursion, methods, arrays) are covered in Part 1 and not spread throughout the text. A student familiar with another language, such as C⫹⫹, can easily find the Java counterpart to any fundamental control structure. 3. Examples, examples, and more examples Examples lead to understanding. Understanding leads to abstraction. Expecting students to immediately digest an abstraction that took a professional perhaps years to distill is unrealistic. Regardless of how clever or articulate the presentation, the practical teacher quickly resorts to examples so that the student can extract the general principles in context. Our text contains dozens of examples in the form of fully implemented programs. Moreover, our experience teaching introductory courses convinces xi
sim23356_FM_USE.indd xi
12/15/08 7:30:51 PM
xii
Preface
us that students rarely read examples spanning four or five pages. With that in mind, we have tried to keep our examples short, succinct, and occasionally entertaining. 4. Independent and parallel presentation of related computer science topics We present a variety of computer science topics that expand upon and enhance the study of a particular part of the Java toolbox. Optional “Bigger Picture” sections appear after the exercises of most chapters and are independent of each other. These optional segments provide an introduction to more advanced topics such as fractals, computer architecture, artificial intelligence, computer theory, bioinformatics, and trees.
PEDAGOGICAL FEATURES Each chapter contains the following features: 1. Objectives—Each chapter begins with a list of concepts that the student will learn in that chapter. 2. Just the Facts—At the conclusion of each chapter, a summary of the fundamental ideas of the chapter can be reviewed at a glance. 3. Bug Extermination—At the end of each chapter is a short section on debugging with a summary of some commonly occurring bugs, and hints for how best to avoid them. 4. Examples—Examples permeate each chapter. Almost every numbered example is a standalone program. Many examples are dissected line by line. Each example follows the same easy-to-understand format: a problem description, a Java solution, typical output, and finally a discussion of the solution. 5. Exercises—Each chapter contains a variety of exercises and programming problems. The style and difficulty of the exercises and problems vary. There are: • crossword puzzles that test terminology, • short answer questions that check basic understanding, • debugging and tracing exercises that do not require a computer, • short programming problems that reinforce the concepts of the chapter, and • longer programming assignments that require some creativity and algorithm development. 6. The Bigger Picture—Following the exercises, a section entitled The Bigger Picture builds upon and extends the ideas covered in the chapter. Topics range from two’s complement number representation, to the halting problem, to DNA sequencing. The material in The Bigger Picture sections is not prerequisite to any subsequent section of the text. Furthermore, one Bigger Picture segment does not depend upon another. Each stands entirely on its own. These sections may be included, assigned as supplemental reading, used in a closed lab setting, or skipped entirely, depending on the audience or time constraints. However, students who choose to tackle some or all of these sections will find a wealth of topics, each opening new roads of inquiry into computer science. The effort will provide students with a larger framework of ideas that extend beyond the study of programming.
THE CONTENTS The text is divided into four parts: 1. The Fundamental Tools; 2. Principles of Object-Oriented Programming; 3. More Java Classes; and 4. Basic Graphics, GUIs, and Event-Driven Programming
sim23356_FM_USE.indd xii
12/15/08 7:30:51 PM
Preface
xiii
Part 1: The Fundamental Tools Part 1 consists of the standard programming constructs that exist in most programming languages: storage and control structures. 1. Introduction to Computers and Java Chapter 1 is a brief introduction to the hardware and software of a computer system. The chapter includes a discussion of programming languages, compilers, and the Java Virtual Machine. 2. Expressions and Data Types Chapter 2 begins with a few applications that display string output and moves gradually to examples that evaluate expressions. The chapter includes an introduction to the primitive data types: int, double, char, and boolean. 3. Variables and Assignment Variables are introduced in this chapter. Specifically, Chapter 3 addresses three questions: • How does an application obtain storage for data? • How does an application store data? • How does an application utilize stored data? Java’s Scanner class is used for interactive input. 4. Selection and Decision: if Statements Chapter 4 covers selection via • the if statement, • the if-else statement, and • the switch statement. The chapter also includes a discussion of nested if statements. 5. Repetition Repetition is first introduced with the while statement, then the do-while statement, and finally the for loop. The chapter explains the stylistic differences among the loops and when each type of loop may be appropriate. There is a discussion of common errors that may lead to infinite loops or loops that are “off by one.” The chapter includes examples of applications with nested loops. 6. Methods Methods are introduced as “black boxes” that accept input and return a value. Here, we present a number of methods from Java’s Math class. The bulk of the chapter deals with “home grown” methods. Because we have not yet introduced classes and objects, all methods are static. 7. Arrays and Lists: One Name for Many Data This chapter covers arrays and array instantiation. Here, we first introduce the concept of a reference. The chapter includes an introduction to sorting and searching. After discussing two-dimensional arrays, the chapter concludes with a case study: The Fifteen Puzzle. The case study uses most of the concepts introduced in Part 1. 8. Recursion Recursion is the final topic of Part 1. The chapter begins with a simple example that does no more than print a message. Subsequent examples grow in complexity, leading to a discussion of tail recursion versus “classic” recursion as well as the Quicksort algorithm. A final case study, The Design of an Anagram Generator, ties the concepts together. The chapter emphasizes recursive thinking.
sim23356_FM_USE.indd xiii
12/15/08 7:30:51 PM
xiv
Preface
Part 2: Principles of Object-Oriented Programming The heart of Part 2 is the object-oriented paradigm. With the tools of Part 1 mastered, students can concentrate on the principles of object-oriented programming. The concepts of Parts 1 and 2 are not in any way tied to building GUIs or event-driven programming. No side trips to loop-land or “by-the-ways” are necessary. Part 2 is comprised of the following chapters: 9. Objects and Classes I: Encapsulation, Strings, and Things Chapter 9 introduces encapsulation, classes, and objects. This first introduction to classes and objects is accomplished with examples of several Java classes, including: • Random • String • StringBuilder • File • DecimalFormat Here, students learn how to use text files for simple I/O. 10. Objects and Classes II: Writing Your Own Classes In Chapter 9, students learn about objects and classes by using a few prepackaged classes. In this chapter students learn how to write their own classes. The chapter discusses encapsulation and information hiding and gives meaning to a few mysterious words, such as public and static, that have been used in previous chapters. A final case study builds a simple audio player, which we dub a myPod. 11. Designing with Classes and Objects The sole topic of Chapter 11 is program design. This chapter consists of a single case study: an interactive poker game. We formulate a methodology for determining the appropriate classes and objects and how these objects interact. Our focus here is not the syntax, semantics, or mechanics of Java but problem solving and object-oriented design. 12. Inheritance We introduce inheritance as the second principle of object-oriented programming. Here, we contrast inheritance and composition. We also discuss the Object class and those Object methods inherited by all classes. The chapter includes a discussion of abstract classes and interfaces. 13. Polymorphism The final chapter of Part 2 is a discussion of polymorphism. If inheritance emphasizes the “sameness” of classes in a hierarchy, then polymorphism underscores the differences. The chapter discusses dynamic binding, using polymorphism with interfaces, and polymorphism as it relates to Object. Part 3: More Java Classes Part 3 is the most technical section of the text. Here, we examine the wrapper classes, exception classes, stream classes, and classes for random access files. We also introduce generics and several elementary data structures such as stacks, queues, and linked lists. Part 3 ends with a discussion of the Java Collections Framework. 14. More Java Classes: Wrappers and Exceptions Chapter 14 begins with a discussion of the wrapper classes. The chapter includes a discussion of auto-boxing and unboxing. The remainder of the chapter is
sim23356_FM_USE.indd xiv
12/15/08 7:30:52 PM
Preface
xv
devoted to Java’s Exception hierarchy. The chapter explains the throw-catch mechanism, the finally block, checked and unchecked exceptions, the throws clause, and how to create an Exception class. 15. Stream I/O and Random Access Files By far the most technical chapter of the text, Chapter 15 is a selective discussion of some of the Byte Stream and Character Stream classes as well as the connection between the Byte Stream hierarchy and the Character Stream hierarchy. The chapter contrasts text and binary files, gives examples of binary file I/O, and discusses object serialization. Random access files are also covered in this chapter. 16. Data Structures and Generics Chapter 16 begins with an introduction to Java’s ArrayList class and generics. This leads to a discussion of several elementary data structures: stacks, queues, and linked lists. An implementation for each type of data structure is discussed. 17. The Java Collections Framework By examining the implementations of several classes in the Java Collections Framework, this chapter demonstrates how choosing the “wrong” class an lead to an inefficient application. Part 4: Basic Graphics, GUIs, and Event-Driven Programming Part 4 introduces graphics, graphical user interfaces, and event-driven programming. 18. Graphics: AWT and Swing Chapter 18 discusses Swing and AWT. The chapter emphasizes frame layout and discusses several layout managers. Here, we explain how to arrange graphical components within a window. We also include an introduction to the Graphics class. 19. Event-Driven Programming Event-driven programming is discussed in terms of the delegation event model. Applications that include buttons, labels, text fields, text areas, dialog boxes, checkboxes, radio buttons, mouse events, and menus fill out the rest of the chapter. 20. A Case Study: Video Poker, Revisited Chapter 20 revisits the case study of Chapter 11. Here the focus is on the design and implementation of a GUI for the text-based poker game developed in Chapter 11. The objective of this chapter is an understanding of the design principle that entails the separation of the data model from the interface, or more simply, the model from the view. Appendix A: Java Keywords Appendix B: The ASCII Character Set Appendix C: Operator Precedence Appendix D: Javadoc This appendix describes how to use Sun’s Javadoc tool to automatically generate documentation from Java source files. Appendix E: Packages Appendix E focuses on the use of packages to better organize large-scale applications with many classes.
sim23356_FM_USE.indd xv
12/15/08 7:30:52 PM
xvi
Preface
TO THE INSTRUCTOR How to Use This Book This book is flexible and is designed to serve several audiences: • For a college-level introduction to programming in Java, Parts 1 and 2 can be used alone or followed by Part 4 with selections from Part 3, depending on the pace and focus of the course. In a first course, we would omit the chapter on Stream classes (Chapter 15). Basic text file I/O is covered in Chapter 9. • A course for students who already know a programming language can begin with Part 2 and refer to Part 1 as needed. This same approach could be used by an instructor who prefers “objects early.” • For high school students in an AP course, Parts 1 and 2 and selections from Part 3 cover the required Java topics. Chapter 15 can be skipped entirely. Recursion appears as Chapter 8 at the conclusion of Part 1, prior to our introduction to object-oriented programming. We present recursion independent of object-oriented programming because recursion is a fundamental concept of program control independent of the programming paradigm. Although recursion appears at the end of Part 1, the topic can be delayed until the end of Part 2, or skipped entirely. Any example or exercise in the book that requires recursion is explicitly marked (R) so that an instructor can choose whether or not to assign it. Arrays are storage structures common to most programming languages. Consequently, we have included the topic of arrays in Part 1. On the other hand, Java arrays are objects. The book is structured so that arrays (Chapter 7) can be covered at the end of Part 1, or delayed until after Chapter 9, Objects and Classes I: Encapsulation, Strings, and Things. Chapter 7 includes a discussion of two-dimensional arrays. These sections can be postponed without loss of continuity. Simple data structures (stacks, queues, and linked lists) and the Java Collections Framework are covered at the end of Part 3 because the implementation of data structures is heavily dependent on the object-oriented paradigm.
Chapter Dependency Chart The following chart gives general chapter prerequisites. The chart can be used to configure many different types of courses. Although Chapters 1 through 6 are shown as prerequisite to Chapter 9, for those instructors eager to start with objects, a course might begin with Chapters 1–3, skip to 9, and cover the material in 4–6 as needed.
Online Resources Online resources to accompany Java Programming are available on the text’s website at www.mhhe.com/bravaco. Some of those resources include: • • • •
Code and data for all program examples in the text Lecture PowerPoint slides An image library of all line art in the text An instructor’s manual containing solutions to exercises
To access these resources, contact your McGraw-Hill representative.
sim23356_FM_USE.indd xvi
12/15/08 7:30:52 PM
Preface
xvii
1. Computers and Java
2. Expressions and Data Types
3. Variables and Assignment
4. Selection
5. Repetition
7.1–7.5 Arrays
6. Methods
7.6–7.10 Arrays
9. Objects and Classes I
8.1–8.4 Recursion
10. Objects and Classes II
8.5–8.6 Recursion
12. Inheritance
16. Data Structures and Generics
17. Java Collections Framework
11. Designing with Classes
13. Polymorphism
14.1–14.2 The Wrapper Classes
14.3 Exceptions
15. Stream IQ
18. Graphics: AWT and Swing
19. Event Driven Programming
20. A Case Study
TO THE STUDENT You are about to study Java, a popular object-oriented programming language. There are many reasons why you may be studying Java: • Knowledge of Java and computer programming is required in your discipline (business, information technology, science, etc.). Programming is a useful tool. Even if you do not become a programmer yourself, this text will provide you with an appreciation for what a programmer does. Long after you have forgotten the details in this book, the principles that you have learned will allow you to communicate better with programmers.
sim23356_FM_USE.indd xvii
12/15/08 7:30:52 PM
xviii
Preface
• You hope to secure an interesting job. Proficiency in Java is a marketable skill. Many interactive websites are written using Java. There is much to learn and Java’s learning curve is steep, but greater proficiency comes with experience. • You are beginning a college major in computer science. Unlike introductory courses in other sciences such as chemistry and physics, a first course in computer science is generally not an overview of the discipline but an intense introduction to programming and the tools of the discipline. While there are breadth-first courses that provide an overview of computer science, these courses are rare, and most computer science programs have retained the tradition of teaching programming first. Java may very well be the first of many programming languages that you will learn. A good first language is one with a rich set of features that enables you to learn other languages quickly. A good first language is one powerful enough to implement sophisticated algorithms without tedious effort. A good language gives you enough power to easily implement an abstract concept. There is no best first language, but there are many good ones such as Scheme, C, C⫹⫹, C#, Visual Basic, Python, and of course, Java. Each language has its fans as well as its detractors. Java, like any programming language, has its strengths and weaknesses as a first language. Strengths: • Internet friendly • Platform independent • Reliable • Secure • Sophisticated GUI and event-driven paradigm • Designed from the ground up as an object-oriented language • Widely used • Has huge collection of object libraries allowing fast, efficient reuse of code Weaknesses: • Huge collection of object libraries is intimidating to beginners. • Steep learning curve, especially for GUI and event-driven models. • Slow execution relative to standard compiled languages. There is no perfect choice, but Java is certainly a good one. Thousands of people consider Java their “native” programming language, and Java will not likely disappear soon from industry or the classroom. Java is an excellent first language. The only way to become fluent in Java is to write programs. You can and should listen to lectures; you can and should read the text. And, unquestionably, you must do the exercises. With practice and perseverance, you can become a skilled and successful programmer and have a bit of fun along the way. Enjoy your journey.
Electronic Textbook Option This text is offered through CourseSmart for both instructors and students. CourseSmart is an online resource where students can purchase the complete text online at almost half the cost of a traditional text. Purchasing the eTextbook allows students to take advantage of CourseSmart’s web tools for learning, which include full text search, notes and
sim23356_FM_USE.indd xviii
12/15/08 7:30:52 PM
Preface
xix
highlighting, and email tools for sharing notes between classmates. To learn more about CourseSmart options, contact your sales representative or visit www.CourseSmart.com.
ACKNOWLEDGMENTS Many people have contributed to the development of this book. We owe a debt of gratitude to our reviewers, who graciously gave of their time and expertise: Suzanne Balik, North Carolina State University Julia I. Couto, Georgia Gwinnet College Jeanne Douglas, University of Vermont William E. Duncan, Louisiana State University H. E. Dunsmore, Purdue University Joseph D. Hurley, Texas A & M University Dennis Kellermeier, Wright State University Lorrie Lehman, University of North Carolina, Charlotte Kathy Liszka, University of Akron Mark Llewellyn, University of Central Florida Hunter Lloyd, Montana State University Blayne E. Mayfield, Oklahoma State University Robert J. McGlinn, Southern Illinois University, Carbondale Rodrigo A. Obando, Columbus State University Kevin O’Gorman, California Polytechnic Institute of Technology Rayno D. Niemi, Rochester Institute of Technology Juan Pavón, Facultad de Informática Cyndi Rader, Colorado School of Mines Michael D. Scott, University of Texas at Austin Harish Sethu, Drexel University Monica Sweat, Georgia Institute of Technology Bahram Zartoshty, California State University, Northridge We also wish to thank the members of the academic administration at Stonehill College for their encouragement and support, especially Provost and Academic Vice President Katie Conboy, Dean Karen Talentino, and Dean Joseph Favazza. Colleagues, friends, and students who helped us along our way include Ryan Amari, Tanya Berger-Wolf, Jennifer Burge, Kathy Conroy, Robert Dugan, Matthew Fuller, Thomas Gariepy, Michael Haney, Andrew Harmon, Matthew Hinds, Antonio “Thumbs” Martinez, Nan Mulford, Elizabeth Patterson, Annemarie Ryan, Bonnie Troupe, and Thomas Wall. Our gratitude goes to our students at Stonehill College and to the participants in our NSF Java workshops. You have contributed to this book in ways great and small. Our editorial, production, and marketing staff helped this book take shape and we thank them all: Alan Apt, Carrie Burger, Kevin Campbell, Bonnie Coakley, Edwin Durbin, Tammy Juran, Melissa Leick, Rebecca Olson, Curt Reynolds, Brenda Rolwes, Michael Ryder, Raghu Srinivasan, and most especially Lora Kalb-Neyens, who patiently guided us throughout the creation of this book. Lastly, we thank our families, Kathryn Kalinak and Emily Bravaco, and Andrea, Zosh, Yair, and Yona Simonson, for their love, their encouragement, and their endless patience without which this book would not have been possible.
sim23356_FM_USE.indd xix
12/15/08 7:30:53 PM
sim23356_FM_USE.indd xx
12/15/08 7:30:53 PM
Java Programming From the Ground Up
sim23356_FM_USE.indd xxi
12/15/08 7:30:53 PM
sim23356_FM_USE.indd xxii
12/15/08 7:30:53 PM
PART
1
The Fundamental Tools 1. An Introduction to Computers and Java 2. Expressions and Data Types 3. Variables and Assignment 4. Selection and Decision: i f Statements 5. Repetition 6. Methods 7. Arrays and Lists: One Name for Many Data 8. Recursion
PART
1
sim23356_ch01.indd 1
12/15/08 6:26:09 PM
CHAPTER
1
An Introduction to Computers and Java “I think there is a world market for maybe five computers.” —Thomas Watson, IBM (1943) “Computers in the future may weigh no more than 1.5 tons.” —Popular Mechanics (1949) “There is no reason anyone would want a computer in their home.” —Ken Olson, Digital Equipment Corp (1977)
Objectives The objectives of Chapter 1 include an understanding of the basic components of a computer system: hardware and software, high-level languages and compilation, Java’s place among programming languages, and the concept of an algorithm.
1.1 INTRODUCTION In 1946, the ENIAC (Electronic Numerical Integrator and Computer), weighing 30 tons and filling a 1000-square-foot room was the world’s first electronic digital computer. Today, computers far more powerful than the ENIAC weigh just a few pounds and can fit inside a briefcase with room to spare. And, contrary to the predictions of yesteryear, computers are everywhere: in homes, offices, schools, bus terminals, bookstores, and even coffee shops and cafes. Is there anyone who hasn’t used a word processor, sent email, or played a computer game? And who has not “googled” for some information? Today, computer usage is as common as driving a car, reading a book, or watching television. So what exactly is a computer? What’s going on inside the “little box” that processes data so quickly? What are “bits and bytes”? What is a computer program? This chapter addresses such questions. We begin with a general overview of a computer system: both the hardware—the physical components of a computer—as well as the software—the programs that manipulate the hardware. We conclude with a discussion of programming languages, and in particular, the programming language Java. Software development using Java is the focus of this book. And, as you will see in subsequent chapters, Java is a very powerful programming language, easy to learn, and undeniably fun. 2
sim23356_ch01.indd 2
12/15/08 6:26:11 PM
Chapter 1
An Introduction to Computers and Java
3
1.2 WHAT IS A COMPUTER? A computer is a machine that performs computations, logical operations, or more generally, data manipulation according to some prescribed sequence of instructions called a computer program. The physical components of a computer are termed hardware and the programs software. Hardware and software work in tandem to perform tasks as varied as word processing, playing chess, finding the fastest route to your destination, or even calculating to three hundred and seventy-eight decimal places. Together the hardware and software comprise a computer system.
1.3 THE HARDWARE Although computer hardware consists of many complex parts, the major hardware components are: • • • •
the central processing unit (CPU), primary or random access memory (RAM), secondary or long-term memory, and input and output devices (I/O devices).
1.3.1 The Central Processing Unit The CPU is the heart, muscle, and brain of the machine. The CPU does the computing, the processing, the bulk of the work. The most important components of the CPU are • the arithmetic and logic unit (ALU), • the control unit (CU), and • the clock. The ALU performs calculations, billions per second, and the CU controls or coordinates which calculations the ALU performs. If the ALU is the heart and muscle of the computer, pumping data throughout the system and tirelessly executing calculations, then the CU is the brain that directs or orchestrates the actions of the ALU according to a prepared script, that is, according to the instructions of a program. The CPU clock, by sending electronic pulses throughout the system, determines how frequently the computer hardware executes instructions. A system’s hardware components are synchronized with the clock. Every time the clock ticks, another hardware action occurs. Of course, the clock speed depends on the amount of time required by the slowest of the CPU’s actions. This is called the critical state of the machine. Moving the clock any faster than the time needed for the critical state would cause the next action to occur too soon, before the data from the previous action would be processed. This would make the computer unpredictable and useless. Speeding up the critical state in the hardware allows a system to utilize a faster clock. This can be accomplished by designing smaller and more efficient circuitry. During the past thirty years, clock speeds have increased from thousands of ticks per second to billions of ticks per second.
sim23356_ch01.indd 3
12/15/08 6:26:12 PM
4
Part 1
The Fundamental Tools
1.3.2 Primary or Random Access Memory How Data Is Stored Computers store data in binary format; that is, every piece of information, including characters, numbers, and even program instructions, is stored as a sequence of 0’s and 1’s or, as these two binary digits are commonly called, bits. For example, a lowercase ‘a’ is represented by 1100001 and a ‘b’ is encoded as 1100010. This particular encoding is used to identify a character’s ASCII code (American Standard Code for Information Interchange). Every character that appears on your keyboard has its own 7-bit ASCII sequence or code. However, each character is typically stored using 8 bits, a leading 0 followed by the character’s 7-bit ASCII code. Thus, character ‘a’ is stored as 0 1100001. A sequence of eight bits is called a byte. A long enough sequence of bytes can be used to store text of any size. Like character data, every decimal number also has a binary representation. The decimal numbers 0 through 15 in binary format are: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 1 10 11 100 101 110 111 1000 1001 1010 1011 1100 1101 1110 1111
Can you determine the binary representation for 16? 17? 18? Binary numbers are not really very different than the ordinary base-10 or decimal numbers that you use every day. As you know, a number such as 1234 can be expressed as 1 thousand 2 hundreds 3 tens 4 ones That is, 1234 1 1000 2 100 3 10 4 1 1 103 2 102 3 101 4 10 0.
sim23356_ch01.indd 4
12/15/08 6:26:12 PM
Chapter 1
An Introduction to Computers and Java
5
The binary number system works similarly except that the only allowable digits are 0 and 1 (rather than 0, 1, 2, 3, 4, 5, 6, 7, 8, and 9) and the base is not 10 but 2. Thus 1101base 2 1 23 1 22 0 21 1 20
18140211 13base 10 In other words, the binary number 1101 is equivalent to the decimal number 13. If you do the arithmetic, you’ll see that 10011010010 is the binary representation of the decimal number 1234. Long sequences of numbers are used to represent audio, video, financial transactions, and many other forms of data. With enough bits, there is no limit to the number of songs, movies, or bank account transactions you can store. Indeed, since every character is encoded with an ASCII value between 0 and 127, text can also be considered a sequence of numbers.
Where Data Is Stored When the CPU executes a program, the program instructions, along with relevant data, are stored in primary memory. Primary memory is also known as random access memory (RAM) because data may be retrieved or accessed in random, rather than sequential, order. You can conceptualize RAM as a collection of storage cells or boxes, each capable of holding just a single byte of information. A unique number, or memory address, identifies each such storage cell. Figure 1.1 depicts a small portion of memory with addresses 1000, 1001, 1002, 1003, etc. Of course, in practice, these addresses are expressed as binary and not decimal numbers.
Memory addresses
1000
01000011
1001
01000001
A
1002
01010100
T
1003
01010011
S
C Binary representation of the word CATS
1004
1005
FIGURE 1.1 Primary memory Primary memory is volatile. This means that shutting down your computer causes all data in primary memory to be erased. For example, when you work with a word processor, both the word processing program and your document are loaded into primary memory. If your computer shuts down
sim23356_ch01.indd 5
12/15/08 6:26:13 PM
6
Part 1
The Fundamental Tools
before you have had a chance to save your work, your document may be lost forever. Longterm storage is achieved with secondary memory. When you save a document, it is saved in secondary memory.
1.3.3 Secondary Memory Secondary memory is used for long-term or even permanent storage. Secondary memory devices include hard disks, tapes, CDs, DVDs, and flash memory sticks. The programs that you use every day such as word processors, spreadsheets, and games are permanently stored on secondary storage devices. Compared to RAM, secondary memory is, in general, cheaper (per bit), slower, larger, electromechanical rather than electronic, and persistent: secondary memory devices do not lose their values when you turn off the computer. Before executing a program, the CPU first copies the program instructions along with any necessary data from secondary memory to RAM. To execute the program, the instructions are fetched and executed one by one from RAM. Each instruction may be executed many thousands of times. Fetching data and instructions that are stored in electronic RAM is much faster than retrieving information from a mechanical device such as a hard disk.
1.3.4 Input/Output Devices A computer communicates with a human user through input and output devices. Standard input devices are keyboards, mouses, joysticks, stylus pens, cameras, and microphones for audio input. Typical output devices include monitors, printers, and speakers.
1.4 THE SOFTWARE The programs that run on a computer are collectively known as software. Word processors, Internet browsers, editors, database management systems, computer games, and spreadsheets are all part of your computer’s software library. When you turn on or boot your computer, a program called the operating system automatically runs. This special program provides an interface between you and your computer. The operating system is the “concierge” of your computer. It manages the computer’s resources and activities. If you wish to use your word processor or perhaps play solitaire, you inform the operating system, and the operating system carries out your request. If you’d like to erase or rename a file, you tell the operating system. Indeed, the operating system affects all the programs that run on a computer. Today, the most popular operating systems are Windows (various dialects), GNU-Linux, Unix variants, and MAC OS X. You can buy many different types of software, but of course, you can create your own software, too. And doing so is precisely the topic of this book.
sim23356_ch01.indd 6
12/15/08 6:26:14 PM
Chapter 1
An Introduction to Computers and Java
7
1.4.1 In the Beginning There Was Machine Language... Each computer, or more specifically each CPU, executes instructions encoded in its own unique native machine language. Moreover, each machine language instruction consists of a sequence of bits. For example, a hypothetical instruction for adding one number to another might have the form 10010010
00000001
00000001
10101101
Certainly, programming in machine language is both tedious and time-consuming. Machine languages tend to have instructions that operate at a level of detail too low to allow a programmer to keep perspective and maintain productivity. Furthermore, because each individual CPU understands only its own native machine language, proficiency in one machine language does not translate into proficiency in the language of another machine. Imagine trying to master a new binary-based language for each new CPU on the market! In the early days of computers, machine language was the only option for programmers. However, in the 1960s, the first high-level language, FORTRAN, was invented, and no longer were programmers forced to devise programs with binary instructions. FORTRAN instructions use an English-like syntax. Today, hundreds of high-level languages are available, with dozens in mainstream use, including Fortran 2003, COBOL, Lisp, Visual BASIC, C, C, C#, Java, Perl, Python, PHP, and Javascript. A typical instruction coded in a high-level language, such as BASIC, might be if income 1000000 then print “You are rich!”
This is certainly more comprehensible than a sequence of bits, and easier to program. Still, if each computer speaks but one language, its native machine language, how does a computer understand a Fortran 2003, BASIC, or C program? Before a program that is written in a high-level language can be executed on a particular computer, the program must be translated into the machine language of that computer. Translation is the job of a program called a compiler. You can think of the compiler as a black box that accepts a program written in a highlevel language such as C, the source program, and produces a translation into the target machine language. See Figure 1.2. C⫹⫹ program (source)
C⫹⫹ compiler
Machine language program (target)
FIGURE 1.2 A compiler translates a C program into a machine language. Once a compiler translates the source program into machine language, the machine’s CPU can execute the resulting target program. A programmer can conveniently write just one program and translate it into several different machine languages. You need one compiler to translate your C program into a machine language for an Intel processor Windows machine, and another to translate it for a Mac that uses a PowerPC processor, but you write only one C program.
sim23356_ch01.indd 7
12/15/08 6:26:14 PM
8
Part 1
The Fundamental Tools
1.4.2 Then, Along Came Java Java is a general-purpose language developed by Sun Microsystems in the early 1990s. Java was originally designed to program smart consumer electronic devices. Java’s creators identified three main goals for their new language: • Platform independence—Java programs should be capable of running on any computer. • Security—Java programs should not be susceptible to hackers’ code and dangerous viruses. • Reliability—Java programs should not “crash.” Although Java was intended for use with consumer electronic devices, such devices did not become its destiny. Serendipitously, the Web provided Java with the perfect environment for the goals of platform independence, security, and reliability. Since its invention, Java has evolved into arguably the most important programming language for developing e-commerce and other Web-driven applications. Its application base is growing daily and includes dynamic Web-content generation with servlet technology, the building of business components with Enterprise JavaBeans, the creation of cross-platform user interfaces with Swing, and much more.
The Java Virtual Machine In order to make Java a cross-platform programming language, Java’s creative team designed an abstract computer implemented in software called the Java Virtual Machine (JVM). You cannot go to a store and buy a JVM computer. Instead you install software on your computer that simulates a JVM computer. The JVM is not a piece of hardware, but it pretends to be one. The machine language of the JVM is called bytecode. Java programs are first compiled into bytecode, and then executed. Typically, the Java interpreter, which is part of the JVM, executes each bytecode instruction, one by one. However, to speed up execution, some versions of the JVM are equipped with a “just in time compiler” that compiles some bytecode directly to native machine code at runtime, that is, during execution. But regardless of how the JVM deals with the bytecode, the important point is that every Java program compiles into bytecode, the native language of the Java Virtual Machine. See Figure 1.3. Java program
Java compiler
Bytecode
JVM
FIGURE 1.3 The JVM is a simulated computer that executes bytecode. Bytecode provides an extra layer of abstraction between source code and execution. Once a Java program is translated into bytecode, the bytecode can run on any computer that has installed the JVM. A Java program needs to be compiled into bytecode just once. Proponents of Java often use the slogan “compile once, run anywhere.” The JVM allows every computer to act as though it were built to execute native bytecode. Therefore, once you compile a program into bytecode, it can be run on any machine with the JVM installed. The program never needs to be recompiled in order to run on a different machine. Behind the scenes, the JVM and bytecode are run in the native machine language of the target machine, but that is invisible to the programmer. Essentially, separate compilation for each machine is replaced by the flexibility of the JVM. Of course, this all works provided that the same version of the JVM is installed in each computer on which one intends to run the program.
sim23356_ch01.indd 8
12/15/08 6:26:14 PM
Chapter 1
An Introduction to Computers and Java
9
How to Compile Java Programs There are many different “integrated development environments” (IDEs), each complete with a slick graphical interface that facilitates the development of Java programs. Most of these IDEs provide: • • • •
a text editor for writing programs, file browsing, a “debugger” that assists in finding program errors, and push-button compilation and execution.
Many of these systems such as Eclipse, JDEE, BlueJ, JGrasp, and Dr. Java are free. Because each IDE is very different, we restrict our discussion to Sun’s bare bones compiler. You do not need an IDE to write and run Java programs. If you prefer, you can write a program using any text editor, such as Notepad or Emacs, and compile your program with the Java Development Kit (JDK), which you can download free from Sun. Installation instructions are available on Sun’s website. The installation process places the Java compiler, javac.exe, in a newly created directory, unless you specify otherwise. In a Windows environment, the location of javac.exe is most likely C:\Program Files\Java\jdk1.6.0_01\bin
(The version of the development kit (1.6.0_01) will probably be different, however.) If you do not know the location of the Java compiler, search for javac.exe. Figure 1.4 shows the Windows directory C:\Program Files\Java\jdk1.6.0_01\bin, which includes the Java compiler, as well as a number of other programs that support Java.
FIGURE 1.4 C:\Program Files\Java\jdk1.6.0_01\bin contains the compiler, javac.exe. You can invoke the Java compiler from the command prompt with the directive C:\Program Files\Java\jdk1.6.0_01\bin\ javac
Of course, using a fully qualified name becomes tiresome very quickly. To invoke the Java compiler from any directory with the one-word command javac, you must add the location of the Java compiler to the PATH variable of your machine. The PATH variable tells your system where to find the Java compiler. How you set the PATH variable depends on your
sim23356_ch01.indd 9
12/15/08 6:26:15 PM
10
Part 1
The Fundamental Tools
system, and directions are readily available on the Web. If you do not set the PATH variable, you can still invoke the Java compiler with its fully qualified name. But surely, the one-word command javac is more appealing. Once the Java Development Kit is installed, and the PATH variable set, you are ready to write and compile programs. At least in the beginning, it is a good idea to keep all of your Java programs in a folder named JavaPrograms, MyPrograms, JavaStuff, or some variation of that. To create a program: • Open a text editor, such as Notepad or Emacs. • Type your program. • Save the program in a file with a .java extension such as Hello.java or myProgram.java. (We discuss restrictions to the program name in Chapter 2.) • Exit or minimize the text editor. To compile the program: • Open a command window. If you are running Windows: • click Start; • click Run; • in the text box that appears, type cmd; • click OK. • Navigate to the directory where you have saved your program. • Type the command javac programName.java, e.g., javac Hello.java or javac MyProgram.java.
If your program contains errors, the compiler graciously generates “error messages” indicating where the errors exist. In this case, you must reopen the program in the editor, fix the errors, save the program, and compile the program again. If the program has no errors, the compiler creates a class file using the same name as your program but with a .class extension, for example, Hello.class. This file contains the bytecode that runs on the Java Virtual Machine. To run the program (execute the class file), type the command java programName,
where programName is the name of your program, for example, java Hello. Notice that you do not include the .class extension. The java command executes the bytecode on the Java Virtual Machine. A text editor along with the javac and java commands are all you need to compile and run Java programs. Nonetheless, most people rely on the convenience of an IDE. And most IDEs use Sun’s compiler under the hood, so whether you click a button or type a command, you are most likely using the same compiler and building the same class file. This book teaches you how to write and design Java programs. You are on your own to choose one of the myriad variety of systems that make compiling and debugging more convenient. Some IDEs are simple and some have a steep learning curve. There are many. The choice is yours.
1.5 PROGRAMMING AND ALGORITHMS Mastery of a programming language such as Java is certainly a noble achievement that is part of a bigger picture that includes problem solving and the study of algorithms.
sim23356_ch01.indd 10
12/15/08 6:26:15 PM
Chapter 1
An Introduction to Computers and Java
11
An algorithm is a finite, step-by-step procedure for accomplishing some task or solving a problem. Algorithms are everywhere. Every time you query Google, a Web-mining algorithm runs; every time you use Mapquest for directions, a shortest-path algorithm runs; and every time you use a spell-checker, a string-searching algorithm runs. Creating correct and efficient algorithms is an art and a science, which takes both practice and creativity. Whether you need to calculate the average of five numbers, sort a list of two million names, or guide a rocket, an algorithm lurks in the background; the solution to your problem is an algorithm. The study of algorithms is a cornerstone of computer science. A programming language is your tool, a tool that you can use to investigate and implement algorithms. With a programming language, such as Java, you can turn algorithms into programs so that a computer finds the average, sorts the list, or guides the rocket. Programs implement algorithms; programming makes algorithms come to life. As you work through the problems and exercises in this text, you will hone your problem-solving skills, design and implement your own algorithms, and, along the way, discover that programming with Java is fun.
1.6 IN CONCLUSION In this chapter, you have seen the basic structure of a computer system: the hardware and the software. Just as the ENIAC has evolved into the powerful, easy-to-use personal computer of today, software has progressed from primitive machine language instructions to sophisticated, high-level programming languages such as Java. Hardware and software do not exist in isolation. A computer without software can do nothing. The remainder of this book deals with software development using Java. And, although we begin with the simplest of programs, by the end of the book you will be able to write applications that computer pioneers never dreamed of implementing.
Just the Facts • A computer is a machine that performs computations, logical operations, and data manipulation according to some prescribed sequence of instructions called a computer program. • The physical components of a computer are called hardware. • The programs that run on a computer are called software. • The central processing unit (CPU ) is that part of the computer that performs most calculations and makes decisions. • The arithmetic and logic unit (ALU ) is the part of the CPU that performs arithmetical calculations. • The control unit (CU ) coordinates the calculations of the ALU and the movement of data between the CPU and RAM. • The clock determines how frequently the computer hardware executes instructions. • A computer stores data in binary format, i.e., as a sequence of 0’s and 1’s. • A single 0 or 1 is called a bit; a sequence of eight bits is called a byte.
sim23356_ch01.indd 11
12/15/08 6:26:16 PM
12
Part 1
The Fundamental Tools
• Primary or random access memory (RAM ) is composed of a collection of storage cells, each capable of holding one byte of information. Each cell has a unique numerical address. • RAM is volatile; when the computer is turned off, all data in RAM is erased. • Secondary memory is used for long-term or permanent storage. Retrieving data from secondary memory is slower than retrieving data from RAM. • The operating system is a program that manages all the resources of a computer. All requests such as running a program, deleting a file, and printing a document are made through the operating system. • Each CPU understands just a single language, its unique native machine language. Machine language programs are written in binary format. • A program written in a high-level language, such as C or BASIC, cannot run on a computer until the program is translated into that computer’s machine language. A program that does this translation is called a compiler. • The Java Virtual Machine (JVM ) is a simulated computer that is implemented in software. The machine language of the JVM is called bytecode. Once the Java compiler translates a program into bytecode, the bytecode can run on any computer that has installed the JVM. • At minimum, to write, compile, and run a Java program you need a text editor, the JVM, a terminal window, and a command line. However, there are also many fullfeatured IDEs (integrated development environments) that facilitate the writing, compiling, execution, and debugging of Java programs. • Downloading the newest version of JDK (Java Development Kit) from Sun is the way to get the complete functionality of the JVM. A subset of JDK called JRE (Java Runtime Environment) allows you to execute bytecode but not to compile your own programs. • An algorithm is a step-by-step procedure for solving a problem. A computer program implements an algorithm so that a computer can accomplish the procedure.
sim23356_ch01.indd 12
12/15/08 6:26:16 PM
Chapter 1
An Introduction to Computers and Java
13
EXERCISES LEARN THE LINGO Test your knowledge of the chapter’s vocabulary by completing the following crossword puzzle. 1
6
2
3
4
7
8 12
11
13
5
9
10
14 15
17
16 18
19
20
21
22 24
23
26
27
29
Across 2 1111 in decimal (word) 4 101 in decimal (word) 7 Memory cells are identified by a unique . 9 One of the first computers 11 Invokes the Java compiler 15 Performs arithmetical calculations 16 Abstract computer implemented in software 17 Step-by-step procedure for solving a problem 20 Primary memory is electronic, secondary memory is . 23 Long-term memory 27 Interface between the user and the computer 29 Computer programs 30 Primary memory is (two words) memory.
sim23356_ch01.indd 13
25
28
30
Down 1 RAM is : when the computer is turned off, all memory is erased. 3 First high-level language 5 A sophisticated system for writing and compiling programs 6 Physical components of a computer 8 The “brain” of a computer 10 Translates a program into native code 12 Output device 13 A binary digit 14 Primary memory 18 Each computer speaks a unique language. 19 Computers store data in format. 21 Determines how fast hardware executes instructions 22 Java programs are compiled into . 24 Eight bits 25 Secondary memory device 26 The Java compiler creates a file with a . extension. 28 Input device
12/15/08 6:26:16 PM
14
Part 1
The Fundamental Tools
SHORT EXERCISES 1. True or False If false, give an explanation. a. Retrieving data from RAM usually takes more time than retrieving data from a hard drive. b. The ALU performs arithmetical calculations. c. Primary memory (RAM) is addressable in units of one bit. d. The clock speed of a computer has nothing to do with how fast programs execute. e. The CU determines the next instruction that executes. f. An operating system is a fundamental part of the hardware of a computer. g. Executing the same C program on two machines with different CPUs requires two compilers. h. Bytecode is the native language of most Windows machines. i. Java is compiled directly to a machine’s native language, and then translated line by line to bytecode. j. Any computer you purchase can execute Java bytecode without any special downloading of software. 2. Binary to Decimal Convert each of the following binary numbers to its decimal equivalent. a. 10101 b. 00101 c. 100100101 3. Decimal to Binary Determine the binary representation of a. 128 b. 235 c. 66 4. Adding and Multiplying in Binary When does 1 1 10? When you are adding binary numbers. Addition of binary numbers is much the same as with decimal numbers. For example, decimal numbers 23 and 15 in binary format are 10111 and 01111, and their sum is calculated as 10111 +01111 100110
As you see, sums are simple as long as you remember to carry a 1 whenever you add 1 1. Multiplication is just as simple: 10111 01111 10111 10111 10111 10111 00000 101011001
Find the following binary sums and products: a. 11111 + 00001 b. 101010101 + 010101011
sim23356_ch01.indd 14
12/15/08 6:26:17 PM
Chapter 1
c. d. e. f.
An Introduction to Computers and Java
15
111100011101 + 01001011111 (111) × (101) (1010) × (0101) (11111) × (11111)
5. Octal and Hexadecimal Numbers Octal numbers use 8 as a base and digits 0, 1, 2, 3, 4, 5, 6, and 7. Hexadecimal numbers use 16 as a base and digits 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, and F. Conversions between binary and octal numbers can be done easily three bits at a time. Conversions between binary and hexadecimal numbers can be accomplished quickly four bits at a time. There is no need to make any interim conversions to decimal numbers. For example, 76 hexadecimal equals the binary number 0111 0110, because 7 is 0111 and 6 is 0110. There is no need to first convert 76 hexadecimal to its decimal equivalent 118 and then back to binary. Calculate the following: a. the decimal equivalent of the octal number 3427 b. the octal equivalent of the binary number 100100101 c. the hexadecimal equivalent of the binary number 00011010111101011001 d. the binary equivalent of the hexadecimal number A03 6. ASCII Encoding The ASCII code for uppercase ‘A’ is 01000001 (decimal 65); the code for ‘B’ is 01000010 (decimal 66); for ‘C’ it is 01000011 (decimal 67), etc. Decode the following sequence of nine bytes. 010010100100000101010110010000010100100101010011010001100101010101001110
7. Encoding Opcodes One part of a machine language instruction is the opcode (Operation Code). A typical opcode might signify the “Add” operation, another “Subtract,” and another “Exit.” If there are typically 120 different opcodes and each opcode is represented by a string of bits, how many bits are required to uniquely encode or represent each opcode? 8. Java Translation Choose your favorite IDE, and investigate how it executes bytecode on your computer. For example, does it execute the bytecode directly, or does it translate bytecode into machine code using a JIT compiler? 9. Compilers What distinguishes a high-level programming language from machine language? 10. Assembly Language Assembly language is a low-level language like machine language. Do a little research and describe the format and purpose of assembly language. How does assembly language differ from machine language? 11. Compile Once, Run Anywhere Does the Java slogan “compile once, run anywhere” come with any “fine print?” Explain exactly what this phrase means. 12. Bytecode Programs written in a language such as C are compiled directly into the machine language of a particular computer. Java programs are first compiled into bytecode and then interpreted by the JVM. What are the disadvantages and advantages of using Java versus C with respect to compilation and execution times?
sim23356_ch01.indd 15
12/15/08 6:26:17 PM
16
Part 1
The Fundamental Tools
THE BIGGER PICTURE 1. MACHINE LANGUAGE AND COMPUTER ARCHITECTURE The following equation is commonly used for expressing a computer’s performance ability: cycles time instructions time _______ _____ _________ __________ program cycle instruction program This equation means that the time necessary to run a program equals the time it takes for the CPU clock to tick once (time/cycle), times the number of different hardware steps required to perform an instruction (cycles/instruction), times the number of instructions in the program (instructions/program). Each of these values depends on the machine language and the computer’s CPU design (or architecture). Two major competing paradigms in CPU design are reduced instruction set computer (RISC) and complex instruction set computer (CISC)1. The CISC approach creates a machine language with complex instructions. For example, a single instruction might be sufficient to add the contents of two memory locations and store the result in a third. The same action in a RISC language might take four separate instructions: two to move the data from memory (RAM) to the CPU, one to add them in the ALU, and one to move the answer back to RAM. However, the single CISC instruction might take 21 clock cycles, while each of the four RISC instructions use just five clock cycles, for a total of only 20 cycles. In general, CISC machines tend to minimize the number of instructions per program, sacrificing the number of cycles per instruction, while RISC machines do the opposite, reducing the cycles per instruction at the cost of the number of instructions per program. The clock in RISC machines tends to be faster than the clock in CISC machines because the RISC hardware is simpler.
THE BIGGER PICTURE
Exercises 1. A program that compiles into 2,000,000 machine language instructions on a CISC computer requires 7,000,000 instructions on a RISC computer. The clock on the RISC computer ticks 3,000,000,000 times each second, and the clock on the CISC machine ticks 2,400,000,000 each second. The average cycles/instruction on the CISC computer is 12.5, and the average cycles/instruction on the RISC machine is 4.8. How much time does it take to run the program on each machine? Which machine runs your program faster? 2. A CPU architect is able to increase the clock speed on the RISC machine to 3,300,000,000 cycles per second, while keeping the average cycles/instruction at 4.8, but at the cost of increasing the number of instructions to 7,100,000. How much time does it take to run the program on each machine? Which machine runs your program faster?
2. ALGORITHMS An algorithm is a step-by-step procedure for solving a problem. The following algorithm describes a procedure that converts a decimal number to a binary number. The binary number is computed from right to left. That is, the rightmost bit is written down first. Let x be a positive decimal number. Repeat the following steps until x has the value zero: 1. If x is even, then write down 0, otherwise write down 1. 2. Change the value of x to x/2, dropping the remainder, if necessary.
sim23356_ch01.indd 16
12/15/08 6:26:17 PM
Chapter 1
An Introduction to Computers and Java
17
Let’s look at this algorithm in action when x 17. x 17 17 is odd, so write 1. Divide 17 by 2 and drop the remainder; x is now 8. 8 is even, so write 0. Divide 8 by 2; x is now 4. 4 is even, so write 0. Divide 4 by 2; x is now 2. 2 is even, so write 0. Divide 2 by 2; x is now 1. 1 is odd, so write 1. Divide 1 by 2, drop the remainder; x is now 0. Because x is 0, stop. The final binary number is: 10001. Discovering and testing new algorithms is an important part of computer science, but it is a separate skill from learning how to implement an algorithm in Java. In upcoming chapters, you will learn how to turn a simple algorithm like this into a Java program. You may not have been able to discover this algorithm yourself, and even now that you have seen the algorithm, it may not be obvious why it works. Nonetheless, you can still explore some simpler algorithms such as those described in the following two exercises.
Exercises 1. Write an algorithm to convert a binary number into a decimal number. 2. The ASCII values for the digits 0–9 are 48–57, respectively. Write an algorithm that, given a positive integer x, constructs a sequence of values in the range 48–57, representing the ASCII values of the digits of x. For example, if x 104, the resulting sequence is 49 48 52, since the ASCII values for 1, 0, and 4 are 49, 48, and 52, respectively.
3. STORING INTEGERS
Base 10 Numbers In olden days everyone knows, Folks would count on their fingers and toes. They’d get up to twenty, Then, twenty was plenty. “Now, heaven knows, anything goes.”
THE BIGGER PICTURE
This section describes how Java represents and stores negative numbers using bits. After reading this section, you may wonder whether any of this material is really essential to a Java programmer. A beginner can certainly get by without much behind-the-scenes knowledge, but as you gain experience as a programmer, you will find that a deeper understanding of how Java works is crucial. For example, a program that correctly encodes credit card numbers requires a thorough understanding of arithmetic overflow and number representations. This section introduces the basics.
Mathematical folklore postulates that the base-10 number system which came about during the Renaissance found favor because humans possess just ten fingers for counting. Fact or fiction, we use exactly ten digits (0–9) to signify any decimal or base-10 number.
sim23356_ch01.indd 17
12/15/08 6:26:18 PM
18
Part 1
The Fundamental Tools
The first ten non-negative integers require just one digit: 0, 1, 2, 3, 4, 5, 6, 7, 8, or 9. Next, we add a tens column, put a 1 in it, and get the integer 10. You are probably so familiar with decimal numbers that you rarely notice the 10s, 100s, and 1000s columns. You know implicitly that the number 6123 consists of 6 thousands plus 1 hundred plus 2 tens plus 3 ones: 6123 (6 1000) (1 100) (2 10) (3 1) (6 103) (1 102) (2 101) (3 100)
Unsigned Numbers As you have read in this chapter, a computer stores integers as binary numbers. Unlike a base-10 system that requires ten symbols (0–9), a binary system needs just two: 0 and 1. In contrast to the columns of a decimal system, the column values of a binary system (right to left) have place values that are powers of 2: 1, 2, 4, 8, 16, 32, 64, 128, and so on. Thus the binary number 1111011, which is 123 in the decimal system, consists of: 1 sixty-four plus 1 thirty-two plus 1 sixteen plus 1 eight plus 0 fours plus 1 two plus 1 one.
Exercises 1. 2. 3. 4. 5.
Write 37 in binary. Write 137 in binary. What is the value of 100110 in decimal? What is the value of 100111 in decimal? What happens to the value of a binary number when you append a zero to the right end? 6. What happens to the value of a binary number when you append a one to the right end? Using a single bit you can form just two binary numbers, 0 and 1 with two bits, there are four binary numbers, 00, 01, 10, and 11, and with three bits there are eight, 000, 001, 010, 011, 100, 101, 110, and 111. With every additional column, the number of binary integers doubles. For example, the four two-bit numbers are:
THE BIGGER PICTURE
00 01 10 11
sim23356_ch01.indd 18
To construct all three-bit binary numbers, prefix each two-bit number with a 0 and also with a 1, in effect doubling the number of possible binary numbers and giving eight bit patterns: 000 001 010 011
100 101 110 111
To construct all four-bit numbers, add 0 to the left of every three-bit number, and do likewise with 1, yielding 16 binary numbers with four bits: 0000 0001 0010 0011
0100 0101 0110 0111
1000 1001 1010 1011
1100 1101 1110 1111
12/15/08 6:26:19 PM
Chapter 1
An Introduction to Computers and Java
19
These last numbers represent the positive values 0 through 15 (24 1). In general, n bits can store positive numbers in the range 0 through 2n 1 inclusive. Such binary numbers, because they have positive values, are called unsigned numbers.
Exercises 7. The smallest unit of “addressable memory” in a computer is a collection of 8 bits, called a byte. How many different binary numbers are possible using 8 bits? 8. What is the largest unsigned number you can represent with 8 bits? 9. What is the range of values for a 7-bit ASCII code? 10. How many binary numbers can you create using 16 bits (two bytes)? 11. What is the largest unsigned number (in decimal) that you can make with 16 bits? 12. The largest unit of addressable memory in a computer is 32 bits (four bytes). How many binary numbers are possible using four bytes?
Negative Numbers and Two’s Complement You have probably noticed that we have not discussed negative numbers. How then are negative numbers expressed in a binary number system? Java uses a system of representation called two’s complement. In a two’s complement scheme, half the bit patterns of an integer represent positive numbers; the other half signify negative numbers. If a number begins with zero, the number is positive, and if a number starts with one, then it is negative. The leftmost bit is called the sign bit. For example, the byte 00010011, as you would expect, is equivalent to the decimal number 19 (16 2 1 19). The sign bit is 0, so the number is positive. However, the number 10010011, with a leading 1, is not equivalent to 19. It actually corresponds to 109. How does this work? To simplify the discussion, we consider three-bit numbers. As you know there are 8 such binary numbers. Figure 1.5 shows both the unsigned decimal (no sign bit) value and the two’s complement decimal value of each bit pattern. That is, a pattern of bits is interpreted two different ways.
Decimal Value Two’s complement representation Left bit is sign bit
000
0
0
001
1
1
010
2
2
011
3
3
100
4
4
101
5
3
110
6
2
111
7
1
FIGURE 1.5 Three-bit number representations: unsigned and two’s complement We focus on the negative numbers. Notice that binary number 101 is both the two’s complement representation of –3 and also the unsigned binary representation of 5. In general, the two’s complement version of the 3-bit negative number x is the same as the unsigned binary representation of 8 x. So the bit pattern for 1, in the two’s complement
sim23356_ch01.indd 19
THE BIGGER PICTURE
Bit pattern
Decimal Value Unsigned representation No sign bit
12/15/08 6:26:19 PM
20
Part 1
The Fundamental Tools
world, is the same as the unsigned bit pattern for 8 1 7, and that’s 111; the two’s complement representation for 2 is the unsigned pattern for 8 2 6, which is 110. Let’s generalize to bytes. A byte consists of 8 bits, and there is a total of 28 256 different bit patterns. Therefore, byte-sized two’s complement binary numbers can represent 128 non-negative numbers (0 to 127) and 128 negative numbers (128 to 1). The negative number x has the same bit pattern as the unsigned representation of 256 x. Thus, a two’s complement system stores 109 as 10010011 because 256 109 147, which as an unsigned binary number is 10010011. We have discussed two’s complement as a method for signifying negative numbers. That is so. It is also an operation that you can perform on a binary number. Indeed, performing two’s complement on a binary number is the operation of negation. The two’s complement of any unsigned n-bit number x is 2n x. For example, to compute the two’s complement of 011 (3 decimal): compute 8 3 5 or 101, which we saw is also, the two’s complement representation of –3. Symmetrically, the two’s complement of 101 is 8 5, and that is 011. Thus, the two’s complement operation on 011 (3 decimal) gives 101 (3) and the two’s complement of 101 (3) yields 011 (3). Computing a number’s two’s complement is akin to multiplication by 1, i.e., the two’s complement operation is negation. Figure 1.6 shows the results of the two’s complement operation of each three-bit number. Bit pattern
Result of the two’s complement operation
000
000
001
111
010
110
011
101
100
100
101
011
110
010
111
001
THE BIGGER PICTURE
FIGURE 1.6 Two’s complement operation There is a simpler method for calculating the two’s complement of an n-bit number. Just toggle all the bits (change 0’s to 1’s and 1’s to 0’s) and add 1. For example, the two’s complement of 101 is 010 + 1 = 011, and the two’s complement of 011 is 100 + 1 = 101. And, the two’s complement of 10101010 is 01010101 + 1 = 01010111. You can understand this trick by once again considering the case of 3-bit numbers. First notice that toggling the bits of x is the same as subtracting x from 7 (111). For example, 111 -101 010
and
111 -011 100
Subtracting from 7 and then adding 1 is no different than subtracting from 8, which is what we have been doing all along in the previous examples.
sim23356_ch01.indd 20
12/15/08 6:26:20 PM
Chapter 1
An Introduction to Computers and Java
21
Java uses two’s complement representation for all integers. Other languages such as C allow you to specify whether or not an integer is two’s complement or unsigned. An unsigned byte value ranges from 0 through 256. The unsigned byte 10010011 is equivalent to decimal 147, but as you know, 10010011 is the two’s complement representation of 109. The byte has different values depending on whether the language considers it unsigned or two’s complement. There are applications such as cryptography where unsigned integers are necessary, and this lack of flexibility in Java forces some awkward code to simulate unsigned integers.
Exercises 13. Using two’s complement representation, what is the decimal value of the byte 11101110? 14. Assume that a system stores all integers as bytes using two’s complement representation. What is the value of 1 127? 15. Using two’s complement representation, what is the decimal value of the 16-bit integer 1111110111111101? 16. Using two’s complement, what range of integers can be represented with 16 bits? 32 bits? 64 bits? 17. What is the two’s complement of the two’s complement of x? 18. What are the decimal values of the following 32-bit, two’s complement integers: 11111111111111111111111101011100 and 00000000000000000000000010001111?
Why Two’s Complement?
Carry →
1 1 1101 +1101 11010
Here is how to do binary subtraction using addition. We use one byte for each number. You can verify that the binary form of 108 is 01101100 and that 00000011 signifies 3. We calculate 01101100 - 00000011, i.e., 108 3.
sim23356_ch01.indd 21
THE BIGGER PICTURE
There are other ways to represent negative integers besides two’s complement. A much simpler method uses the leftmost bit to signify the sign of the number and the remaining bits to indicate the magnitude of the number. This method is called sign-magnitude. For positive numbers, sign-magnitude representation is the same as two’s complement, but for negative numbers it’s different. For example, 10010011 19 in sign-magnitude and 109 in two’s complement. Why choose one method over the other? Although there are circumstances where sign-magnitude representation is preferable (multiplication circuitry), it is safe to say that the standard representation of negative integers in a computer is two’s complement. And two’s complement is the representation that Java uses. There is a very important reason why Java uses two’s complement representation for negative integers. A carry-lookahead adder is a circuit that that performs addition in a computer. Surprisingly, this same circuit does subtraction! Using two’s complement representation allows the adder to do both addition and subtraction. There is no need to design a separate circuit to perform subtraction. Addition of binary numbers is no different than addition of decimal numbers except that a carry occurs with a sum of 2 or more rather than a sum of 10 or more. Just remember 1 + 1 = 10. For example, adding 1101 + 1101 is performed as
12/15/08 6:26:20 PM
22
Part 1
The Fundamental Tools
The calculation is simple: negate 0000001 and add. As you know, the two’s complement operation is really negation. So, the two’s complement of 00000011 is 11111100 + 1 = 11111101. Thus 01101100 - 00000011 is: 01101100 +11111101 1 01101001
If you ignore the leftmost bit, the remaining bits give the correct answer 01101001, which is equivalent to 105. Ignoring the leftmost 1 is automatic in a computer because if there is no room to store the leftmost bit, it just disappears. Similarly, to subtract 00000111 - 00000011 (7 3): a. Compute the two’s complement of 00000011: 11111100 + 1 = 11111101. b. Add: 00000111 + 11111101 = 1 00000100. (Notice that there are nine bits.) c. Drop the leftmost bit, giving 00000100, which is equivalent to 4. In the following exercises, we ask you to investigate this method of subtraction.
Exercises
THE BIGGER PICTURE
19. Assuming 8-bit two’s complement integers, compute the binary subtraction 01100011 - 00011000 by adding the two’s complement of 00011000 to 01100011. Verify the calculation in base 10. Assuming 16-bit two’s complement integers, add the two values 1001000000001011 + 0110100010010111 and write down the binary result. Verify that the result is correct by converting the values to decimal. What subtraction is being done by this “addition”? 20. The ten’s complement of an n-bit decimal number x is defined to be 10n x. For example, the ten’s complement of 198 is 103 198 802. A fast way to calculate the ten’s complement of 198 is to subtract 198 from 999 and then add 1. Subtracting from 999 is easy because for every digit i that you subtract, each resulting digit is simply 9 i. Calculate the ten’s complement of 1872, 192, 981652, and 19734. 21. Let’s do decimal subtraction using just addition. To subtract 198 from 217, simply add the ten’s complement of 198 to 217. Why does this work? Recall that the ten’s complement of 198 is 1000 198. Therefore, adding the ten’s complement of 198 to 217 gives 1000 198 217 1000 217 198 1019. This answer is exactly 1000 too high, so by ignoring the extra 1 in the fourth column, we get the correct answer of 19.
sim23356_ch01.indd 22
a. Compute 78612 12832 by adding the ten’s complement of 12832 to 78612. b. Compute 8012 2318 by adding the ten’s complement of 2318 to 8012. 1
See David A. Patterson and John L. Hennessy, Computer Organization and Design : The Hardware/Software Interface. Morgan Kaufmann Publisher, Third Edition, 2007.
12/15/08 6:26:21 PM
CHAPTER
2
Expressions and Data Types “Can you do addition?” the White Queen asked. “What’s one and one and one and one and one and one and one and one and one and one?” “I don’t know,” said Alice. “I lost count.” —Lewis Carroll
Objectives The objectives of Chapter 2 include an understanding of simple Java programs that utilize print and println, Java style comments, string literals, primitive data types: char, int, double, and boolean, numerical, relational, and boolean operators, operator precedence, expressions composed of primitive data types, and expressions that mix data types.
2.1 INTRODUCTION A computer program or application is a set of instructions, written in a programming language that enables a computer to perform some specified task. An application can play championship chess, control interplanetary probes, manage the tunes on your iPod, or navigate the Internet. This chapter does not teach you how to write a chess-playing program or even how to design a simple application that balances your checkbook. In this chapter, our goals are more modest: you will learn how to display text on your computer’s screen and also how to instruct a computer to perform simple arithmetic calculations. “Everything comes gradually and at its appointed hour.”—Ovid
2.2 IN THE BEGINNING . . . We begin our discussion with the simplest of examples: an application that displays a single line of text. 23
sim23356_ch02.indd 23
12/15/08 6:27:31 PM
24
Part 1
The Fundamental Tools
EXAMPLE 2.1 Problem Statement Write a program that displays the line of text Peter Piper picked apart a pithy program
Java Solution 1. 2. 3. 4. 5. 6. 7. 8.
// This application prints "Peter Piper picked apart a pithy program." on the screen public class TongueTwister { public static void main(String[] args) { System.out.println ("Peter Piper picked apart a pithy program."); } }
Output Peter Piper picked apart a pithy program.
Discussion Taking a cue from Peter, let’s pick apart the program and analyze it, line by line. Line numbers are not part of a Java program and appear only for reference. Line 1
Line 1 is a comment.
Programmers use comments to explain or clarify the meaning of some section of a program.
This program is not complicated. Even a novice programmer would understand its purpose without the comment. With more complex and intricate programs, comments are extremely important for explaining the programmer’s intentions. Since programs are continually updated or changed, well-written, succinct comments can save a programmer many hours of frustration. Comments are optional in the sense that they are not required to make the program work correctly, but stylistically, they are mandatory. Comments may be placed anywhere within a Java program. As your programs become increasingly more complex, you will see that well-placed comments can save you programming time and improve the readability and clarity of your programs.
A single-line comment begins with the compound symbol // (two forward slashes) and continues until the end of the line.
The text of the comment is not executable and is ignored by the compiler. Once the compiler recognizes the beginning of a single-line comment, the compiler skips all subsequent text on that line. A comment may begin anywhere on a line. Line 1 is a singleline comment. Java also provides multi-line comments. A multi-line comment begins with the compound symbol /* and ends with the compound symbol */. Between these markers you may include any text whatsoever—except another multi-line comment symbol.
sim23356_ch02.indd 24
12/15/08 6:27:32 PM
Chapter 2
Expressions and Data Types
25
The compiler ignores all text between these two symbols. Consequently, if you forget to “close” or terminate a multi-line comment, parts of your program might be ignored. Here is the program of Example 2.1 rewritten with a multi-line comment. /* This application prints the sentence "Peter Piper picked apart a pithy program." on the screen */ public class TongueTwister { public static void main (String[] args) { System.out.println ("Peter Piper picked apart a pithy program.") } } Line 2
Line 2 begins with two special words—public and class—that you will see over and over again. In later chapters, these words will have greater meaning for you. For the present, it is more convenient to just remember that all of your programs must begin with these two words. In fact, you might think of “public class” as synonymous with “program.” This is indeed a gross simplification, and soon you will see that a program or application usually consists of many “classes,” public or otherwise. For now, each of our applications consists of a single named class. The third word on line 2, TongueTwister, is the name of the class. Although the programmer chooses the class name, that name must be a valid Java identifier.
A valid Java identifier is a “word” of arbitrary length composed of letters and/or digits and/or two special characters $ (dollar sign) and _ (underscore), where the first character must be a letter.
For example, R2D2, HarryPotter, and MyProgram are valid Java identifiers. Hamlet is a valid identifier but 2BorNot2B is not. Java is case sensitive. The name TongueTwister is considered different than tonguetwister and TONGUEtwister. Also, Java assigns special meanings to certain words and, as such, these words may not be used as Java identifiers. Such words are called keywords or reserved words. The words public and class are keywords. A list of Java keywords is shown in Figure 2.1. Finally, the words true, false, and null, although not keywords, have very specific meanings in Java and may not be chosen as identifiers.
abstract continue for
new
boolean do
if
private this
byte
else
import public
catch
extends int
short
class
finally
strictfp volatile const float
long
switch
assert default goto
package synchronized
break double implements protected throw
throws case
enum
instanceof
return
transient
try
final
interface
static
void
native
super
while
char
FIGURE 2.1 Java keywords
sim23356_ch02.indd 25
12/15/08 6:27:33 PM
26
Part 1
The Fundamental Tools
By convention, a class name begins with an uppercase letter. Because spaces may not be part of a name, uppercase letters are commonly used to separate “words” within a name. Some class names that follow these practices are TongueTwister, MyProgram, or TweedledumAndTweedledee. This style is called camelCase, because of the “bumps” in the middle of the word, suggestive of the humps on a camel. Lines 3 and 8
The curly braces “{” and “}” on lines 3 and 8 mark the beginning and the end of the TongueTwister class that comprises our application. A group of statements or instructions enclosed by curly braces is called a block. The body or executable section of a class is contained within these matching braces. Thus, the general structure of a class is: public class ProgramName { // class body //This class body is a block }
where ProgramName is a valid Java identifier. Again, an application usually consists of one or more classes. Lines 4, 5, 7
The line public static void main ( String[] args)
is certainly a mouthful of Java-speak. This line is the first line or the heading of the class’s main method. Generally speaking, a method is a section of a class that performs a task. More specifically, a method consists of a named list of statements that a program carries out or executes. You might think of a statement as an instruction or a directive. A method might contain a single statement or several dozen. Although the sample program has but a single method (named main), a more complicated class usually has many methods, each with its own name. The main method, however, is special among methods. When a Java program starts, the main method is automatically executed. That is, the statements of the main method are executed first. The main method is the starting point of every program. Consequently, every application must have a main method. And every main method begins with the same (albeit, for now, mysterious) first line. The curly braces of lines 5 and 7 mark the beginning and the end of the main method. The actions that the main method performs are included between these curly braces.
sim23356_ch02.indd 26
12/15/08 6:27:34 PM
Chapter 2
Expressions and Data Types
27
Thus far, a Java program has the following skeletal format: public class ProgramName { public static void main (String args []) { // executable statements go here } }
Notice that we have aligned the matching braces of a block and indented statements within matched braces. This program format is a matter of style and not syntax. The application would run even if it were typed on a single line. Another common style of program layout is public class ProgramName { public static void main (String[] args){ // executable statements go here } }
However, the programs in this text use the first style, which aligns matching pairs of curly braces. Line 6
Line 6 is the only statement or instruction of the main method. The statement System.out.println ("Peter Piper picked apart a pithy program");
instructs the computer to print Peter Piper picked apart a pithy program on the screen. The quoted text ("Peter Piper picked apart a pithy program") is called a string literal or more simply a string. A string literal must be contained on a single line. The quotation marks are not part of the string literal. The quotation marks indicate the beginning and the end of the string. The statement System.out.println ("Peter Piper picked apart a pithy program.");
instructs the computer to display the string literal on the screen. The statement also prints the newline character, that is, it advances the cursor to the next line. Printing the newline character ensures that the next item that is printed begins on a new line. Printing the newline character is akin to pressing the Enter key.
The newline character causes the cursor to advance to the start of the next line.
The words (and periods) System.out.println will become more meaningful in subsequent chapters. But, for the present, you should accept System.out.println (or simply println) as the instruction that prints text followed by the newline character. The word println is actually the name of a method that Java provides for output. We refer to the string supplied to this println method as an argument. That is, "Peter Piper picked apart a pithy program." is an argument supplied to the println method. Previously, we stated that a method performs a task. Specifically, the task of the println method is to print its argument.
sim23356_ch02.indd 27
12/15/08 6:27:35 PM
28
Part 1
The Fundamental Tools
You will notice a semicolon at the end of the statement in line 6. Java dictates that all statements are terminated with a semicolon. The semicolon is not optional. Forgetting semicolons is often the bane of beginning programmers. Finally, the program must be saved in a file named TongueTwister.java. In general, if a class name is ClassName, you must save the class in a file called ClassName.java.
The application of Example 2.1 displays a string. At this point some questions about strings may come to mind. If quotation marks are used to indicate the beginning and the end of a string literal, can a string contain a quotation mark? How does an application print the string "Oh, so they have Internet on computers now!" exclaimed Homer Simpson
with its two quotation marks? The erroneous statement System.out.println (" " Oh, so they have Internet on computers now! "exclaimed Homer Simpson ");
does not do the job. The second quotation mark within the string falsely signals the end of the string, and results in a syntax error. The Java solution is simple. To include quotation marks within a string literal, use the escape sequence, \" (backslash, quote) as in the following Java statement: System.out.println (" \" Oh, so they have Internet on computers now! \" exclaimed Homer Simpson ");
The previous statement produces the following output: "Oh, so they have Internet on computers now! " exclaimed Homer Simpson
The print method is a variation of println. The next example illustrates the single difference between these two methods.
EXAMPLE 2.2
Problem Statement Using print rather than println, write a program that displays the sentence Peter Piper picked apart a pithy program.
Java Solution 1. // This program prints the sentence "Peter Piper picked apart a pithy program." on the screen 2. public class AnotherTongueTwister 3. { 4. public static void main( String[] args) 5. {
sim23356_ch02.indd 28
12/15/08 6:27:35 PM
Chapter 2
29
Expressions and Data Types
6. System.out.print ("Peter Piper picked apart "); // print NOT println 7. System.out.print ("a pithy program."); 8. } 9. }
Output Peter Piper picked apart a pithy program.
Discussion The application has two statements within the main method. Notice that these statements are of the form System.out.print
rather than System.out.println
Here, unlike the println method of Example 2.1, the statement System.out.print ("Peter Piper picked apart ");
does not print the newline character following the string literal. Consequently, the program’s output is Peter Piper picked apart a pithy program.
Both string literals appear on a single line. The two strings are displayed next to each other. No newline characters are generated.
Here is one final example that uses both System.out.println and System.out.print.
Blaise Pascal (1623–1662) is often credited with the design of one of the first “computers.” Pascal’s computer, actually a calculating machine constructed of cogs, gears, and wheels, was capable of addition and multiplication. Subtraction and division could be accomplished only through a rather tedious and indirect method. The following program displays a little bit of that computer history. Program output is produced on four separate lines. Notice the use of both print and println.
EXAMPLE 2.3
Java Solution 1. public class ComputerHistory 2. { 3. public static void main(String[] args) 4. { 5. System.out.print ("A guy named Pascal had a scheme"); 6. System.out.println(); // prints the newline character 7. System.out.print ("For building an adding machine"); 8. System.out.println(); 9. System.out.print (" Too bad, his contraption"); 10. System.out.println(); 11. System.out.print (" Could not do subtraction"); 12. System.out.println(); 13. System.out.print ("Subtraction remained just a dream "); 14. System.out.println(); 15. } 16. }
sim23356_ch02.indd 29
12/15/08 6:27:36 PM
30
Part 1
The Fundamental Tools
Output A guy named Pascal had a scheme For building an adding machine Too bad, his contraption Could not do subtraction Subtraction remained just a dream.
Discussion As you know, output from the statement, System.out.print("…") does not include a newline character. However, System.out.println() outputs the newline character and only the newline character. No string argument is supplied to println, so no string is printed.
2.3 DATA TYPES AND EXPRESSIONS Although displaying tongue twisters and limericks might be momentarily intriguing, the fascination wears thin rather quickly. So, let’s move ahead to applications that actually perform some computation. Again, we begin with a rather simple example.
EXAMPLE 2.4 The song “Seasons of Love” from the musical play Rent repeatedly declares that there are 525,600 minutes in a year. For most years, that’s just fine, but what about leap years?
Problem Statement Write an application that calculates the number of minutes in a leap year. Java Solution 1. //Calculates the number of minutes in a leap year 2. // Uses the fact that there are 525,600 minutes in a 365 day year 3. public class LeapYearMinutes 4. { 5. public static void main(String[] args) 6. { 7. System.out.print( "The number of minutes in a leap year is "); 8. System.out.println( 60 * 24 ⴙ 525600); // 60 min/hr times 24 hr/day ⴙ 525600 min 9. } 10. }
Output The number of minutes in a leap year is 527040 Discussion Lines 7 and 8 are the only instructions or executable statements of the application. As you already know, the instruction on line 7 displays the string The number of minutes in a leap year is on the screen. Line 8 requires some explanation. Again, you see the now familiar println method. In this case, however, the argument supplied to the println method is not a string literal (look, no quotes!) but a numerical expression: 60 * 24 525600. An expression is a sequence of symbols that denotes, represents, or signifies a value.
sim23356_ch02.indd 30
12/15/08 6:27:37 PM
Chapter 2
Expressions and Data Types
31
The value of the expression 60 * 24 525600 is 527040. In this case, 60 and 24 are multiplied ("*" signifies multiplication) and the product is added to 525600. The value of the computation, 527040, is supplied to the println method, and that number is displayed on the screen. In the expression 60 * 24 525600, the symbols * and are called operators and the numbers 60, 24, and 525600 are called operands. We say that the expression 60 * 24 525600 evaluates to 527040.
Example 2.4 involves the multiplication and addition of integers. Of course, Java allows computation and manipulation of other types of data such as floating-point numbers and even alphabetical characters. Each type of data is identified with a specific data type. A data type is a set of values together with an associated collection of operators for manipulating those values. We begin with four primitive data types: int, double, char, and boolean. There are others, which we discuss in subsequent chapters.
2.3.1 Type int The values associated with the data type int are integers in the range 2,147,483,648 to 2,147,483,647. This range of numbers will make more sense later. And, as you will see, Java can handle even larger numbers. The associated operators that manipulate integers are: * / %
addition subtraction multiplication division modulus
The , , and * (times) operators function as they do in ordinary arithmetic. Thus the expression 4 6 evaluates to 10; 3 5 has the value 2; and 12 * 10 has the value 120. The / operator, however, denotes integer division; that is, a / b evaluates to a divided by b, discarding any remainder. Java specifies that the quotient of two integers is always an integer. Thus, 5 / 2 evaluates to 2; −23 / 6 evaluates to −3; and 4 / 43 has the value 0. The modulus operator % may be new to you. The expression a % b evaluates to the remainder of a divided by b. The value of a % b has the same sign as a. Consequently, 5 % 2 has the value 1; 23 % 3 the value 2; and 47 % (43) the value 4. The modulus operator is used more often than you might think. For example, we can use the modulus operator to determine whether an integer is odd or even. If x % 2 is 0 then x is even, otherwise x is odd. Also, you can use “%10” to extract the smallest digit of an integer. For example, 23657 % 10 evaluates to 7, the units digit of 23657. The expressions a/b and a % b evaluate respectively to the quotient and remainder of a divided by b. Example 2.5 illustrates both integer division and the modulus operator.
sim23356_ch02.indd 31
12/15/08 6:27:39 PM
32
Part 1
The Fundamental Tools
EXAMPLE 2.5 Each year, Betting Betty sets aside her spare pennies for an annual jaunt to Las Vegas. Betty bets exclusively at the quarter slot machines. This year, Betty has saved a total of 23,478 pennies.
Problem Statement Devise an application that displays the number of quarters that Betty can get from her bankroll and how many pennies remain for next year’s excursion. Java Solution 1. //Calculates the number of quarters and the remaining pennies obtained from 23478 pennies 2. public class BettysBundle 3. { 4. public static void main(String[] args) 5. { 6. System.out.println( "In 23478 pennies there are: "); 7. System.out.print( 23478/25); // how many quarters? 8. System.out.println( " quarters."); 9. System.out.print( 23478%25); // how many pennies remain? 10. System.out.println( " pennies remain"); 11. } 12. }
Output In 23478 pennies there are: 939 quarters. 3 pennies remain
Discussion The division on line 7 determines how many quarters are in Betty’s bundle. Remember this is integer division. The remainder gives the number of pennies left over. The remainder is calculated on line 9 using the modulus operator %.
Of course, integer expressions may contain several operators. The expression 2 * 3 4 * 5 has three operators and a value of 26. The order in which operations are performed is the same as in ordinary arithmetic. That is, for integer expressions, operations are performed according to the precedence (priority) rules of Figure 2.2. high Operator
*
/
Associativity %
Left to right Left to right
low FIGURE 2.2 Operator precedence Figure 2.2 implies that 1. *, /, and % have the highest precedence and are performed before or . 2. *, /, and % are equal in precedence.
sim23356_ch02.indd 32
12/15/08 6:27:40 PM
Chapter 2
33
Expressions and Data Types
3. and are equal in precedence but lower than *, /, and %. 4. Operations of equal precedence have left-to-right associativity. Thus 6 3 1 is evaluated as (6 3) 1 3 1 2 and not 6 (3 1) 6 2 4. And, 8 / 3 * 4 is processed as (8 / 3) * 4 8, and not 8 / (3 * 4) 0. You may explicitly change the order of operations by inserting parentheses into an expression. An expression enclosed by parentheses must always be fully evaluated before it can be used in a larger expression. Thus, you might say that parentheses have the highest precedence. For example, the two multiplications of the expression 2 * 3 4 * 5 are performed before the addition: 2*34*5 6 4*5 6 20 26 However, the parentheses of 2 * (3 4) * 5 force the addition to be performed first: 2 * (3 4) * 5 2*7*5 14 * 5 70
The program in Example 2.6 uses an integer expression that is a bit more complex than those we have seen so far.
Superstitious Sam has recently suffered a streak of bad luck. In light of some recent unfortunate events and because his birthday is May 13, 1988, Sam speculates that perhaps he was born on a Friday, yes, the fearsome Friday the 13th. Certainly, that would explain Sam’s unhappy circumstances. Being mathematically savvy, Sam knows that, using a method developed by the Rev. Christian Zeller (1822–1899), he can find the day of the week for any date (month/ day/year) with the following formula: Day of the week
EXAMPLE 2.6
((day (13 * ((month 9) % 12 1) 1) / 5 year % 100 year % 100 / 4 year / 400 2 * (year / 100) ) % 7 7) % 7 1
where • Day of the week is a number between 1 and 7 representing the day of the week (Sunday 1, Monday 2 . . . , Saturday 7), • day is the day of the month (1 through 31), • month is encoded as January 1, February 2 . . . December 12, and • year is the four-digit year in question. Look over the formula and make sure that you understand the operations and the order of operations. It is rather complicated.
sim23356_ch02.indd 33
12/15/08 6:27:41 PM
34
Part 1
The Fundamental Tools
Problem Statement Write an application that determines whether or not Sam’s birthday, May 13, 1988, occurred on a Friday. Java Solution 1. // Displays the number of the day (1-7) on which May 13, 1988 occurred. 2. public class DayFinder 3. { 4. public static void main(String[] args) 5. { 6. System.out.print ("May 13, 1988 fell on day number "); 7. // Uses the Zeller formula 8. System.out.println( ((13 (13*((5ⴙ9)%12ⴙ1) 1)/5 // day 13, month 5 9. 1988%100 // year 1988 10. 1988%100/4 11. 1988 /400 12. 2*(1988 /100))%7 7) %71 ); 13. } 14. }
The output confirms Sam’s worst suspicions.
Output May 13, 1988 fell on day number 6
Discussion If you look closely at the program, you might think that parentheses are unnecessary in the term 2 * (1988 / 100). That is not the case. If Java used “ordinary” (decimal) division, 2 * (1988 / 100) 2 * 19.88 39.76 and (2 * 1988) / 100 3976 / 100 39.76, the parentheses would not matter. However, using integer division, 2 * (1988 / 100) 2 * 19 equals 38, while (2 * 1988) / 100 3976 / 100 has the value 39. The parentheses in 2 * (1988 / 100) make a difference.
2.3.2 Type double The values associated with data type double are decimal numbers in the range 1.7 10308 . . . 1.7 10308 with 14 significant digits of accuracy. You can express a number of type double in two ways: 1. Decimal notation 2. Scientific or exponential notation Numbers like 123.45 or .05 are numbers written in decimal notation. Scientific notation may be a little less familiar to you. The term 2.3E2 (or 2.3e2) is an example of a number expressed in scientific notation. The number 2.3E2 is numerically the same as 2.3 102. Thus, 2.3E2 2.3 102 230.00. Similarly, 3.2E3 3.2 103 3200.00 and 234.567E1 234.567 10 2345.67.
sim23356_ch02.indd 34
12/15/08 6:27:42 PM
Chapter 2
35
Expressions and Data Types
In general, a number of the form x Ey (or x ey), where y is an integer, means x 10y. The number x is called the base and y is called the exponent. As in ordinary mathematics, an exponent may be negative. Recall that 10n 1/10n. Thus 4.63E-2 4.63 102 4.63 1/102 4.63 1/100 .0463 You may have noticed that when converting from scientific notation to decimal notation, a positive exponent, n, necessitates moving the decimal point to the right n places and a negative exponent, -n, necessitates moving the decimal n places to the left. Zeroes are added, if necessary. Thus, to convert 4.56789123E5 to decimal notation, move the decimal five places right. The equivalent number is 456789.123. Similarly, 55.2E-4 is equivalent to .00552. The operators associated with type double are − * /
addition subtraction multiplication division
Here the division operator (/) denotes decimal or floating-point division rather than integer division; so 5.0 / 2.0 has the value 2.5 but 5 / 2 has the value 2. The % operator can also be used with numbers of type double, e.g., 5.5 % 2.5 .5, but its use is usually restricted to integers.
Does intelligent life, capable of interplanetary communication, exist? Astronomer Frank Drake may have an answer. Drake’s equation provides a method for estimating the number of intelligent civilizations capable of interplanetary communication that may exist in our galaxy. Drake’s equation is usually expressed as:
EXAMPLE 2.7
N ⴝ R ⴛ fp ⴛ ne ⴛ f l ⴛ fi ⴛ fc ⴛ L where N is the number of extraterrestrial civilizations capable of interplanetary communication, R is the average rate of star formation in our galaxy (number per year), fp is the fraction of stars with planets, ne is the average number of planets in a solar system that can support life, fl is the fraction of suitable planets where any type of life develops, f i is the fraction of life bearing planets that have intelligent life, fc is the fraction of planets with intelligent life on which the interplanetary communication develops, and L is the average lifetime (in years) of a civilization that develops technology. Each of these values is either a rate or a fraction, so each can be represented by a number of type double. Of course, no one can determine these numbers with any certainty, and conjecture abounds.
Problem Statement Write an application that determines N given some typical default values: 20.0, .5, .5, .5, .2, .2, and 500.00 for R, fp , ne , fl , fi , fe, and L.
sim23356_ch02.indd 35
12/15/08 6:27:43 PM
36
Part 1
The Fundamental Tools
Java Solution 1. // An application of Drake’s Equation with default values 2. // R20.0, fp.5, ne.5, fl.5, fi.2, fc.2 and L500.00 3. public class ET 4. { 5. public static void main(String[] args) 6. { 7. System.out.print("The number of civilizations capable of interplanetary communication is "); 8. System.out.println ( 20.0*.5*.5*.5*.2*.2* 500.00 ); 9. } 10. }
Output The number of civilizations capable of interplanetary communication is 50.0.
Discussion Each of the constants shown on line 8 contains a decimal point, so each is of type double. Consequently, the product is of type double. It appears that we are not alone. ET phone home!
2.3.3 Type char Computer applications do much more than numerical calculations. Programs manipulate large databases of names and addresses, manage inventory files, and facilitate word processing. Such applications must handle alphabetical or character data. Type char is the set of all characters found on the standard keyboard (in addition to thousands of other characters that are used for displaying text in languages that do not use the English alphabet). A value of type char is enclosed in single quotes. Thus 'A' denotes a value of type char as do '%' and '$'. Note that '5' is a value of type char, "5" is a string literal, and 5 is an integer. They are all different. The integer expression 1 5 has the value 6 but, as you will see later, the expression 1 '5' has the value 54, and the expression 1 ''5'' has the value ''15''. Computers store characters as non-negative numbers. Every character has a code number called its ASCII value. Even “control characters” such as the backspace and the tab have assigned codes. So, what determines a character’s internal code number? The ASCII (American Standard Code for Information Interchange) code assigns a non-negative integer between 0 and 127 to each character found on a standard English language keyboard. For example, 'A' is assigned 65, 'B' is assigned 66, 'Z' is assigned 90, '5' is assigned 53, '6' is assigned 54, and backspace is assigned 8. Like all data, these values are stored as binary numbers, typically a leading 0 followed by a 7-bit code number between 0 and 127 inclusive. For example, 'A' is stored as 01000001, which is the binary equivalent of 65; and the code for the backspace is 00001000, the binary representation of 8. ASCII values can be stored using a single byte of memory; that is, one character requires just one byte of storage.
sim23356_ch02.indd 36
12/15/08 6:27:43 PM
Chapter 2
37
Expressions and Data Types
The ASCII character set can be found in Appendix B. Although an ASCII value requires just one byte of storage, Java uses the Unicode character set and allocates two bytes of memory for each character. A one-byte scheme allows up to 255 different code numbers, of which ASCII uses half. Using two bytes expands the range significantly to 65,536 characters. Consequently, using two bytes instead of ASCII’s one byte allows the Unicode character set to include not only English characters but also characters for many other languages such as Greek, Chinese, Arabic, Japanese, and Hebrew. By design, the ASCII character set is a subset of Unicode. So, for example, the character 'A' has the code value 65 in both ASCII and Unicode. The ASCII code for 'A' is stored as 01000001 (one byte), while the Unicode representation is 0000000001000001 (two bytes). Throughout this text, we will restrict our use of characters to the ASCII subset of Unicode. In addition to standard alphanumeric characters, the value set of type char includes several special characters that are represented by an escape sequence or escape character. You have already seen the escape sequence \", which designates a double quotation mark. Other common escape sequences are: \n \t \b \r \' \\
newline tab backspace carriage return single quote backslash
Like the escape sequence \", any escape character may be used within a string literal as Example 2.8 illustrates.
Returning to the history lesson of Example 2.3, we point out that Blaise Pascal’s mechanical computer, dubbed the Pascaline, was not a colossal success. Pascal’s quasifailure is noted in the output of the following program.
EXAMPLE 2.8
Java Solution 1. public class ComputerHistoryToo 2. { 3. public static void main(String[] args) 4. { 5. System.out.print ("Undaunted, Blaise built his machine\n"); // note the escape character, \n 6. System.out.print ("Which came to be called \" Pascaline \"\n "); 7. System.out.print (" \tBut when he unveiled it \n"); 8. System.out.print (" \tSome critics assailed it \n"); // \t is a tab 9. System.out.print ("Reviews ranged from mean to obscene "); 10. } 11. }
Output Undaunted, Blaise built his machine Which came to be called "Pascaline" But when he unveiled it Some critics assailed it Reviews ranged from mean to obscene
sim23356_ch02.indd 37
12/15/08 6:27:45 PM
38
Part 1
The Fundamental Tools
Discussion Notice the use of print in conjunction with the newline character (\n) on lines 5 through 8. This combination is equivalent to using the single println instruction. The tab character (\t) appears twice in the program (lines 7 and 8) to effect indentation.
2.3.4 Type boolean Type boolean has but two values, true and false. The associated operators are not the standard , , *, and / operators but &&, ||, and !
signifying and, or, and not, respectively. The type name boolean honors the 19th century English mathematician George Boole, who revolutionized the study of logic by making logic more like arithmetic. He invented a method for calculating with truth values (true and false) as well as an algebra system for reasoning about such calculations. Boole’s methods are used extensively today in the engineering of hardware and software systems. Type boolean may seem somewhat peculiar at first since the values, true and false, are perhaps less familiar to you than numbers or characters. To acquire some intuition for boolean values, consider each of the following statements. Like an arithmetic expression, each statement has a value—either true or false. Read each statement and convince yourself that you understand the logic of each assigned value. Statements 1–4 are simple assertions that we accept as either true or false: 1. 2. 3. 4.
Statement Snow is white. Snow is red. The sky is blue. The sky is green.
Value true false true false
Statements 5–14 in Figure 2.3 are compound statements with values, true or false, which can be derived from the values of statements 1–4. Read each statement and try to determine its value: true or false. Statement
Value
Comparable boolean expression
5. Snow is white and The sky is blue
true
true && true
6. Snow is white and The sky is green 7. Snow is red and The sky is blue 8. Snow is red and The sky is green
false false false
true && false false && true false && false
9. Snow is white or The sky is blue 10. Snow is white or The sky is green 11. Snow is red or The sky is blue 12. Snow is red or The sky is green
true true true false
true || true true || false false || true false || false
13. It is not the case that Snow is white 14. It is not the case that the sky is green
false true
!true !false
FIGURE 2.3 Boolean operations
sim23356_ch02.indd 38
12/15/08 6:27:46 PM
Chapter 2
39
Expressions and Data Types
Just as an integer expression such as 2 * 4 3 has the value 11, the boolean expression true && true (statement 5) has the value true; the expression false || true (statement 11) has the value true; and !true (statement 13) has the value false. Figure 2.4 summarizes Java’s boolean operators.
x
y
x && y (and)
x || y (or)
!x (not)
true
true
true
true
false
true
false
false
true
false
false
true
false
true
true
false
false
false
false
true
FIGURE 2.4 Boolean operators
Notice that the expression x && y has the value true only if both operands, x and y, are true. The expression x || y is false only if both operands are false. Among boolean operators, ! (not) has the highest precedence, followed by && and finally ||. Example 2.9 uses electrical circuits to illustrate the type boolean.
A switching circuit through which electricity flows consists of wires and switches. Assume that electricity flows from terminal A to terminal B. When a switch, X, is open, the flow of electricity is stopped; when X is closed electrical flow is uninterrupted. See Figure 2.5.
A
B
X
A
B
X
Open switch
EXAMPLE 2.9
Closed switch
FIGURE 2.5 Electricity flows when X is closed A light switch is a simple illustration of a switching circuit. If a light switch is turned on (closed) electricity flows to the bulb, but when the switch is off (open) the flow of current is interrupted and electricity cannot reach the bulb. Two simple circuits are displayed in Figure 2.6. X A
X
Y Serial circuit
B
A
B Y Parallel circuit
FIGURE 2.6 Two circuits Electricity flows from A to B through the serial circuit of Figure 2.6 if and only if both X and Y are closed. Electricity flows from A to B through the parallel circuit if and only if either X or Y is closed (or both are closed).
sim23356_ch02.indd 39
12/15/08 6:27:46 PM
40
Part 1
The Fundamental Tools
If we assign a closed switch the value true and an open switch the value false, Figures 2.7 and 2.8 illustrate the possible scenarios for the serial and parallel circuits. A value of true in the third column (Flow) indicates that the current is uninterrupted.
X
Y
true true (closed) (closed) true false (closed) (open) false true (open) (closed) false false (open) (open)
Flow ⴝ X && Y true (flows) false (does not flow) false (does not flow) false (does not flow)
X
Y
true true (closed) (closed) true false (closed) (open) false true (open) (closed) false false (open) (open)
FIGURE 2.7 Serial
Flow ⴝ X || Y true (flows) true (flows) true (flows) false (does not flow)
FIGURE 2.8 Parallel
Notice that, for the serial circuit, when X && Y has the value true, electricity flows from A to B; for the parallel circuit when the expression X || Y is true, electricity flows. Figure 2.9 shows a more complex circuit with terminal points A and B and four switches X, !X, Y, and !Y. (Note that !X is a switch that is open when X is closed and closed when X is open. !Y is similar.). The switches of Figure 2.9 can be either open or closed. A boolean expression that models this circuit is: (X && !Y || !X && !Y || !X && Y) && ( !Y || X) !X
Y X
!X
A X
!Y !Y
B !Y
FIGURE 2.9 A more complicated circuit
Of the four possible switch configurations of the circuit: 1. 2. 3. 4.
X closed, Y closed X closed, Y open X open, Y closed X open, Y open
(so consequently, !X open, and !Y open) (!X open, !Y closed) (!X closed, !Y open) (!X closed, !Y closed)
two (2 and 4) let the electricity flow from A to B. The dark lines in Figure 2.10 show the flow through the circuit when X is closed and Y is open (configuration 2). !X
Y X
!X
A X
!Y !Y
B !Y
FIGURE 2.10 Flow through the circuit when X is closed and Y is open
sim23356_ch02.indd 40
12/15/08 6:27:48 PM
Chapter 2
Expressions and Data Types
41
Problem Statement Write a program that demonstrates that the electricity flows from A and B whenever • X is closed and Y is open, that is, when X true and Y false, or • X is open and Y is open, that is, when X false and Y false. More simply, electricity flows from A to B whenever Y is open.
Java Solution 1. 2. 3. 4. 5. 6.
// Evaluates the four possible switch configurations: // closed-closed, closed-open, open-closed, and open-open // for the circuit modeled by the boolean expression // (X && !Y || !X && !Y || !X && Y) && (X || !Y) // the application displays true or false for each configuration indicating whether // or not an electrical current can flow through the circuit
7. public class Circuit 8. { 9. public static void main (String[] args) 10. { 11. System.out.print("If X is closed and Y is closed. Flow: "); // Xⴝtrue; Yⴝtrue 12. System.out.println((true && !true || !true && !true || !true && true) &&(true ||!true)); 13. 14.
System.out.print("If X is closed and Y is open. Flow: "); // Xⴝtrue; Yⴝfalse System.out.println((true && !false || !true && !false || !true && false) && (true ||!false));
15. 16.
System.out.print ("If X is open and Y is closed. Flow: "); // Xⴝfalse; Yⴝtrue System.out.println((false && !true || !false && !true || !false && true) &&(false || !true));
17. System.out.print("If X is open and Y is open. Flow: "); // Xⴝfalse; Yⴝfalse 18. System.out.println((false && !false ||!false&& !false || !false && false) &&(false ||!false)); 19. } 20. }
Output If X is closed and Y is closed. Flow: false If X is closed and Y is open. Flow: true If X is open and Y is closed. Flow: false If X is open and Y is open. Flow: true
2.3.5 Relational Operators In addition to the operators &&, ||, and !, Java provides a set of relational operators, used in expressions that evaluate to true or false. Each relational operator requires two operands, which may be two integers, two decimal numbers, or two characters. The relational operators are: !
sim23356_ch02.indd 41
less than less than or equal greater than greater than or equal equals (has the same value) not equal
12/15/08 6:27:49 PM
42
Part 1
The Fundamental Tools
Character data are compared using Unicode (ASCII) integer values. For example, because 'A' has the code value 65, and 'C' the value 67, the expression 'A' 'C' evaluates to true since 65 67. The ASCII encoding purposely encodes letters so that they are ordered alphabetically. Similarly, '1' '2' has the value true, as you would expect, because 49 50. You should be careful when comparing characters of different case, however. The numerical value of 'a' is 97, so the expression 'a' 'C' (97 67) evaluates to false as does 'a' 'A' since 97 does not equal 65. The order of operations is performed according to the precedence table of Figure 2.11.
high Operator
Associativity
!
Right to left
*
/
!
Left to right
%
Left to right
Left to right Left to right
&&
Left to right
||
Left to right
low FIGURE 2.11 Operator precedence
Figure 2.11 indicates that the ! (not) operator is right associative. This means that an expression such as !!!true is evaluated from right to left as !(!(!true)). The ! operator is called a unary operator because ! operates on only one value. All the other operators that we have discussed are binary operators because they operate on two values. The following expressions illustrate the relational operators as well as some relational expressions. 1. 5 3 || 6 2 2. 1 14 % 5 0 3. 'A' 'B'
false || true has the value true
4. 'Z' 'a'
true
5. 6. 7. 8.
1 1 2 || 1 1 3 37 / 3 .3333 2 3 && 4 5 || 7 5 && 2 3 2 3 && (4 5 || 7 5) && 2 3
9. false false 10. true ! false
sim23356_ch02.indd 42
false true
(code for 'A' is 65; for 'B' it is 66: 65 66) (code for 'Z' is 90 and for 'a' it is 97: 90 97) true || false has the value true true true || false has the value true true && true && false has the value false true true
12/15/08 6:27:50 PM
Chapter 2
Expressions and Data Types
43
Expressions such as 2 3 4 make no sense in Java. Java attempts to evaluate this expression as (2 3) 4 true 4. The expression true 4 is invalid and generates an error. The Java equivalent of 2 3 4 is (2 3) && (3 4).
A leap year is any year divisible by four except those years divisible by 100 unless the year is also divisible by 400. For example, 2000 was a leap year but 1900 was not. In researching her family tree, Jeannie Ology has discovered that her great-greatgreat grandmother’s birth certificate records the date of birth as February 29, 1800. Jeannie is a bit suspicious of the date. Was 1800 a leap year? Jeannie, being a skilled programmer but an error-prone mathematician, has devised a program to determine whether or not Granny’s birth certificate is in error. Her program displays true or false depending upon whether or not 1800 was a leap year. When you read the program, be certain that you understand the boolean expression on line 9 and how that expression satisfies the leap year conditions. The expression includes boolean operators as well as several relational operators. Parentheses are not necessary. Can you determine the order of the operations?
EXAMPLE 2.10
Problem Statement Write a program that determines whether or not 1800 was a leap year. Java Solution 1. // A leap year is a year that is divisible by 4 but not 100 unless it is divisible by 400 2. // This program determines whether or not 1800 meets all conditions of a leap year 3. public class LeapYear 4. { 5. public static void main(String[] args) 6. { 7. System.out.print("The year 1800 is a leap year? True or false: "); 8. // (divisible by 4 and not by 100) or (divisible by 400) 9. System.out.println( 1800%4 ⴝⴝ0 && 1800 %100 !ⴝ0 || 1800%400 ⴝⴝ 0 ); 10. } 11. }
Output The year 1800 is a leap year? True or false: false
Discussion So, it appears that the birth certificate is in error. There are no awards for programming with the least number of parentheses, and obscure code should never be a matter of pride. To make your code easier to read, regardless of whether it is technically required, include parentheses in your expressions. Here is a fully parenthesized version of the expression on line 9: (((1800%4) 0) && ( (1800 %100) !0)) || ((1800%400 ) 0 )
This version is preferable to the one we used on line 9.
sim23356_ch02.indd 43
12/15/08 6:27:50 PM
44
Part 1
The Fundamental Tools
2.3.6 Short Circuit Evaluation Consider the following partial boolean expressions, where something and something_else have boolean values 1. (3 5) && (something) 2. (2 9) || (something_else) Expression 1 always has the value false, regardless of the value of something. If something is true, expression 1 is false; if something is false, expression 1 is false. This is because the first operand (3 5) is false. No further evaluation need be performed after the first operand is evaluated since “false && something” always has the value false. The value of something is irrelevant. Expression 2 has the value true regardless of the value of something_else. If one operand has the value true, expression 2 is true. The value of each expression can be determined without evaluating the entire expression. The term on the left is first evaluated, and evaluation stops because the value of the entire expression is determined from this term. This method of evaluation is called short circuit evaluation.
Java uses short circuit evaluation to evaluate expressions involving the boolean operators && and ||.
This means that Java stops the evaluation of an expression once the value of the expression is determined. For example, consider the expression 1 2 || 2 3 || 3 4 The value of this expression is true. Notice that this value can be determined after evaluating 1 2. Consequently, no more of the expression need be considered. Similarly, (1 2) && ( 1 2 || 2 3 || 3 4) has the value false because the first item (1 2) is false. No other evaluation within the expression is necessary. Surprisingly, (1 2 ) && ( 1 3 / 0) causes no error, despite division by zero in the second operand. Because 1 2 has the value false and the short circuit operator && evaluates its left operand first, the value of the expression is false regardless of the second term. The division by 0, 3 / 0, is ignored. On the other hand, the value of the boolean expression (1 2) && (3 4) cannot be determined without evaluating the entire expression. In subsequent chapters, you will see that exploiting short circuit evaluation has its advantages.
2.3.7 Mixing Data Types in a Numerical Expression A Java expression can be constructed from data of several different types. For example, the expression (22 3.0) / 4 contains both integers (int) and decimal numbers (double). Is the value of this expression 6, 6.0, or 6.25? It’s 6.25. How about an expression like 'A' 1,
sim23356_ch02.indd 44
12/15/08 6:27:52 PM
Chapter 2
Expressions and Data Types
45
which mixes character data with integer data? Is the value of this expression 'B' or, since the Unicode (ASCII) value for 'A' is 65, is the value 66? Or, does the compiler consider such an expression an error? When evaluating a binary expression with operands of different data types, Java first promotes or casts the operand of the “smaller” data type to the data type of the other operand. “Smaller” data type? The range of values determines the “size” of a data type. Thus char is smaller than int, which, in turn, is smaller than double.
The expression (22 3.0) / 4 has the value 6.25.
EXAMPLE 2.11
The expression is evaluated as follows: (22 3.0) / 4 The expression consists of decimal and integer types. (22.0 3.0) / 4 The integer 22 is cast to 22.0 (an int is cast to a double). 25.0 / 4 This is floating-point addition—22.0 3.0. 25.0 / 4.0 The integer 4 is cast to 4.0. This is floating-point division. The expression 'A' 1 has the value 66. The expression is evaluated as follows: 'A' 1 The expression consists of character and integer data. 65 1 The character 'A' is cast to the integer 65—its ASCII code value. 66 This is integer addition. The expression 'A' 1.0 has the value 66.0. The expression is evaluated as follows: 'A' 1.0 The expression consists of character and a decimal data. 65 1.0 The integer 65 is the ASCII code for 'A', that is, 'A' is stored as 65. 65.0 1.0 The integer 65 is cast to 65.0. 66.0 This is floating-point addition.
The / operator, which denotes both integer and floating-point division, can often be the source of subtle bugs. For example, consider the formula that converts degrees Fahrenheit to degrees Celsius: 5 (F 32) C __ 9 If F 212.0, the mixed expression (5 / 9) (212.0 32) evaluates to 0, not 100.0.
sim23356_ch02.indd 45
12/15/08 6:27:52 PM
46
Part 1
The Fundamental Tools
This miscalculation is caused by the omission of a decimal point. The value of (5/9) is calculated using integer division, and consequently (5/9) evaluates to 0. The correct conversion formula should be written as (5.0/9.0)(212.0 32), (5.0/9)(212.0 32), or (5/9.0)(212.0 32.) With each expression, division is correctly performed as floating point. Numerical operators can also be used with character operands. In this case, both operands are treated as integers.
EXAMPLE 2.12 The expression 'A' 'Z' has the value 155 since the ASCII values for 'A' and 'Z' are 65
and 90, respectively. Similarly, 'A' 'Z' has the value 25. On the other hand, the expression "A" "B" does not have the value 155. In this case, "A" and "B" are not character data but strings. The operator may be used with strings but, as you will see in the next section, the result is not an integer.
2.3.8 The ⴙ Operator and Strings In Example 2.12, we state that the operator has a special meaning when used with string data: If both operands A and B are strings, then the expression A B evaluates to another string, which is the concatenation (joining together) of A and B. If only one operand is a string, then the other operand is first cast to a string and the value of the expression is the concatenation of two strings. Example 2.13 gives several variations on the operator and string data.
EXAMPLE 2.13
a. Joining two strings The expression "Bibbidi " "Bobbidi " evaluates to a new string "Bibbidi Bobbidi ", which is formed by joining, that is, concatenating, "Bibbidi " and "Bobbidi ". "Bibbidi " "Bobbidi " "Boo" evaluates to the string "Bibbidi Bobbidi Boo", which is formed by first joining "Bibbidi " and "Bobbidi " and then concatenating the result with "Boo". The idea is quite simple; there’s no magic. b. Joining a string and a number The expression 2147483647 " is not only the largest value of type int but also a prime number!" evaluates to the string "2147483647 is not only the largest value of type int but also a prime number!" Here, the first operand is the integer 2147483647, which is cast to the string "2147483647" and then the two strings are concatenated. c. Joining a string and a numerical expression The expression "The sum of the two dice is " (5 2) evaluates to the string "The sum of the two dice is 7"
sim23356_ch02.indd 46
12/15/08 6:27:53 PM
Chapter 2
Expressions and Data Types
47
Notice that the expression in parentheses is evaluated first. Parentheses can force a change in the usual precedence because the expressions inside them must be evaluated first. However, if the parentheses are omitted, then the expression "The sum of the two dice is " 5 2 evaluates to the string "The sum of the two dice is 52." Evaluation proceeds as in the following sequence. Here parentheses have been added for emphasis. ("The sum of the two dice is " 5 ) 2 ("The sum of the two dice is " "5") 2 The integer 5 is cast to string "5". ("The sum of the two dice is 5") 2 "The sum of the two dice is " and "5" are joined. ("The sum of the two dice is 5") "2" The integer 2 is cast to "2". "The sum of the two dice is 52" "The sum of the two dice is 5" is concatenated with "2". Notice that numerical addition is not performed. In contrast, the expression "The product of the two dice is " 5 * 2 evaluates to the string "The product of the two dice is 10". The * operation is performed first since * has higher precedence than . Finally, the expression "The difference of the two dice is" 5 2 is ill formed and causes an error. Since and are of equal priority and are associated (grouped) left to right, the expression is evaluated as: ("The difference of the two dice is " 5) 2 ("The difference of the two dice is " "5") 2 "The difference of the two dice is 5" 2 An error now occurs because the minus () operator cannot be applied to strings. The Java compiler detects this error.
2.4 IN THE BEGINNING . . . AGAIN We have come full circle, and we return to the print and println methods introduced at the beginning of the chapter. You may have noticed that in previous examples we used several println methods to generate a single line of output. Typically to produce the output The cost of 15 wickets is 375 dollars
an application might include three instructions: 1. 2. 3.
System.out.print("The cost of 15 wickets is "); System.out.print( 15 * 25); System.out.println(" dollars");
Java specifies that the print and println methods accept a single argument of any type.
sim23356_ch02.indd 47
12/15/08 6:27:54 PM
48
Part 1
The Fundamental Tools
In statements 1 and 3 (above), that argument is a string literal; in statement 2 the argument is an integer (375). Conveniently, the previous three lines of code can be condensed to a single line System.out.print("The cost of 15 wickets is " (15 * 25) " dollars");
Notice that the mixed expression "The cost of 15 wickets is " (15 * 257) " dollars"); evaluates to the string: "The cost of 15 wickets is 375 dollars" and it is this string that is the argument to the println method.
EXAMPLE 2.14 Test your understanding of various data types and operators and determine the value of each of the following expressions: 1. 2. 3. 4. 5. 6. 7.
'A' 'B' 'A' "B" "A" "B"
"" 'A' 'B' 'A' 'B'"" 3 4 "" "" 3 4
1. Answer: 131 (int) The expression 'A' 'B' is evaluated as (65 66). 2. Answer: AB (string) Since the second operand "B" is a string, 'A' is cast to the string "A". The final value is the concatenation "A" "B" ("AB"). 3. Answer: AB (string) "A" "B" is the concatenation of two strings. 4. Answer: AB (string). The pair of double quotes positioned one after the other denotes the empty string, that is, the string with no characters. The evaluation is accomplished as ("" 'A') 'B' ("" "A") 'B' "A" 'B' "A" " B" "AB"
'A' is cast to string "A". "" and "A" are concatenated to "A". 'B' is cast to "B". "A" and "B" are concatenated.
5. Answer: 131 (string) Here, the first signifies addition and not string concatenation. Thus, the evaluation proceeds as ('A' 'B') "" (65 66) "" 131 "" "131" "" "131"
sim23356_ch02.indd 48
12/15/08 6:27:55 PM
Chapter 2
Expressions and Data Types
49
6. Answer: 7 (string) Associativity for is left to right, so first 3 4 evaluates to 7. Next, 7 "" evaluates to the string "7". 7. Answer: 34 (string) The integer 3 is cast to "3" and string concatenation ("" 3) is effected. Next, 4 is cast to "4" and "3" "4" evaluates to "34".
The International Civil Aviation Organization has devised a formula that calculates the amount of rest (in days) needed to recover from the mental fatigue of jet lag:
EXAMPLE 2.15
1. Divide the length of the trip (in hours) by 2. 2. Subtract 4 from the number of time zones crossed. 3. Determine your departure and arrival time coefficients according to the following chart: Local time Departure time coefficient 8:00 a.m.–12:00 p.m. 0 12:00 p.m.–6:00 p.m. 1 6:00 p.m.–10:00 p.m. 3 10:00 p.m.–1:00 a.m. 4 1:00 a.m.–8:00 a.m. 5
Arrival time coefficient 4 2 0 1
3
Note: if a time is "on the border" then the average of the two coefficients is used. So if a departure time is 6:00 p.m., the departure coefficient is (1 3) / 2 2. 4. Add the values in steps 1–3 and divide by 10 to get the number of days needed to recover from jet lag. Suppose that Zip flies from New York at 4:00 p.m., arriving in Frankfurt at 5:00 a.m. The length of the trip is 7 hours. The number of time zones crossed is 7, so the number of time zones in excess of 4 is 3. The departure time coefficient is 1. The arrival time coefficient is 3.
Problem Statement Write a program that calculates the recommended number of recovery days for Zip’s trip. Java Solution Thus the number of recommended days of rest can be computed as: (7.0 / 2 3 1 3) / 10 This is a mixed-type expression. The result is a value of type double. 1. //Calculates the number of days of jetlag recovery for a flight between New York and Frankfurt 2. //restDays (flightLength/2 timeZones-4 departureCoefficient arrivalCoefficient)/10 3. //where flightLength 7, timeZones 7, departureCoefficient 1, arrivalCoefficient 3 4. public class JetLag 5. { 6. public static void main(String[] args)
sim23356_ch02.indd 49
12/15/08 6:27:56 PM
50
Part 1
The Fundamental Tools
7. { 8. System.out.println("Recommended rest: "ⴙ(7.0/2 ⴙ 3 ⴙ 1 ⴙ 3)/10ⴙ "days"); 9. } 10. }
Output Recommended rest: 1.05 days
Discussion Notice that all output is accomplished with one statement using the string concatenation operator. The expression on line 8 is mixed. The division 7.0 / 2 is computed using floating-point division and has the value 3.5. The subsequent sum is thus evaluated as 3.5 3.0 1.0 3.0 ( 10.5). Finally, the floating-point division 10.5 / 10 gives the value 1.05. Again, this final division is floating-point division because the numerator is a double.
2.5 IN CONCLUSION This chapter presents the basics of screen output as well as a discussion of data types and expressions. Using the methods of the chapter, you can write programs that print virtually any text on the screen as well as compute all types of arithmetic and logical expressions. On the other hand, the programs of this chapter do lack a certain flexibility: all data are “hardwired” into these programs, and no program accepts input from a user. For example, the program of Example 2.10 that determines whether or not 1800 is a leap year cannot do the same for 1984 or 2968 without our rewriting and recompiling the program. In Chapter 3 you will learn how to accept data from outside an application as well as how to store that data in the computer’s memory and retrieve it for later use.
Just the Facts • • • •
Single-line comments in Java begin with // and continue to the end of the line. Multi-line comments in Java begin with /* and end with */. Comments may be placed anywhere within a program. For the present, applications have the following format: public class ClassName { public static void main(String[] args) { //Java statements go here } }
where ClassName is a valid Java identifier chosen by the programmer. The class must be saved in a file ClassName.java. • A block is a group of statements enclosed in curly braces. • System.out.println(…) is used to display data followed by a newline character. • System.out.print(…) is used to display data without a newline character.
sim23356_ch02.indd 50
12/15/08 6:27:57 PM
Chapter 2
Expressions and Data Types
51
• A string literal consists of text enclosed by quotation marks. A string literal must be contained on a single line. • If both operands A and B are strings, then the expression A B evaluates to another string, which is the concatenation (joining together) of A and B. If only one operand is a string, then the other operand is first cast to a string and the value of the expression is the concatenation of two strings. • A data type is a set of values together with an associated collection of operators for manipulating those values. • Java data types include int, char, double, and boolean. • Type int includes integer values and operators , –, *, /, and %. • Integer division discards the remainder. • The modulus operator % gives the remainder of an integer division. The sign of a % b is the same as the sign of a. • Type double includes decimal numbers and the operators , –, *, and /. The modulus operator is available but rarely used. • Type char includes all Unicode characters. Java stores character data using 2 bytes, that is, 16 bits. • ASCII code numbers and Unicode values coincide. Unicode is a superset of ASCII. • Type boolean includes just two values, true and false. • Boolean operators are && (and), || (or), and !(not). • The relational operators , , , , , and ! return boolean values. • The order of operations is based on operator precedence. (See the precedence chart in this chapter.) Parentheses override precedence. • Boolean expressions are evaluated left to right until the value of the expression is determined. This is called short circuit evaluation. • Data of different types can be combined in a single expression. Smaller data types are promoted to larger data types. The hierarchy of data types from smallest to largest is char, int, double.
Bug Extermination As soon as we started programming, we found to our surprise that it wasn’t as easy to get programs right as we had thought. Debugging had to be discovered. I can remember the exact instant when I realized that a large part of my life from then on was going to be spent finding mistakes in my own programs. —Maurice V. Wilkes, British computer scientist, 1949
Initial versions of almost every program commonly contain errors or bugs. There are three categories of errors: 1. Compilation errors 2. Runtime errors 3. Logical errors A compilation error occurs when a program violates one of the rules of Java, such as the omission of a semicolon, a string’s quotation mark, or a closing curly brace. The
sim23356_ch02.indd 51
12/15/08 6:27:58 PM
52
Part 1
The Fundamental Tools
compiler flags the error and tells you where the error occurs. A program must be free of such errors before it can be translated into bytecode. As the name suggests, a runtime error occurs during program execution. A runtime error can occur when the program attempts some invalid operation such as division by zero. A runtime error results in program termination. Even if the Java compiler detects no errors and a program runs to completion, a program may not do what it is supposed to do. For example, a program that converts degrees Fahrenheit to degrees Celsius using the erroneous expression (1)
(5 / 9)(F 32), where F represents a Fahrenheit temperature;
rather than (2)
(5.0 / 9.0)(F 32)
may compile. However, because (5 / 9) is evaluated using integer division, the result of expression (1) is always 0. The compiler may “approve” the program but a bug obviously exists. Such a program contains a logical error. Uncovering logical errors can be difficult and time consuming. One primitive, yet effective, method for finding bugs is to trace the program with paper and pencil, performing each of the steps that the computer performs. Other methods include generating additional output or using a tool called the debugger. Because our programs, thus far, are quite simple, most of the bugs that you will encounter will be syntax errors. Here are some common sources of errors: • Using an illegal name. Remember the rules for forming a valid Java identifier. • Omitting the parentheses with the empty println() method. Use println() not println; • Using the wrong case. Java is case sensitive. Public and public are not interchangeable. • Omitting a quotation mark for a string literal. • Stretching a string literal over two lines. • Forgetting to close a multi-line comment. • Using a quotation mark within a string. (Use \") • Using print when you intend to use println. • Omitting the semicolon at the end of a statement. • Using integer division when floating-point division is required. • Using double quotation marks instead of single quotation marks to denote a character. • Errors with operator precedence. When in doubt, use parentheses to ensure that the expression you type does the computation you intend it to do. Even when not in doubt, it is good style to fully parenthesize expressions. • Using when you mean . (In Chapter 3, you will see that the equals sign has its own meaning.) • Using incompatible types with an operator. For example, the expressions (3 true), (3 true), and (4 && true) all result in syntax errors. To check whether 3 4 7, you must use (3 4) && (4 7). The expression 3 4 7 generates a syntax error because (3 4) is a boolean expression and 7 is an integer. • Using // in the middle of an instruction, effectively hiding the remainder of the instruction from the compiler.
sim23356_ch02.indd 52
12/15/08 6:27:59 PM
Chapter 2
Expressions and Data Types
53
EXERCISES LEARN THE LINGO Test your knowledge of the chapter’s vocabulary by completing the following crossword puzzle. 1
2
4
5
3
6
7
8
9
10 11
12
13 14
15 16 17
18
19
20
21
22 23 24 25
26
27
28 29 30
31
32
Across 2 Adds clarity to a program 4 4 in 52E4 6 Used for string concatenation 11 One-byte character code 15 Convert from one type to another 18 Java programs may consist of several _____ 19 Character set with thousands of characters 21 5 * 4 / 3 (word) 22 \t 26 Statement terminator 28 ! has ____ precedence among boolean operators 30 5 * (4 / 3) (word) 31 A string literal must be contained on (two words) 32 The word public is a _____
sim23356_ch02.indd 53
Down 1 22 % 7 (word) 3 ! 5 Built one of the first computers 7 Add to print to get a new line 8 Method of evaluating boolean expressions 9 Decimal data type 10 A program begins execution here 12 The name of a class must be a valid Java ____ 13 Data type of 'X' 14 A group of statements enclosed by curly braces 16 && 17 Associative rule for 20 Separates System from out 23 To group operations 24 Computes the remainder 25 Symbol for multiplication 27 || 29 6 / 10 31 Boolean operator with lowest precedence
12/15/08 6:27:59 PM
54
Part 1
The Fundamental Tools
SHORT EXERCISES 1. True or False If false, give an explanation. a. Integer and decimal numbers can be mixed in an expression. b. Integers can be added to character data. c. Boolean data can be cast to integer data. d. The relational operators cannot be used with character data. e. If only one decimal number is used with the / (division) operator, the result is an integer. f. It makes no difference whether one uses 5 or 5.0 in a numerical expression. g. The decimal form of 23.00E6 is 2300.00. h. The argument to println must be a string. i. Two boolean expressions may be compared using . j. The plus operator may be used with two strings. 2. Playing Compiler Evaluate each of the following expressions or determine that the expression is ill formed. a. 3 4.5 * 2 27 / 8 b. true || false && 3 4 || !(5 7) c. true || (3 5 && 6 2) d. !true 'A' e. 7 % 4 3 2 / 6 * 'Z' f. 'D' 1 'M' % 2 / 3 g. 5.0 / 3 3 / 3 h. 53 % 21 45 / 18 i. (4 6) || true && false || false && (2 3) j. 7 (3 8 * 6 3) (2 5 * 2) 3. Playing Compiler Determine which of the following Java statements/segments are incorrect. If a statement is correct, give the output. If incorrect, explain why. a. System.out.print ("May 13, 1988 fell on day number "); b. System.out.println( ((13 (13 * 3 1) / 5 1988 % 100 1988 % 100 / 4 1988 / 400 2 * (1988 / 100)) % 7 7) % 7 ); c. System.out.print ("Check out this line "); d. System.out.println( "//hello there " '9' 7 ); e. System.out.print( 'H' 'I' " is " 1 "more example"); f. System.out.print( 'H' 6.5 'I' " is " 1 "more example"); g. System.out.print("Print both of us", "Me too"); h. System.out.print( "Reverse " 'I' 'T' ); i. System.out.print("No! Here is" 1 "more example"); j. System.out.println ("Here is " 10*10)) // that’s 100 ; k. System.out.println("Not x is " true); // that’s true. l. System.out.print(); m. System.out.println; n. System.out.print("How about this one" '?' 'Huh? ' );
sim23356_ch02.indd 54
12/15/08 6:27:59 PM
Chapter 2
Expressions and Data Types
55
4. Playing Compiler Find and correct the errors in the following program: public class LeapYear; { public static void main(String args) { System.out.print("The year 2300 is a leap year? " "True or false: "); // (divisible by 4 and not by 100) or (divisible by 400) // System.out.println( 2300 % 4 0 && 1800 % 100 ! 0 || 1800 % 400 0); }
5. Parentheses and Operator Precedence Fully parenthesize each of the following expressions to reflect operator precedence. a. 2 3 4 5 b. 3 * 4 5 / 6 7 c. 2 3 * 4 * 5 d. 9 % 2 / 2 * 3 e. 7 6 * 4 % 2 3 * 5 f. true || false || true && !true 6. Boolean Expressions Compute the value of each of the following boolean expressions. Recall that Java uses short circuit evaluation. For each expression determine how much of the expression Java must evaluate to determine a value. a. true && false &&true || true b. true || true && true && false c. (true && false) || (true && ! false) || (false && !false) d. (2 3) || (5 2) && !(4 4) || 9 ! 4 e. 6 9 || 5 6 && 8 4 || 4 3 7. Boolean Expressions Write a Java boolean expression that models each of the following circuit diagrams. See Example 2.9. a. !X Y X A
B !X
!Y
!Y !X
b.
X
Y
!Y
A
B X !X
!Y
8. Playing Compiler Determine which of the following expressions are valid. For each valid expression give the data type of the resulting value. a. 27 / 13 4 b. 27 / 13 4.0 c. 42.7 % 3 18 d. (3 4) && 5 / 8
sim23356_ch02.indd 55
12/15/08 6:28:00 PM
56
Part 1
The Fundamental Tools
e. f. g. h. i. j. k.
23 / 5 23 / 5.0 2.0 'a' 2 'a' 'a' 'b' 'a' / 'b' 'a' && !'b' (double)'a' / 'b'
9. DeMorgan’s Law DeMorgan’s Laws for boolean expressions state that !(a && b) is equivalent to !a || ! b, and !(a || b) is equivalent !a && ! b
Use DeMorgan’s Laws to simplify the following boolean expressions: a. !(a || !b) b. !(!a && !b) c. !(!a || !b) d. ! ((a &&b) || (!a && !b)) 10. What’s the Output? Determine the output of the following program public class Memory { public static void main(String[] args) { System.out.print ("There once was a girl named Elaine\n"); System.out.print ("With a microchip lodged in her brain\n"); System.out.print ("\tHer friends were amazed\n"); System.out.print ("\tBedazzled and dazed\n"); System.out.print ("By the facts that Elaine could retain\n"); } }
11. What’s the Output? Determine the values of each of the following Java expressions: a. 7 / 3 * 2 b. 7 / (3 * 2) c. 7.0 / 3 * 2 d. 7 / 3 * 2.0 e. 7 / (3 * 2.0) f. 7.0 / 3.0 * 2.0 g. (7 / 3) * 2 h. (7.0 / 3) * 2 12. Comments Debugging a program can be a long and intricate process. Can you think of how you might use Java comments as an aid to debugging? What are some other ways that you might use Java comments?
PROGRAMMING EXERCISES 1. Celsius to Fahrenheit The temperature F in Fahrenheit equals (9 / 5)C 32 where C is the Celsius temperature. Write a program that computes and displays the temperatures in Fahrenheit for Celsius values 5, 0, 12, 68, 22.7, 100, and 6.
sim23356_ch02.indd 56
12/15/08 6:28:00 PM
Chapter 2
Expressions and Data Types
57
2. Uptime The uptime command of the UNIX operating system displays the number of days, hours, and minutes since the operating system was last started. For example, the UNIX command uptime might return the string Up 53 days 12:39 Write a program that converts the 53 days, 12 hours, and 39 seconds to the number of seconds that have elapsed since the operating system was last started. 3. Java Competency The average person needs approximately four million three hundred and fifty thousand seconds of study and experience to qualify as a competent Java programmer. Write a program that calculates and prints the number of days, hours, minutes, and seconds necessary for Java competency. 4. Logical Calculations Silly Sammy studies when both Serious Stuart and Studious Selma study, or when neither studies. Selma studies every day except Sunday. Stuart studies every day except Saturday. Write a program that determines, for each day of the week, whether or not Silly Sammy studies. 5. Baseball Expenses A baseball game has nine innings. Freddie Fanatic likes to buy a beer before every odd-numbered inning, nachos before every even-numbered inning, and a scorecard when he first arrives for batting practice before the game begins. Beer costs $6, nachos $4, and a scorecard is $3. Write a program that prints a summary of the items that Freddie buys at the ballpark. Your program should display the name each item, the number of each item, the total cost of each item, and Freddie’s total expenditures. 6. Pictures Write a program that prints the triangle: * * * * * *
* * * * *
* * * * * * * * * *
7. More Pictures Write a program that prints a triangle with your initials somewhere in the middle: * * * * * * S * * R * * * * * * *
8. Your Own Art Write a program that prints your own version of a smiley face.
sim23356_ch02.indd 57
12/15/08 6:28:01 PM
58
Part 1
The Fundamental Tools
9. Your Own Header Write a program that displays a box containing a line of text. Here is an example. Try to make yours look better! * * * * *
Abra Varcolph and Hasim Sonsoni
* * * * *
10. ASCII Name Write a program that prints the letters of your name followed by the ASCII value of each letter. For example: K 75 r 114 a 97 m 109 e 101 r 114
THE BIGGER PICTURE 1. BINARY ENCODING I—ASCII ENCODING
THE BIGGER PICTURE
Decimal numbers are constructed from the digits 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 but binary numbers contain only digits 0 and 1. The digits making up a binary number are called bits (short for binary digits). For example, 010110 is a binary number. Although there are ten different single-digit decimal numbers (0, 1, 2, 3, 4, 5, 6, 7, 8, 9), there are just two single-bit binary numbers: 0 and 1. Similarly, there are ninety decimal numbers with two digits (10, 11, 12 . . , and 99) but merely four binary numbers with two bits: 00, 01, 10, and 11. With three bits, there are just eight different binary numbers: 000, 001,
sim23356_ch02.indd 58
010, 011, 100, 101, 110, and 111.
Exercises 1. How many different binary numbers are there with 4 bits? 10 bits? n bits? 2. How many different characters are included in the ASCII coding scheme? Although each ASCII code number uses just 7 bits, for practical reasons having to do with hardware, the number is stored using 8 bits (one byte) with the leftmost bit always set to 0. For example, 01111111 and 01101010 require one byte of memory and have the leftmost bit set to 0. 3. Many electronic devices, such as calculators and digital clocks, display no symbols other than the digits 0 through 9. With only ten possible symbols, the 7-bit ASCII code is overkill. We can use fewer than 7 bits per digit. How many bits can be used to encode a digit in a calculator or clock? Using this number of
12/15/08 6:28:01 PM
Chapter 2
Expressions and Data Types
59
bits per digit, how many digits can be stored in one byte? This type of encoding is called BCD, or binary coded decimal, and it is twice as compact as ASCII encoding. 4. How many different characters can be represented using the 16-bit Unicode system? Explain your answer. 5. Considering Hebrew, Arabic, Cyrillic, Greek, Sanskrit, and Kanji symbols, conjecture whether the number of Unicode values is reasonably large enough to include all the characters that humans use for written communication. Can you think of any reasons for converting to a 64-bit character code? Like the characters 'A', 'B', 'C', and so on, the digit characters '0' through '9' also have ASCII codes. The ASCII code for zero is 48 (decimal) or 0110000 (binary). The ASCII codes for the other digits increase in order, 49 for '1', 50 for '2', and so on. 6. Determine the ASCII code for the four-digit string "1026". Use one byte for each digit. 7. Determine the binary equivalent of the decimal number 1026. 8. What are the advantages and disadvantages of storing a string of digits using ASCII rather than its binary number encoding? 9. How do you think digits in a Java program are stored? For example, are digits that are part of a class name stored in the same way as the digits that comprise an integer in an arithmetic expression? Use the following example to explain your answer. What are the differences between the internal representations of 23748 in the following three lines of Java code? public class MyClass23478 { System.out.println ( "In 23478 pennies there are: "); System.out.println( 23478 12); }
2. BINARY ENCODING II—DECIMAL ENCODING
Exercises 1. 2. 3. 4. 5.
sim23356_ch02.indd 59
Give the decimal equivalents of 1011100, 1111111, and 0000000001011100. Which characters are encoded by the ASCII and Unicode values in exercise 1? Determine the 7-bit binary equivalent of 64. What is the 16-bit binary equivalent of 10,000? Repeat Programming Exercise 10 and include a third column with the binary equivalent of each integer in the third column. For now, you’ll have to calculate
THE BIGGER PICTURE
As you know, the digits of a decimal number X represent the number of ones, tens, hundreds, thousands, and so on in X. For example, 358 consists of 8 ones, 5 tens and 3 hundreds. Similarly, the bits of a binary number tell us the number of ones, twos, fours, eights, sixteens, and so on. For example, the binary number 1101 has 1 one, 0 twos, 1 four, and 1 eight. Furthermore, each binary number can be considered a unique decimal number and vice versa. For example, the binary number 1010001 is equivalent to the decimal number 81: 1 1 0 2 0 4 0 8 1 16 0 32 1 64 81, which incidentally is also the ASCII code for the letter 'Q'. The Unicode for the letter 'Q' is 0000000001010001—16 bits with the leftmost 8 bits set to 0.
12/15/08 6:28:01 PM
60
Part 1
The Fundamental Tools
the binary numbers by hand and use the println method to display them. Typical output is: R a l p h
82 97 108 112 104
1010010 1100001 1101100 1110000 1101000
3. BOOLEAN TYPES Boolean values and operators have an unusual algebra that resembles the algebra of integers with || instead of , and && instead of . For example, the distributive law states that if a, b, and c are integers, then a (b c) (a b) (a c) Similarly, if a, b, and c are type boolean, then a && (b || c) (a && b) || (a && c)
Exercises For each problem, if true, explain why, and if false, give a counterexample. 1. Is it true that if a, b, and c are boolean then a || (b && c) is equivalent to (a || b) && (a || c)?
2. Is it true that if a, b, and c are integers then a (b c) is equivalent to (a b) (a c)?
THE BIGGER PICTURE
3. The exclusive-or (XOR) operation on two Boolean operands is defined to be true whenever exactly one of the two operands is true. Write a Java boolean expression that calculates the exclusive-or of two boolean operands x and y.
sim23356_ch02.indd 60
12/15/08 6:28:02 PM
CHAPTER
3
Variables and Assignment “One man’s constant is another man’s variable” —Alan Perlis
Objectives The objectives of Chapter 3 include an understanding of the concept of a variable as a named memory location, variable declarations and initializations, assignment and Java’s assignment operators: , , , *, /, and %, the use of a Scanner object for interactive input, the advantages of using final variables, type compatibility and casting, and the increment and decrement operators.
3.1 INTRODUCTION The programs of Chapter 2 perform tasks that can just as easily be accomplished with a no-frills calculator. Indeed, most calculators provide memory and allow you to store and retrieve data. In this chapter, we explain how data can be stored by a program and later retrieved for output or further computation. Specifically, we address three questions: 1. How does a program obtain storage for data? 2. How does a program store data? 3. How does a program use stored data? We begin with the concept of a variable.
3.2 VARIABLES A variable is a named memory location capable of storing data of a specified type. You might visualize a variable as a labeled box, container, or memory cell capable of holding a single value of a specific data type. Figure 3.1 illustrates three variables. Figure 3.1a shows a variable named quantity that holds the integer 7; Figure 3.1b shows another named cost with value 250.75, a double; and Figure 3.1c shows a variable, quality, that contains a single character, ‘A’. 61
sim23356_ch03.indd 61
12/15/08 6:31:05 PM
62
Part 1
The Fundamental Tools
25
250.75
‘A’
Quantity
Cost
Quality
(a)
(b)
(c)
FIGURE 3.1 A visualization of three variables You can store a value in a variable, change the contents of a variable, and also retrieve and use a stored value. The program of the following example utilizes five different variables. Read through the program and the subsequent explanation. For now, do not concern yourself with syntax or minute details. We will come back to those issues. Try to understand the role that variables play in the application.
EXAMPLE 3.1
We begin with an age-old nursery rhyme/riddle: As I was going to St. Ives, I met a man with seven wives, Each wife had seven sacks, Each sack had seven cats, Each cat had seven kits: Kits, cats, sacks, and wives, How many were there going to St. Ives? Well, technically, the answer to the question is “one.” Only the narrator was going to St. Ives. The others presumably were traveling in another direction.
Problem Statement Write a program that calculates the number of people, sacks, cats, and kits that the narrator of this “polygamous poem” encountered on his/her journey. Java Solution 1. // How many people, sacks, cats and kits were encountered on the road to St. Ives 2. public class StIves 3. { 4. public static void main (String[] args) 5. { 6. int wives 7; // a variable named wives that holds the value 7 7. int sacks; // holds the number of sacks 8. int cats; // holds the number of cats 9. int kits; // number of kits 10. int total; // sum of man, wives, sacks, cats and kits
sim23356_ch03.indd 62
11. 12. 13. 14.
sacks 7*wives; cats 7*sacks; kits 7*cats; total 1wivessackscatskits;
15. 16. 17. 18. 19. 20. } 21. }
System.out.println("Wives: " wives); System.out.println("Sacks: " sacks); System.out.println("Cats: " cats); System.out.println("Kits: " kits); System.out.println("Man, wives, sack, cats and kits: " total);
// each wife had seven sacks // each sack had seven cats // each cat had seven kits // "1" counts the man
12/15/08 6:31:06 PM
Chapter 3
63
Variables and Assignment
Output Wives: 7 Sacks: 49 Cats: 343 Kits: 2401 Man, wives, sacks, cats and kits: 2801
Discussion We begin our dissection of the program at line 6. Line 6: int wives 7;
The statement on line 6 is a variable declaration. The declaration accomplishes three tasks. 1. It instructs the compiler to set aside or allocate enough memory to hold one integer (int). 2. It labels the allocated memory location with the name wives. The program can use the name wives to refer to this memory location. 3. It stores the number 7 in this memory location.
Wives (int)
Wives is a variable, a named memory location that can store a single number of type int.
FIGURE 3.2 The
Currently, this memory cell holds the integer 7. See Figure 3.2. In Chapter 1, you learned that every memory cell has a unique numerical address. Conveniently, a program refers to a variable by its name and not by its address. In fact, Java hides the address of a variable from the programmer. Figure 3.3 steps through the remainder of the program.
variable wives
wives sacks
cats
kits
total
7
Lines 7–10: int sacks; int cats; int kits; int total;
Here we have four additional variable declarations. Each variable can hold one integer (int). However, in contrast to wives, no values are assigned to these variables. The variables are uninitialized. The uninitialized variables hold no meaningful values at this point, and we denote an uninitialized variable with an empty box.
7
Line 11: sacks 7 * wives ; 7
49
7
49
343
7
49
343
2401
7
49
343
2401
The value stored in the variable wives (7) is used to compute the number of sacks. The result (49) is stored in the variable sacks. Line 12: cats 7 * sacks; The value of sacks (49) is used to compute the number of cats. This product (343) is saved in the variable cats. Line 13: kits 7 * cats;
Similarly, the value 343 stored in cats is used to calculate the number of kits. The number of kits is 2401 and that is the value placed in variable kits. Line 14: total 1 wives sacks cats kits; 2801
The sum of the values stored in wives, sacks, cats, and kits plus 1 (for the narrator) is computed and stored in total. Notice that it is unnecessary to re-compute the numbers of sacks, cats, and kits because these values are saved in variables. Lines 15–19:
The numbers stored in wives, sacks, cats, kits, and total are displayed. FIGURE 3.3 A line-by-line analysis of StIves
sim23356_ch03.indd 63
12/15/08 6:31:08 PM
64
Part 1
The Fundamental Tools
The simple program of Example 3.1 illustrates much of what you need to know about variables. We now fill in a few details and expand the explanation.
3.3 VARIABLE DECLARATIONS: HOW A PROGRAM OBTAINS STORAGE FOR DATA Lines 6 through 10 of Example 3.1 illustrate an important rule. A variable must be declared before it can be used. A variable declaration specifies • the type of data that the variable can hold, for example int or double, and • the name of the variable. The syntax of a variable declaration is: Type name1, name2, name3,...;
where Type is a data type (int, double, char, boolean) and nameX is a valid Java identifier. As the syntax indicates, several variables of the same type may be declared with a single statement. Some sample variable declarations are: int cats;
// cats can store a single integer (int)
double radius, area, circumference;
// commas separating the names are mandatory // the three variables separated by commas are all double // done can hold either true or false
boolean done;
When naming a variable, you should choose a name that is meaningful. For example, the names used in Example 3.1 (wives, sacks, cats, kits, and total) are far more descriptive than a, b, c, d, and e or even the abbreviations w, s, c, k, and t. It is common practice to begin the name of a variable with a lowercase letter and use an upper case letter to begin any subsequent “words” of a variable name. For example, the names myVariable, numberOfPeople, and hokusPokus all follow this convention. As noted in Chapter 2, this style is called camelCase, for the uppercase “humps” in the intermediate words. Although a variable can store an integer, a floating-point number, a character, or a boolean value, there are notable differences among the storage requirements for these different data types.
3.3.1 Integers The declaration int total;
instructs the compiler to allocate enough memory to store one number of type int. A value of type int requires 32 bits or four bytes of memory. With 32 bits of storage, a variable of type int can hold a value in the range 2,147,483,468 to 2,147,483,467.
sim23356_ch03.indd 64
12/15/08 6:31:09 PM
Chapter 3
Variables and Assignment
65
In addition to type int, Java provides three other integer data types: byte, short, and long. The storage requirements and the range of values for all integer types are as follows: byte short int long
8 bits (1 byte) 16 bits (2 bytes) 32 bits (4 bytes) 64 bits (8 bytes)
27 to 27 1 (128 to 127) 215 to 215 1 (32,768 to 32,767) 231 to 231 1 (2,147,483,468 to 2,147,483,467) 263 to 263 1 (922,337,203,685,475,808 to 922,337,203,685,475,807)
The declaration long bigNumber;
allocates 8 bytes of memory for bigNumber and the declaration short smallNumber;
sets aside just two bytes for smallNumber. Only numbers between 32,768 and 32,767 inclusive can be stored in smallNumber; 1,000,000, for example, doesn’t fit.
3.3.2 Floating-Point Numbers Type double is used for decimal numbers. In addition to type double, Java provides a second, smaller type, float, that also denotes floating-point or decimal numbers. The storage requirements and the range of values for variables of these decimal types are: 32 bits (4 bytes) double 64 bits (8 bytes) float
3.4e38 to 3.4e38 (with 6 to 7 significant digits) 1.7e308 to 1.7e308 (with 14 to 15 significant digits)
3.3.3 Characters Variables of type char require 16 bits or 2 bytes of memory. A character is stored as a 16-bit Unicode integer.
3.3.4 Boolean values The boolean type has just two values: true and false. A boolean value requires just a single bit of storage.
3.4 HOW A PROGRAM STORES DATA: INITIALIZATION AND ASSIGNMENT A variable can be given a value via an initialization statement or an assignment statement. We begin with initialization.
3.4.1 Initialization A variable may be declared and given an initial value with a single initialization statement. The following statements declare and also initialize several different variables: double pi 3.14159; int number 10, sum 0, total 125; boolean done true; char firstLetter ‘A’, lastLetter ‘Z’;
sim23356_ch03.indd 65
12/15/08 6:31:09 PM
66
Part 1
The Fundamental Tools
This technique of declaration together with initialization appears on line 6 of Example 3.1: int wives 7;
Be careful, however. The following initialization causes a syntax error: short smallNumber 100000;
Recall that a variable of type short can store a 16-bit number, which is a number between 32,768 and 32,767. The integer 100,000 exceeds the capacity of smallNumber. Be cautious when using floating-point numbers. The data type of a floating-point constant is double. This means that a floating-point constant requires eight bytes, or 64 bits of storage. Consequently, the seemingly innocuous declaration float decimal 3.14; // The data type of 3.14 is double; decimal is type float
generates a syntax error because the data type of 3.14 is double but the variable decimal is type float. A float variable has just four bytes and is not large enough to hold a value of type double, which demands eight bytes. To be safe, you might declare all floating-point variables as double.
3.4.2 Assignment Values may be stored in a previously declared variable using an assignment statement. An assignment statement has the following format: variable expression;
where variable is a declared variable and expression is a valid Java expression. The symbol is the assignment operator. Notice that the left-hand side of an assignment statement consists of a single variable. Assignment is accomplished in two steps: 1. expression is evaluated. 2. The value of expression is stored in variable. That is, the value of variable is changed. For example, consider the following declaration and assignment: int sum; sum 1 2 3 4 5;
// a variable declaration: sum is type int. // assignment: sum gets the value 15.
First, the expression 1 2 3 4 5 is evaluated (15); then 15 is assigned to (stored in) the variable sum. An assignment statement is also an expression. So, like any expression, an assignment expression has a value. The value of the assignment expression is the value computed on the right-hand side of the operator. For example, the assignment expression number 1 2 3 4 5;
not only assigns 15 to number but also evaluates to 15. Usually, the value of an assignment is discarded, but sometimes, the value can be used. For example, in the following output statement, System.out.println(number 1 2 3 4 5);
the value 15 is assigned to variable number and then is passed as an argument to System.out.println(...), which prints 15.
sim23356_ch03.indd 66
12/15/08 6:31:10 PM
Chapter 3
Variables and Assignment
67
Conveniently, using the value of an assignment statement allows assignments to be chained. For example, int number1, number2, number3; number1 number2 number3 2 4 6 8;
Here, the sum on the right is evaluated first (it’s 20); next, 20 is assigned to number3, then to number2, and finally to number1. As this segment illustrates, assignments are performed right to left. That is, the assignment operator () is right associative. Assignments can be chained, but initializations cannot. This is because an assignment statement is also an expression but an initialization statement is not. For example, the statement int x y z 3; // ERROR!
causes a compile time error. Correct initialization can be accomplished with int z 3, y 3, x 3;
or int z 3, y z, x y; // note the left to right execution
The syntax of initialization can be confusing. For example, what do you think the following statement accomplishes? int x, y, z 0;
You might guess that all three variables x, y, and z are set to zero. In fact, the statement creates three variables: x and y are uninitialized, and only z is initialized to zero. To initialize all three variables, use the statement: int x 0, y 0, z 0; // initialization
The values of x, y, and z can subsequently be changed to 3 using the chained assignment statement: x y z 3 ; // assignment
3.5 HOW A PROGRAM USES STORED DATA Once a variable has been assigned a value, you can use the variable’s name in an expression, provided that the data type of the variable makes sense in the expression. For example, consider the following code snippet: int number1 10; int number2 20; int sum; sum 5 * number1 2 * number2;
The computation on the last line uses the value 10 for number1 and 20 for number2. Consequently, sum is assigned the value 90. However, the following group of statements is not acceptable: boolean bool true; int number 10; int sum; sum number bool ; // ILLEGAL!
sim23356_ch03.indd 67
12/15/08 6:31:10 PM
68
Part 1
The Fundamental Tools
Here, the expression number bool is illegal because the data type of bool is boolean, and addition involving boolean data is not a legal operation. The value stored in a variable may be changed as Example 3.2 illustrates.
EXAMPLE 3.2 Problem Statement Write a program that exchanges the values in two variables. Java Solution 1. // switches the values stored in two variables 2. public class Swap 3. { 4. public static void main (String[] args) 5. { 6. int a 7; 7. int b 100; 8. int temp; // uninitialized 9. 10. 11.
System.out.print("Before -- "); System.out.print("a: " a); System.out.println(", b: " b);
12. 13. 14.
temp a; // store the current value of a in temp a b; // store the value of b in a b temp; // store the original value of a in b
15. System.out.print("After -- "); 16. System.out.print("a: " a); 17. System.out.println(", b: " b); 18. } 20. }
Output Before -- a: 7, b: 100 After -- a: 100, b: 7
Discussion Figure 3.4 steps through the program. a
b
7
100
temp
Lines 6–8: int a 7; int b 100; int temp;
Three variables are declared; two are initialized. Lines 9–11: Display the text Before -- a: 7, b: 100 Line 12: temp a; 7
100
7
Line 12 is an assignment statement. The variable temp gets the value stored in the variable a.
7 100
100
7
This assignment places the value of b in a. Notice that the original value of a is saved in temp.
100
100 7
7
Line 13: a b;
Line 14: b temp;
This assignment stores the value of temp (the original value of a) in variable b. Lines 15–17: Display the text After -- a: 100, b: 7
FIGURE 3.4 Swapping the values in two variables
sim23356_ch03.indd 68
12/15/08 6:31:11 PM
Chapter 3
69
Variables and Assignment
3.6 OBTAINING DATA FROM OUTSIDE A PROGRAM In most cases, the data that a program uses come from outside the program, perhaps from a file or from a user who interacts with the program. The following application demonstrates one very simple mechanism available for interactive input, a Scanner object.
According to the Farmer’s Almanac, you can estimate air temperature by counting the number of times per minute that a cricket chirps. To compute the air temperature (Celsius), divide the number of chirps/minute by 6.6 and add 4.
EXAMPLE 3.3
Problem Statement Write an application that calculates the air temperature given the number of cricket chirps per minute. A user supplies the number of chirps per minute. Java Solution 1. 2. 3. 4. 5. 6. 7. 8. 9.
// calculates the air temperature (Celsius) from cricket chirps/minute import java.util.*; public class Cricket { public static void main (String[] args) { int chirps; // chirps per minute double temperature; // Celsius Scanner input new Scanner(System.in);
10. 11. 12. 13. 14. } 15. }
System.out.print("Enter the number of chirps/minute: "); chirps input.nextInt(); temperature chirps/6.6 4; System.out.println("The temperature is "temperature"C");
Output Enter the number of chirps/minute: 99 The temperature is 19.0C
Discussion We begin our explanation with line 7. Line 7: int chirps;
On line 7, we declare an integer variable, chirps, that is intended to hold the number of chirps per minute. Line 8: double temperature;
The statement on line 8 is also a variable declaration. The variable temperature holds the air temperature. Because the computation of the temperature requires division by 6.6, temperature is declared as double. Line 9: Scanner input new Scanner(System.in) ;
The statement on line 9 is something that you have not previously seen. The name input refers to a “Scanner object.” Objects and object-oriented programming are discussed in later chapters. For the present, we say that a Scanner object is a mechanism or “black box” used for reading data interactively from the keyboard.
sim23356_ch03.indd 69
12/15/08 6:31:12 PM
70
Part 1
The Fundamental Tools
This particular Scanner object has the name input. The choice of the name input is arbitrary and could just as well be any valid Java identifier such as keyboard, console, or even chirpReader. The somewhat mysterious statement on line 9 should be included in every program that uses a Scanner object for interactive input. Line 10: System.out.print("Enter the number of chirps/minute: ");
Line 10 is an output statement that prompts the user for data. A “user friendly” program should always supply a prompt when interactive input is required. It is also a good idea to remind the user of the type of units that are expected, that is, chirps/minute rather than chirps/second. Line 11: chirps input.nextInt();
The statement on line 11 demonstrates the Scanner object in action. The Scanner object, input, accepts or reads one integer from the keyboard. In fact, the program pauses indefinitely until the user types an integer and presses the Enter key. Once the user supplies an integer, that number is assigned to the variable chirps. The Scanner object, input, expects an integer (input.nextInt()). If the user enters a decimal number or a character other than whitespace (spaces, tabs, or new lines), a runtime error terminates the execution of the program and the system issues an error message. Because the Scanner object skips leading whitespace, a user can legally enter “ 77”—the spaces are ignored. Line 12: temperature chirps/6.6 4;
The value stored in chirps is used to compute the air temperature. The result of the computation is assigned to the variable temperature. Line 13: System.out.println("The temperature is "temperature"C"); The program displays the value stored in temperature along with some explanatory
text. You’ve probably noticed that we’ve given no explanation of line 2 (import java.util.*). Interactive input is not simple to effect. In fact, there is an enormous amount of code lurking beneath the Scanner. This code is contained in a system package called java.util. A system package is a collection of code available for use in any program. The statement import java.util.* instructs the compiler to include the java.util package in the program, and with it, the code that implements a Scanner. This statement is necessary whenever a program uses a Scanner object for interactive input. Notice that this statement, called an import statement, appears outside the class declaration.
3.7 A SCANNER OBJECT FOR INTERACTIVE INPUT Before using a Scanner object for input you must: • Include the import statement: import java.util.*; • Declare a Scanner object as Scanner name new Scanner(System.in)
where name is a valid Java identifier such as input or keyboardReader. Once a Scanner has been declared you can use the following methods to read data: • name.nextInt() • name.nextShort()
sim23356_ch03.indd 70
12/15/08 6:31:13 PM
Chapter 3
• • • •
71
Variables and Assignment
name.nextLong() name.nextDouble() name.nextFloat() name.nextBoolean()
where name is the declared name of the Scanner. A Scanner object cannot read data of type char. Other Scanner methods are available, but for now, these six suffice. Like the println() method, which displays text, each of these methods accomplishes a task: each reads one value from the keyboard and supplies or returns that value for further computation. For example, if input is the name of a Scanner object, then the statement int number input.nextInt();
reads one integer from the keyboard and stores that value in the variable number. You do not need to declare a new Scanner object for each data type. An unlimited number of input values of different types can be read using a single Scanner object. The program of Example 3.4 uses a Scanner object to read two double values that are supplied by a user.
Do you get more bite for your buck with a 14-inch pizza or a 10-inch pizza?
EXAMPLE 3.4
Problem Statement Write a program that calculates the price per square inch of a round pizza, given the diameter and price. Java Solution 1. 2. 3. 4. 5. 6. 7.
sim23356_ch03.indd 71
// Calculates the price/sq.in. of a round pizza using area r 2 // Uses the diameter and the price import java.util.*; // to use Scanner public class Pizza { public static void main (String[] args) {
8. 9. 10. 11.
Scanner input new Scanner(System.in); //declare a Scanner double diameter, area, radius; double price; double pricePerSquareInch;
12. 13.
System.out.print("Enter the diameter of the pizza in inches: "); diameter input.nextDouble(); // use Scanner object, read a double
14. 15.
radius diameter/2.0; area 3.14159*radius*radius; //area r 2
16. 17.
System.out.print("Enter the price of the pizza: "); price input.nextDouble(); // use Scanner object, read a double
12/15/08 6:31:14 PM
72
Part 1
The Fundamental Tools
18. 19.
pricePerSquareInch price/area; System.out.println("The price per square inch of a " diameter " inch pizza is $" pricePerSquareInch);
20. } 21. }
Using some real data obtained from a local pizza shop, we ran the program three times.
Output Enter the diameter of the pizza in inches: 10.00 Enter the price of the pizza: 6.50 The price per square inch of a 10.0 inch pizza is $0.0827606403127079 Enter the diameter of the pizza in inches: 12.00 Enter the price of the pizza: 10.50 The price per square inch of a 12.0 inch pizza is $0.09284046188925567 Enter the diameter of the pizza in inches: 14.00 Enter the price of the pizza: 12.50 The price per square inch of a 14.0 inch pizza is $0.08120157016552973
Discussion Lines 3, 8, 13, and 17 contain the necessary statements for interactive input using a Scanner object. The name input (line 8) can be any valid Java identifier such as nextData or priceGrabber. Program output shows that the 14-inch pizza is the most economical, the 10-inch pizza comes in second, and the 12-inch pizza is the most costly.
3.8 FINAL VARIABLES The program of Example 3.4 includes the calculation area 3.14159*radius*radius. // Line 15, Example 3.4
The number 3.14159 is an approximation of what is probably the world’s most famous constant, . Although most people would recognize 3.14159 as “a piece of ,” a statement such as area PI*radius*radius,
adds greater clarity to the application. The following revised version of Example 3.4 replaces 3.14159 with a final variable, PI. A final variable is a variable that is assigned a permanent value. A final variable may be assigned a value just once in any program, and once assigned, the value cannot be altered. Its value is, well, “final.” In Example 3.5, the value 3.14159 is assigned to PI as part of the declaration. It is a good practice to initialize a final variable when it is declared. By convention, names of final variables are comprised of uppercase letters with underscores separating the “words” of a name. For example, PI, TAX_RATE, and FIDDLE_DEE_ DEE adhere to this practice.
sim23356_ch03.indd 72
12/15/08 6:31:15 PM
Chapter 3
73
Variables and Assignment
Problem Statement Write a program that performs the same task as the program of Example 3.4 using a final variable (PI) with value 3.14159.
EXAMPLE 3.5
Java Solution 1. import java.util.*; 2. public class MorePizza 3. { 4. public static void main (String[] args) 5. { 6. 7. 8. 9. 10.
Scanner input new Scanner(System.in); final double PI 3.14159; double diameter, area, radius; double price; double pricePerSquareInch;
11. 12. 13. 14. 15. 16.
System.out.print("Enter the diameter of the pizza in inches: "); diameter input.nextDouble(); //use Scanner object radius diameter/2.0; area PI * radius * radius; System.out.print("Enter the price of the pizza: "); price input.nextDouble();
17. 18.
pricePerSquareInch price/area; System.out.println("The price per square inch of a " diameter " inch pizza is $" pricePerSquareInch);
// declare a Scanner object // PI cannot be changed
19. } 20. }
Discussion The variable PI is declared and initialized on line 7. Because PI is declared as final, its value cannot be changed. PI is a constant. PI is used in the computation on line 14.
A final variable is often called a named constant or simply a constant. Named constants add to the clarity of your programs. Using named constants eliminates “mystery numbers.” In Example 3.5, there is no uncertainty about the number 3.14159; this decimal number represents . Named constants also make your program easier to change. Suppose that, to increase accuracy, you decide to change the approximation of PI from five decimal places to eight. If a program uses the constant PI in several places, you can change all occurrences by altering just one line. Otherwise, you would have to search for each occurrence of 3.14159 and change each, one by one. The use of final variables also prevents the accidental changing of a permanent value. If your code attempts to change the value of a final variable, the compiler complains.
3.9 TYPE COMPATIBILITY AND CASTING In Chapter 2, you saw that before evaluating a binary expression with operands of different data types, Java promotes or casts the operand of the “smaller” data type to the data type of the other operand. For example, the value of the expression 2 3 is 5 (int) but the expression 2 3.0 evaluates to 5.0 (double) because the integer 2 is cast to 2.0 (double) and the subsequent addition is performed on two numbers of type double. Assignment is no different.
sim23356_ch03.indd 73
12/15/08 6:31:16 PM
74
Part 1
The Fundamental Tools
The value of a smaller numerical data type may be assigned to a variable of a larger numerical data type. When you assign a value of a smaller data type to a variable of a larger type, the value of the smaller type is promoted, or cast, to the larger type. The pecking order of the numeric data types from smallest to largest is: • • • • • •
byte short int long float double
Thus, the segment double decimalNumber; decimalNumber 100; // a value of type int is assigned to a variable of type double System.out.println( decimalNumber);
prints 100.0. The value stored in decimalNumber is 100.0, a double, not 100. Before copying a value into decimalNumber, Java casts 100 (int) to 100.0 (double). On the other hand, the following assignment is illegal: int wholeNumber; wholeNumber 37.2;
// cannot assign 37.2 (double) to an integer variable
Java does not automatically cast 37.2 to the integer 37 because the cast results in a loss of precision. However, such an assignment can be accomplished with an explicit cast.
3.9.1 Explicit Casts If value is a number or variable of a numeric data type, then the expression (X )value, where X is a numeric data type, explicitly casts value to type X. For example, the expression (int)3.1459.2 casts a floating-point number to an integer. The value of the expression is the integer 3. Similarly, (float)3.14159 casts 3.14159 from double to float. The following segment demonstrates how you can use an explicit cast (line 3) to assign a value of type double to a variable of type int. 1. 2. 3. 4. 5.
int wholeNumber; double decimalNumber 37.2; wholeNumber (int)decimalNumber; // decimalNumber is explicitly cast to int System.out.println("wholeNumber: " wholeNumber); System.out.println("decimalNumber: " decimalNumber);
When embedded in a complete program, the output of this fragment is: wholeNumber: 37 decimalNumber: 37.2
sim23356_ch03.indd 74
12/15/08 6:31:17 PM
Chapter 3
Variables and Assignment
75
Before decimalNumber is assigned to wholeNumber (line 3), the value stored in decimalNumber (37.2) is explicitly cast to 37 (int), and 37 is stored in wholeNumber. The cast truncates 37.2, that is, the fractional part of 37.2 is removed. No rounding occurs. The cast does not change the value stored in decimalNumber; that value remains 37.2. Likewise, the declaration float pi 3.14159; // cannot assign a double to a float
generates a syntax error because the data type of 3.14159 is double and a value of type double cannot be assigned to a variable declared as float, a smaller type. An explicit cast “down to float” allows the assignment: float pi (float)3.14159;
Coupled with this declaration of pi, the statement float twoPi 2.0 * pi; // double * float results in double
causes an error, but float twoPi 2 * pi;
// int * float results in float
does not. Can you see why? In the first statement, the data type of the expression 2.0 * pi is double and a value of type double cannot be assigned to the variable twoPi, which is declared as float. In the second statement, the data type of 2 * pi is float because the data type of the product of 2 (int) and pi (float) is float, the larger type. The statement float twoPi ((float)2.0) * pi;
accomplishes the same result.
3.9.2 Character and Boolean Data Types Character data may be assigned to a variable of type short, int, long, double, or float. When this is done, the ASCII (or Unicode) value is assigned to the numerical variable. Thus the code fragment double x 'A'; System.out.print(x);
produces the output 65.0
because the ASCII value of 'A' (65) is cast to the double 65.0. Of course, the segment double x 'A'; System.out.print ((char)x);
which casts x down from double to char, changes the output. This revised segment displays the character 'A'. Boolean values cannot be cast to other types, nor can the values of numeric types be cast to boolean. Unlike languages such as C or C, boolean values in Java are not considered integers.
3.9.3 Cast with Caution An explicit cast to a smaller type can produce unexpected results. It may surprise you that the segment byte x (byte)512; System.out.print(x);
sim23356_ch03.indd 75
// explicit cast: int to byte
12/15/08 6:31:17 PM
76
Part 1
The Fundamental Tools
prints 0. As explained in Section 3.3.1, the integer 512 is stored as the four-byte or 32-bit binary number: 00000000 00000000 00000010 00000000.
Because a byte consists of just eight bits, the explicit cast, (byte)512, discards the three leftmost bytes of the binary representation of 512. Only the rightmost byte, 00000000, is stored in x. Consequently, x gets the value 0. In practice, you should avoid casts like the one described above. Such casts can lead to bugs that are often subtle and difficult to uncover.
3.10 A FEW SHORTCUTS As you know, the assignment operator () does not imply mathematical equality. Although a statement such as count count 1;
makes no mathematical sense, it is an acceptable Java statement. Execution of this statement involves the following two actions: 1. count1 is evaluated, and 2. the resulting value is stored in count. Thus, the statement count count 1 adds 1 to the value of count. The statement reads “count is assigned the value count 1” rather than “count equals count 1.” In Example 3.6, the variable cost is adjusted in a similar manner.
EXAMPLE 3.6
At Pepino’s Pizza Parlor, pizzas are $12.00 each. Each additional topping is $1.50. Tax is 5 percent.
Problem Statement Write an application that prompts for the number of pizzas and the number of toppings. The program should calculate the price of the pizza (including sales tax) and print a receipt. Java Solution 1. import java.util.*; 2. public class OrderPizza 3. { 4. public static void main (String[] args) 5. { 6. Scanner input new Scanner(System.in); // declare a Scanner object
sim23356_ch03.indd 76
7. 8. 9. 10.
// some constants final double PRICE_OF_PIZZA 12.00; final double PRICE_OF_TOPPING 1.50; final double TAX_RATE .05;
11. 12.
int numPizza, numTopping; double cost 0.0;
12/15/08 6:31:18 PM
Chapter 3
13. 14. 15. 16.
// determine the number of pizza and adjust the cost System.out.print("Enter the number of pizzas: "); numPizza input.nextInt(); cost cost numPizza * PRICE_OF_PIZZA;
17. 18. 19. 20.
// determine the number of toppings and adjust the cost System.out.print("Enter the total number of toppings: "); numTopping input.nextInt(); cost cost numTopping * PRICE_OF_TOPPING;
21. 22.
// add tax cost cost TAX_RATE * cost;
Variables and Assignment
77
23. System.out.println(); 24. System.out.println("Receipt: "); 25. System.out.println("Number of Pizzas: " numPizza); 26. System.out.println("Number of Toppings: " numTopping); 27. System.out.println("Cost (incl tax): " cost); 28. } 29. }
Output Enter the number of pizzas: 4 Enter the total number of toppings: 6 Receipt: Number of Pizzas: 4 Number of Toppings: 6 Cost (incl tax): 59.85
Discussion On line 12, cost is initialized to 0.0. Subsequently, the value of cost is adjusted three times: on lines 16, 20, and 22. The statement on line 16 adds the cost of the no-topping pizzas to cost. On line 20, the cost of the toppings is added to the current value of cost. Finally, the assignment statement on line 22 adds the tax to the value of cost. Would the application run correctly if cost had been initialized to 0 rather than 0.0? Yes it would, because the declaration on line 12 ensures that the data type of cost is double. Consequently, 0 is automatically cast to double. What do you think would happen if cost had not been initialized at all? If you do not know, try compiling and running the program without initializing cost.
Statements such as those on lines 16, 20, and 22 occur often. As a convenience, Java provides the following shortcut assignment operators:
sim23356_ch03.indd 77
Operator
Shortcut
For
* / %
x 10
x x 10
x 10
x x 10
x * 10
x x * 10
x / 10
x x / 10
x %10
x x % 10
12/15/08 6:31:19 PM
78
Part 1
The Fundamental Tools
With these shortcut assignment operators, the assignment statements on lines 16, 20, and 22 of Example 3.6 can be rewritten respectively as: cost numPizza* PRICE_OF_PIZZA; cost numTopping* PRICE_OF_TOPPING; cost taxRate*cost;
The following example uses the and the % operators.
EXAMPLE 3.7
Here’s a simple trick that may start you on a career as a “math-magician.” Ask an unsuspecting friend to pick a number from 1 to 1000. Now, instruct your friend to divide the secret number by 7 and report the remainder. Then tell him/her to do the same with 11 and finally 13. You can discover your friend’s secret number with the following algorithm: 1. 2. 3. 4. 5.
Multiply the first remainder by the magic multiplier 715. Multiply the second remainder by the magic multiplier 364. Multiply the third remainder by the magic multiplier 924. Add the three products. The secret number is the remainder when the sum is divided by 1001.
Problem Statement Write a program that allows the computer to play the role of math-magician. The program should prompt the user for the appropriate remainders and display the player’s secret number. Java Solution 1. 2. 3. 4. 5. 6. 7.
sim23356_ch03.indd 78
// Determine a number from 1 to 1000 given // the remainders when the number is divided by 7, 11, and 13 import java.util.*; public class MagicalMath { public static void main (String[] args) {
8.
Scanner input new Scanner( System.in);
9. 10. 11. 12. 13.
// constants used in the calculation of the mystery number final int MAGIC_MULTIPLIER1 715; final int MAGIC_MULTIPLIER2 364; final int MAGIC_MULTIPLIER3 924; final int FINAL_DIVISOR 1001;
14. 15.
int mysteryNumber 0; // eventually holds the secret number int remainder;
16.
System.out.println("Think of a number from 1 to 1000");
17. 18. 19.
System.out.print("Divide by 7 and tell me the remainder:"); remainder input.nextInt() ; mysteryNumber remainder * MAGIC_MULTIPLIER1;
20. 21.
System.out.print("Divide by 11 and tell me the remainder:"); remainder input.nextInt() ;
12/15/08 6:31:20 PM
Chapter 3
22. 23. 24. 25.
mysteryNumber remainder* MAGIC_MULTIPLIER2; System.out.print("Divide by 13 and tell me the remainder:"); remainder input.nextInt(); mysteryNumber remainder * MAGIC_MULTIPLIER3;
26. 27.
mysteryNumber % FINAL_DIVISOR ; // the secret number System.out.println("You secret number is " mysteryNumber);
Variables and Assignment
79
28. } 29. }
Output Think of a number from 1 to 1000 Divide by 7 and tell me the remainder: 2 Divide by 11 and tell me the remainder: 1 Divide by 13 and tell me the remainder: 10 You secret number is 23
Discussion Lines 19, 22, 25, and 26 are assignment statements that utilize shortcut operators. Line 19: mysteryNumber remainder * MAGIC_MULTIPLIER1;
is equivalent to mysteryNumber mysteryNumber remainder * MAGIC_MULTIPLIER1;
And, line 26 mysteryNumber % FINAL_DIVISOR;
is a compact version of mysteryNumber mysteryNumber % FINAL_DIVISOR;
Figure 3.5 traces the actions of the program when the secret number is 23.
mysteryNumber
remainder
Line 14: Declare and initialize mysteryNumber to 0. Line 15: Declare remainder (uninitialized)
0
Line 18: 23 % 7 2, so the variable remainder gets the value 2.
0
2
1430
2
Line 19: The variable mysteryNumber gets the value 0 remainder * 715 which is 1430.
1794
1
Line 21: remainder 23 % 11 1. Line 22: mysteryNumber 1430 remainder * 364 1794.
11034
10
Line 24: remainder 23 % 13 10. Line 25: mysteryNumber 1794 remainder * 924 11034.
23
10
Line 26: mysteryNumber mysteryNumber % 1001 23.
FIGURE 3.5 A trace of MagicalMath
sim23356_ch03.indd 79
12/15/08 6:31:21 PM
80
Part 1
The Fundamental Tools
3.11 INCREMENT AND DECREMENT OPERATORS In later chapters, you will see a variety of applications that systematically add 1 to the value of a variable. Typically, this can be done with a statement such as number number 1; or number 1.
Because this operation is so common, Java provides a special increment operator, , which accomplishes the same effect. In fact, the operator has two forms: prefix and postfix. The following statements illustrate both forms: the first statement uses the prefix form of and the second statement the postfix form. 1. number; 2. number;
// prefix form, adds 1 to number // postfix form, adds 1 to number
Used in standalone statements such as (1) and (2), there is no apparent difference between the prefix and postfix versions of . Both accomplish the same task. For example, the output of the following two segments is identical. int number 5; number; //prefix System.out.println(number);
int number 5; number; //postfix System.out.println(number);
In each case, number increases by 1 and the output is 6. However, like or *, the operators can be used in a numerical expression. When used as part of an expression, the postfix and prefix versions operate differently. For example, consider the following code segments: // segment 1
// segment 2
1. int number 5; 2. int result; 3. result 3 * (number); 4. System.out.println(result);
1. int number 5; 2. int result; 3. result 3 * (number); 4. System.out.println(result);
The output of segment 1 is 18 but the output of segment 2 is 15. Segment 1 uses the prefix version of (line 3) and the following actions occur in sequence: 1. The value of number increases from 5 to 6. 2. The new value of number (6) is used in the expression 3*(number). See Figure 3.6. number
result
int number 5;
5
Increment number; 6
6
18
Use the “new” value of number in the expression 3*(number) and store the product in result. FIGURE 3.6 Prefix operator
sim23356_ch03.indd 80
12/15/08 6:31:22 PM
Chapter 3
Variables and Assignment
81
Segment 2 uses the postfix version of the operator (number). The sequence of actions is a bit different. 1. The current value in number (5) is retrieved and stored for use in the expression. 2. The value of number increases from 5 to 6. 3. The expression is evaluated using the “old” value (5) and consequently 3 * 5 15 is assigned to result. See Figure 3.7.
number
result
int number 5; The current value of number (5) will be used in the evaluation of 3*(number). Increment number;
5
6
6
Use the “old” value of number (5) in the expression 3 * (number) and store the product in result.
15
FIGURE 3.7 Postfix operator
In general, when using a variable with the prefix operator in an expression: 1. The value of the variable is first increased by 1. 2. The new value is used in the expression. Alternatively, when using a variable with the postfix operator in an expression: 1. The current value of the variable is retrieved for use in the expression. 2. The value of the variable is increased by 1. 3. The “original value” of the variable is used in the expression In addition to the increment operator, Java provides a decrement operator --, which subtracts 1 from its operand. As you would expect, the decrement operator can be used as a prefix or postfix operator. The increment and decrement operators, like the operators ,,*, /, and %, are shortcuts, “convenience operators,” and not essential. Moreover, the increment and decrement operators are usually used in standalone statements and not within expressions. Thus, it is common to see statements such as int x 20; ... x;
However, an expression such as 5 3 * (x)
// AVOID!
is obtuse and confusing, and should be avoided. This type of coding practice is begging for problems. And now, you can probably guess how the language C got its name.
sim23356_ch03.indd 81
12/15/08 6:31:22 PM
82
Part 1
The Fundamental Tools
3.12 AN EXPANDED PRECEDENCE TABLE We conclude the chapter with an expanded operator precedence chart that includes the assignment operators of this chapter. Notice that the increment and decrement operators have the highest priority. See Figure 3.8. high Operator !
Associativity
--
Right to left Right to left
(type) [cast operator e.g. (int)]
*
/
-
!
Left to right
%
Left to right
Left to right Left to right
&&
Left to right
||
Left to right
-
*
/
%
Right to left
low FIGURE 3.8 Operator precedence
3.13 STYLE Although good programming style is partly personal preference, many practices are universally accepted. Here is a short list of stylistic conventions. As you learn more about Java and programming, this list will grow. • Use meaningful variable names. • If the purpose of a variable is not immediately clear, use a comment to clarify its purpose. • Avoid trivial or gratuitous comments such as x x 1; // increments x. • Avoid complex, “clever” expressions in favor of simple, straightforward ones. Shortcut operators have their place, but use them sparingly. • Use indentation and line spacing to make your program more readable. • Initialize variables whenever possible. • Use explicit casts and parentheses to clarify meaning, even when not technically necessary.
3.14 IN CONCLUSION In this chapter, you have seen a very powerful programming concept: the variable. Programs manipulate data; variables store data. The ideas and techniques of this chapter have added a new level of flexibility to your programming toolbox. Variables allow your programs to store values in the computer’s memory as well as retrieve those values from memory. Moreover, variables facilitate interactive input. In Chapter 4, we show that programs can do more than evaluate expressions and manipulate variables. Programs can make decisions.
sim23356_ch03.indd 82
12/15/08 6:31:23 PM
Chapter 3
Variables and Assignment
83
Just the Facts • A variable is a named memory location capable of storing data of a specified type. • You can store a value in a variable, change its contents, and retrieve and use the variable’s stored value. • All variables must be declared. • A variable declaration specifies (1) the type of data that the variable can hold, and (2) the name of the variable. • The Java syntax for a variable declaration is: Type name1, name2, name3, . . .;
where Type is a Java data type (int, double, char, boolean) and nameX is a valid Java identifier. • A variable may be declared and initialized (given an initial value) with a single statement. For example: int sum 0;
• Values may be stored in a variable using an assignment statement. An assignment statement has the following format: variable expression • An assignment statement is also an expression and, as such, evaluates to the value calculated on the right-hand side of the operator. • An assignment is an expression while an initialization statement is not. Therefore, assignment statements may be chained; initialization statements may not. For example, x y z 5;
is legal, but int x y z 5;
is not. • The assignment statement a b; does not alter the value of b. • A variable’s name can be used in an expression, provided that the data type of the variable makes sense in the expression, and the variable has been assigned a value. • A Scanner object can be used for interactive input. One Scanner object can be used for an unlimited number of input values. • Before using a Scanner object for input, you must: Include the import statement: import java.util.*; Declare a Scanner with the statement Scanner name new Scanner (System.in);
where name is a valid Java identifier (e.g., input). • A variable may be declared as final so that its initial value may not be changed. For example: final double PI 3.14159; Final variables are also called constants. The name of a final variable is traditionally
composed of uppercase letters, digits, and underscores.
sim23356_ch03.indd 83
12/15/08 6:31:23 PM
84
Part 1
The Fundamental Tools
• To assign a value of a larger data type to a variable of a smaller type, a cast must be used. For example int x; double y 3.1987; x (int)y;
• Explicitly casting a variable does not change the contents of that variable. For example: double y 2.5; int x (int) y;
•
• • • •
gives x the value 2 but leaves y equal to 2.5. Java provides a number of shortcut assignment operators: x op y; is a shortcut for x x op y; where op is , , *, /, or %. The prefix increment operator x first adds 1 to the value of x and then returns the altered value of x. The postfix increment operator x first returns the value of x and then adds 1 to the value of x. In addition to the increment operator , Java provides prefix and postfix decrement operators (– –x and x– –). The increment and decrement operators can be applied to a variable of type byte, short, int, long, float, double, or char but not to a boolean variable.
Bug Extermination When we use variables, some common errors that the compiler can catch are: • Using a variable before it has been declared. • Using illegal variable names such as: 3examples, this-is-no-better, or ba_hum_bug! Stick with the (optional) Java camelCase convention: begin every variable name with a lowercase letter and each succeeding word in a name with an uppercase letter. For example, threeExamples, thisIsBetter, and baHumBug all conform to the standard. • Type mismatch in an assignment statement. Java will not automatically cast a larger data type to a smaller one. If x is of type short then x 5;
is a type mismatch because the data type of 5 is int. • Initialization type error: double x 9; is okay, but int y 23.9; is not. Java does not automatically cast a double to an int. • Using a variable before it has been given a value. For example: int x; x x 1;
// Look! an attempt to use an uninitialized variable. • Omitting parentheses around a casting operator. For example, float x float 3.14; // Error • Using a reserved word as a variable name. For example, int final 6; // Error
sim23356_ch03.indd 84
12/15/08 6:31:23 PM
Chapter 3
Variables and Assignment
85
• Chaining initializations. int x y 3; // Illegal int x 3, y 3; or int x 3, y x; // Legal • Using , , or other such shortcuts in declaration statements. int x 3, y x; is okay, but int x 3, y x; is not. • Failing to import a necessary Java package, e.g., import java.util.*; Although the Java compiler can detect errors of the types just listed, the resulting error message may be misleading or cryptic. For example, the erroneous initialization float x float 3.14159 results in the compiler message: java:38: '.class' expected float x float 3.14159; Be aware of the common errors and pitfalls; don’t rely on the compiler to do all the work for you. Logical errors are certainly more elusive than compile time errors. A few common errors that the compiler does not detect are: • Reversing the shortcut operator. For example: using as a shortcut instead of . The statements x 5;
and x 5;
are both valid but with very different meanings. • Misusing operator precedence. When in doubt (and sometimes even when not) use parentheses. • Confusing prefix and postfix operators. For example, x 3; y x; gives y the value 3, but x 3; y x; gives y the value 4. It is wise to avoid using and in expressions. • Mixing data types can cause surprising results. For most common tasks, stick with types int and double when using numerical data. • Confusing with . The former is assignment; the latter is comparison. For example, the statement x true; assigns true to x, and as an expression, always has the value true; but x true; evaluates to either true or false, depending on the value of x. Depending on its context, this error will sometimes be detected by the compiler, but not always.
sim23356_ch03.indd 85
12/15/08 6:31:24 PM
86
Part 1
The Fundamental Tools
EXERCISES LEARN THE LINGO Test your knowledge of the chapter’s vocabulary by completing the following crossword puzzle. 1
2
4
3
5 6
7
8
9
10
11 12 13 14 15 16
17
18
19
20
21
22
24
26
25
27
Across 2 Used for interactive input 4 A variable name cannot be a ______ 6 Operator || has ___ precedence than && 8 Named constants add to the ____ of a program 10 A variable that cannot be altered 11 A variable is accessed via its ______ 12 Statement that places a value in a variable 14 Java will not automatically ____ a larger type to a smaller one 18 Largest integer type 19 Constant names should be _____ 21 Like main() and println(), nextInt() is a _____ 22 A variable declaration must specify the _____ 23 Smallest integer type 24 Give a value in a declaration 26 Assignment is ____ associative 27 Smaller decimal type
sim23356_ch03.indd 86
23
Down 1 Choose variable names that are_______ 3 Scanner method 5 Every variable must be _____ 7 A Scanner object skips _______ 9 Named memory location 13 To use a Scanner you must ____ java.util.* 15 denotes the _____ operator 16 Type that does not allow casting 17 operator 20 Number of bits in a short integer 25 If x is of type byte then x 1 is of type___
12/15/08 6:31:24 PM
Chapter 3
Variables and Assignment
87
SHORT EXERCISES 1. True or False If false, give an explanation. a. If x has type int and y has type float, then the assignment y x; is legal. b. You may declare and initialize a variable in the same statement. c. The statement x 2 * y z; generates an error. d. The statement x y 2 * z; generates an error. e. The statement int byte 350; generates an error. f. The statement int byt 350; generates an error. g. The statement byte x 350; generates an error. h. Variables of type double are stored using 32 bits. i. The two expressions 3 * 5 / 4 and 3.0 * 5 / 4 evaluate to the same number. j. The two expressions 3 * 5 / 5 and 3.0 * 5 / 5 evaluate to the same number. 2. Expressions Give the value and data type of each of the following expressions or explain why the expression results in an error. Assume the following declarations: int x 3, w, v; double y 2.5; short z 's'; boolean m true;
a. b. c. d. e. f. g. h. i. j.
27x 2yz (2 * z x ) / 100 wy*2 v (int)5 * y 17 % (int)(10 / y) 6.2 (y 2.5) || (m && false) (x 2.0) && m (z 'T') || (m false) z * 2 * 2
3. Playing Compiler Determine the syntax errors, if any, in each of t