
6,217 2,173 19MB
Pages 1164 Page size 252 x 328.32 pts
JAVA™ FOR PROGRAMMERS SECOND EDITION DEITEL® DEVELOPER SERIES
Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and the publisher was aware of a trademark claim, the designations have been printed with initial capital letters or in all capitals. The authors and publisher have taken care in the preparation of this book, but make no expressed or implied warranty of any kind and assume no responsibility for errors or omissions. No liability is assumed for incidental or consequential damages in connection with or arising out of the use of the information or programs contained herein. The publisher offers excellent discounts on this book when ordered in quantity for bulk purchases or special sales, which may include electronic versions and/or custom covers and content particular to your business, training goals, marketing focus, and branding interests. For more information, please contact: U. S. Corporate and Government Sales (800) 382-3419 [email protected] For sales outside the U. S., please contact: International Sales [email protected] Visit us on the Web: informit.com/ph
Library of Congress Cataloging-in-Publication Data On file © 2012 Pearson Education, Inc. All rights reserved. Printed in the United States of America. This publication is protected by copyright, and permission must be obtained from the publisher prior to any prohibited reproduction, storage in a retrieval system, or transmission in any form or by any means, electronic, mechanical, photocopying, recording, or likewise. For information regarding permissions, write to: Pearson Education, Inc. Rights and Contracts Department 501 Boylston Street, Suite 900 Boston, MA 02116 Fax (617) 671-3447 ISBN-13: 978-0-13282154-4 ISBN-10: 0-13-282154-0
Text printed in the United States on recycled paper at RR Donnelley in Crawfordsville, Indiana. First printing, March 2012
JAVA™ FOR PROGRAMMERS SECOND EDITION DEITEL® DEVELOPER SERIES
Paul Deitel Deitel & Associates, Inc. Harvey Deitel Deitel & Associates, Inc.
Upper Saddle River, NJ • Boston • Indianapolis • San Francisco New York • Toronto • Montreal • London • Munich • Paris • Madrid Capetown • Sydney • Tokyo • Singapore • Mexico City
Trademarks DEITEL, the double-thumbs-up bug and DIVE INTO are registered trademarks of Deitel and Associates, Inc. Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners. Microsoft, Internet Explorer and the Windows logo are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries. UNIX is a registered trademark of The Open Group. Apache is a trademark of The Apache Software Foundation. CSS, XHTML and XML are registered trademarks of the World Wide Web Consortium. Firefox is a registered trademark of the Mozilla Foundation. Google is a trademark of Google, Inc. Web 2.0 is a service mark of CMP Media.
Throughout this book, trademarks are used. Rather than put a trademark symbol in every occurrence of a trademarked name, we state that we are using the names in an editorial fashion only and to the benefit of the trademark owner, with no intention of infringement of the trademark.
In memory of Clifford “Spike” Stephens, A dear friend who will be greatly missed. Paul and Harvey Deitel
This page intentionally left blank
Contents Preface Before You Begin
xxi xxix
1
Introduction
1
1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9
Introduction Introduction to Object Technology Open Source Software Java and a Typical Java Development Environment Test-Driving a Java Application Web 2.0: Going Social Software Technologies Keeping Up to Date with Information Technologies Wrap-Up
2 2 5 7 11 15 18 20 21
2
Introduction to Java Applications
22
2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8
Introduction Your First Program in Java: Printing a Line of Text Modifying Your First Java Program Displaying Text with printf Another Application: Adding Integers Arithmetic Decision Making: Equality and Relational Operators Wrap-Up
23 23 27 29 30 34 35 38
3
Introduction to Classes, Objects, Methods and Strings
3.1 3.2 3.3 3.4 3.5 3.6
Introduction Declaring a Class with a Method and Instantiating an Object of a Class Declaring a Method with a Parameter Instance Variables, set Methods and get Methods Primitive Types vs. Reference Types Initializing Objects with Constructors
39 40 40 44 47 52 53
viii
Contents
3.7 3.8
Floating-Point Numbers and Type double Wrap-Up
56 60
4
Control Statements: Part 1
61
4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10 4.11 4.12
Introduction Control Structures if Single-Selection Statement if…else Double-Selection Statement while Repetition Statement Counter-Controlled Repetition Sentinel-Controlled Repetition Nested Control Statements Compound Assignment Operators Increment and Decrement Operators Primitive Types Wrap-Up
5
Control Statements: Part 2
86
5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9
Introduction Essentials of Counter-Controlled Repetition for Repetition Statement Examples Using the for Statement do…while Repetition Statement switch Multiple-Selection Statement break and continue Statements Logical Operators Wrap-Up
87 87 89 92 96 98 105 107 113
6
Methods: A Deeper Look
6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8
Introduction Program Modules in Java static Methods, static Fields and Class Math Declaring Methods with Multiple Parameters Notes on Declaring and Using Methods Argument Promotion and Casting Java API Packages Case Study: Random-Number Generation 6.8.1 Generalized Scaling and Shifting of Random Numbers 6.8.2 Random-Number Repeatability for Testing and Debugging Case Study: A Game of Chance; Introducing Enumerations Scope of Declarations Method Overloading Wrap-Up
6.9 6.10 6.11 6.12
62 62 64 65 68 70 73 78 81 82 85 85
114 115 115 115 118 121 122 123 125 129 129 130 134 137 139
Contents
7
Arrays and ArrayLists
7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 7.10 7.11 7.12 7.13 7.14 7.15
Introduction Arrays Declaring and Creating Arrays Examples Using Arrays Case Study: Card Shuffling and Dealing Simulation Enhanced for Statement Passing Arrays to Methods Case Study: Class GradeBook Using an Array to Store Grades Multidimensional Arrays Case Study: Class GradeBook Using a Two-Dimensional Array Variable-Length Argument Lists Using Command-Line Arguments Class Arrays Introduction to Collections and Class ArrayList Wrap-Up
8
Classes and Objects: A Deeper Look
8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9 8.10 8.11 8.12 8.13 8.14 8.15 8.16
Introduction Class Case Study Controlling Access to Members Referring to the Current Object’s Members with the this Reference Time Class Case Study: Overloaded Constructors Default and No-Argument Constructors Notes on Set and Get Methods Composition Enumerations Garbage Collection and Method finalize static Class Members static Import final Instance Variables Time Class Case Study: Creating Packages Package Access Wrap-Up
9
Object-Oriented Programming: Inheritance
9.1 9.2 9.3 9.4
Introduction Superclasses and Subclasses protected Members Relationship between Superclasses and Subclasses 9.4.1 Creating and Using a CommissionEmployee Class 9.4.2 Creating and Using a BasePlusCommissionEmployee Class 9.4.3 Creating a CommissionEmployee–BasePlusCommissionEmployee Inheritance Hierarchy
Time
ix
140 141 141 143 144 153 157 159 162 167 171 177 178 180 183 186
187 188 188 192 193 195 201 202 203 206 209 210 213 214 215 221 222
224 225 226 228 228 229 235 240
x
Contents
9.5 9.6 9.7 9.8
Inheritance Hierarchy Using protected Instance Variables 9.4.5 CommissionEmployee–BasePlusCommissionEmployee Inheritance Hierarchy Using private Instance Variables Constructors in Subclasses Software Engineering with Inheritance Class Object Wrap-Up
10
Object-Oriented Programming: Polymorphism 254
10.1 10.2 10.3 10.4 10.5
10.8
Introduction Polymorphism Examples Demonstrating Polymorphic Behavior Abstract Classes and Methods Case Study: Payroll System Using Polymorphism 10.5.1 Abstract Superclass Employee 10.5.2 Concrete Subclass SalariedEmployee 10.5.3 Concrete Subclass HourlyEmployee 10.5.4 Concrete Subclass CommissionEmployee 10.5.5 Indirect Concrete Subclass BasePlusCommissionEmployee 10.5.6 Polymorphic Processing, Operator instanceof and Downcasting 10.5.7 Summary of the Allowed Assignments Between Superclass and Subclass Variables final Methods and Classes Case Study: Creating and Using Interfaces 10.7.1 Developing a Payable Hierarchy 10.7.2 Interface Payable 10.7.3 Class Invoice 10.7.4 Modifying Class Employee to Implement Interface Payable 10.7.5 Modifying Class SalariedEmployee for Use in the Payable Hierarchy 10.7.6 Using Interface Payable to Process Invoices and Employees Polymorphically 10.7.7 Common Interfaces of the Java API Wrap-Up
11
Exception Handling: A Deeper Look
11.1 11.2 11.3
Introduction Example: Divide by Zero without Exception Handling Example: Handling ArithmeticExceptions and
293 293
InputMismatchExceptions
11.4 11.5 11.6 11.7
When to Use Exception Handling Java Exception Hierarchy finally Block Stack Unwinding and Obtaining Information from an Exception Object
296 301 301 304 308
9.4.4
10.6 10.7
CommissionEmployee–BasePlusCommissionEmployee
242 245 250 251 252 253
255 257 258 260 262 263 266 268 270 271 273 277 278 279 280 281 282 284 286 288 289 290
292
Contents
xi
Chained Exceptions Declaring New Exception Types Preconditions and Postconditions Assertions (New in Java SE 7) Multi-catch: Handling Multiple Exceptions in One catch 11.13 (New in Java SE 7) try-with-Resources: Automatic Resource Deallocation 11.14 Wrap-Up
311 313 314 315
11.8 11.9 11.10 11.11 11.12
12
ATM Case Study, Part 1: Object-Oriented Design with the UML
12.1 12.2 12.3 12.4 12.5 12.6 12.7 12.8
Case Study Introduction Examining the Requirements Document Identifying the Classes in a Requirements Document Identifying Class Attributes Identifying Objects’ States and Activities Identifying Class Operations Indicating Collaboration Among Objects Wrap-Up
13
ATM Case Study Part 2: Implementing an Object-Oriented Design
13.1 13.2 13.3 13.4
13.5
Introduction Starting to Program the Classes of the ATM System Incorporating Inheritance and Polymorphism into the ATM System ATM Case Study Implementation 13.4.1 Class ATM 13.4.2 Class Screen 13.4.3 Class Keypad 13.4.4 Class CashDispenser 13.4.5 Class DepositSlot 13.4.6 Class Account 13.4.7 Class BankDatabase 13.4.8 Class Transaction 13.4.9 Class BalanceInquiry 13.4.10 Class Withdrawal 13.4.11 Class Deposit 13.4.12 Class ATMCaseStudy Wrap-Up
14
GUI Components: Part 1 398
14.1 14.2
Introduction Java’s New Nimbus Look-and-Feel
316 316 317
318 319 319 327 333 338 342 348 355
359 360 360 365 371 372 377 378 379 380 381 383 386 387 388 392 395 395
399 400
xii
Contents
14.3 14.4 14.5 14.6 14.7 14.8 14.9 14.10
Simple GUI-Based Input/Output with JOptionPane Overview of Swing Components Displaying Text and Images in a Window Text Fields and an Introduction to Event Handling with Nested Classes Common GUI Event Types and Listener Interfaces How Event Handling Works
15
Graphics and Java 2D
15.1 15.2 15.3 15.4 15.5 15.6 15.7 15.8 15.9
Introduction Graphics Contexts and Graphics Objects Color Control Manipulating Fonts Drawing Lines, Rectangles and Ovals Drawing Arcs Drawing Polygons and Polylines Java 2D API Wrap-Up
16
Strings, Characters and Regular Expressions
16.1 16.2 16.3
Introduction Fundamentals of Characters and Strings Class String 16.3.1 String Constructors 16.3.2 String Methods length, charAt and getChars 16.3.3 Comparing Strings 16.3.4 Locating Characters and Substrings in Strings
JButton
Buttons That Maintain State 14.10.1 JCheckBox 14.10.2 JRadioButton 14.11 JComboBox; Using an Anonymous Inner Class for Event Handling 14.12 JList 14.13 Multiple-Selection Lists 14.14 Mouse Event Handling 14.15 Adapter Classes 14.16 JPanel Subclass for Drawing with the Mouse 14.17 Key Event Handling 14.18 Introduction to Layout Managers 14.18.1 FlowLayout 14.18.2 BorderLayout 14.18.3 GridLayout 14.19 Using Panels to Manage More Complex Layouts 14.20 JTextArea 14.21 Wrap-Up
401 404 406 410 416 418 420 423 423 426 429 433 435 438 443 446 450 453 454 457 460 462 464 467
468 469 471 472 479 484 488 491 494 501
502 503 503 504 504 505 506 511
Contents
16.5 16.6 16.7 16.8
16.3.5 Extracting Substrings from Strings 16.3.6 Concatenating Strings 16.3.7 Miscellaneous String Methods 16.3.8 String Method valueOf Class StringBuilder 16.4.1 StringBuilder Constructors 16.4.2 StringBuilder Methods length, capacity, setLength and ensureCapacity 16.4.3 StringBuilder Methods charAt, setCharAt, getChars and reverse 16.4.4 StringBuilder append Methods 16.4.5 StringBuilder Insertion and Deletion Methods Class Character Tokenizing Strings Regular Expressions, Class Pattern and Class Matcher Wrap-Up
17
Files, Streams and Object Serialization
17.1 17.2 17.3 17.4
17.7 17.8
Introduction Files and Streams Class File Sequential-Access Text Files 17.4.1 Creating a Sequential-Access Text File 17.4.2 Reading Data from a Sequential-Access Text File 17.4.3 Case Study: A Credit-Inquiry Program 17.4.4 Updating Sequential-Access Files Object Serialization 17.5.1 Creating a Sequential-Access File Using Object Serialization 17.5.2 Reading and Deserializing Data from a Sequential-Access File Additional java.io Classes 17.6.1 Interfaces and Classes for Byte-Based Input and Output 17.6.2 Interfaces and Classes for Character-Based Input and Output Opening Files with JFileChooser Wrap-Up
18
Generic Collections
18.1 18.2 18.3 18.4 18.5 18.6
Introduction Collections Overview Type-Wrapper Classes for Primitive Types Autoboxing and Auto-Unboxing Interface Collection and Class Collections Lists 18.6.1 ArrayList and Iterator 18.6.2 LinkedList
16.4
17.5 17.6
xiii 513 514 514 516 517 518 518 520 521 523 524 529 530 538
539 540 540 542
546 546 553 556 561 562 563 569 571 571 573 574 577
578 579 579 580 581 581 582 583 585
xiv 18.7
Contents
18.8 18.9 18.10 18.11 18.12 18.13 18.14 18.15 18.16
Collections Methods 18.7.1 Method sort 18.7.2 Method shuffle 18.7.3 Methods reverse, fill, copy, max and min 18.7.4 Method binarySearch 18.7.5 Methods addAll, frequency and disjoint Stack Class of Package java.util Class PriorityQueue and Interface Queue Sets Maps Properties Class Synchronized Collections Unmodifiable Collections Abstract Implementations Wrap-Up
19
Generic Classes and Methods
19.1 19.2 19.3 19.4
Introduction Motivation for Generic Methods Generic Methods: Implementation and Compile-Time Translation Additional Compile-Time Translation Issues: Methods That Use a Type Parameter as the Return Type 19.5 Overloading Generic Methods 19.6 Generic Classes 19.7 Raw Types 19.8 Wildcards in Methods That Accept Type Parameters 19.9 Generics and Inheritance: Notes 19.10 Wrap-Up
20
Applets and Java Web Start
20.1 20.2 20.3
Introduction Sample Applets Provided with the JDK Simple Java Applet: Drawing a String 20.3.1 Executing WelcomeApplet in the appletviewer 20.3.2 Executing an Applet in a Web Browser Applet Life-Cycle Methods Initialization with Method init Sandbox Security Model Java Web Start and the Java Network Launch Protocol (JNLP) 20.7.1 Packaging the DrawTest Applet for Use with Java Web Start 20.7.2 JNLP Document for the DrawTest Applet Wrap-Up
20.4 20.5 20.6 20.7
20.8
590 591 594 596 598 600 602 604 605 608 612 615 615 616 616
618 619 619 622 625 628 628 636 640 644 645
646 647 648 652 654 656 656 657 659 661 661 662 666
Contents
21
Multimedia: Applets and Applications
21.1 21.2 21.3 21.4 21.5 21.6 21.7 21.8
Introduction Loading, Displaying and Scaling Images Animating a Series of Images Image Maps Loading and Playing Audio Clips Playing Video and Other Media with Java Media Framework Wrap-Up Web Resources
22
GUI Components: Part 2
22.1 22.2 22.3 22.4 22.5 22.6 22.7 22.8 22.9 22.10
Introduction
23
Multithreading
23.1 23.2 23.3 23.4
Introduction Thread States: Life Cycle of a Thread Creating and Executing Threads with Executor Framework Thread Synchronization 23.4.1 Unsynchronized Data Sharing 23.4.2 Synchronized Data Sharing—Making Operations Atomic Producer/Consumer Relationship without Synchronization Producer/Consumer Relationship: ArrayBlockingQueue Producer/Consumer Relationship with Synchronization Producer/Consumer Relationship: Bounded Buffers Producer/Consumer Relationship: The Lock and Condition Interfaces Concurrent Collections Overview Multithreading with GUI 23.11.1 Performing Computations in a Worker Thread 23.11.2 Processing Intermediate Results with SwingWorker Interfaces Callable and Future Java SE 7: Fork/Join Framework Wrap-Up
23.5 23.6 23.7 23.8 23.9 23.10 23.11
23.12 23.13 23.14
JSlider
Windows: Additional Notes Using Menus with Frames JPopupMenu
Pluggable Look-and-Feel JDesktopPane and JInternalFrame JTabbedPane
Layout Managers: BoxLayout and GridBagLayout Wrap-Up
xv
667 668 669 675 682 685 688 692 692
694 695 695 699 700 708 711 716 720 722 734
735 736 738 741 744 745 749 752 760 763 769 776 783 785 786 792 799 799 800
xvi
Contents
24
Networking
24.1 24.2 24.3 24.4 24.5 24.6 24.7 24.8 24.9 24.10
Introduction Manipulating URLs Reading a File on a Web Server Establishing a Simple Server Using Stream Sockets Establishing a Simple Client Using Stream Sockets Client/Server Interaction with Stream Socket Connections Datagrams: Connectionless Client/Server Interaction Client/Server Tic-Tac-Toe Using a Multithreaded Server [Web Bonus] Case Study: DeitelMessenger Wrap-Up
25
Accessing Databases with JDBC
25.1 25.2 25.3 25.4
25.9 25.10 25.11 25.12 25.13 25.14 25.15
Introduction Relational Databases Relational Database Overview: The books Database SQL 25.4.1 Basic SELECT Query 25.4.2 WHERE Clause 25.4.3 ORDER BY Clause 25.4.4 Merging Data from Multiple Tables: INNER JOIN 25.4.5 INSERT Statement 25.4.6 UPDATE Statement 25.4.7 DELETE Statement Instructions for Installing MySQL and MySQL Connector/J Instructions for Setting Up a MySQL User Account Creating Database books in MySQL Manipulating Databases with JDBC 25.8.1 Connecting to and Querying a Database 25.8.2 Querying the books Database RowSet Interface Java DB/Apache Derby PreparedStatements Stored Procedures Transaction Processing Wrap-Up Web Resources
26
JavaServer™ Faces Web Apps: Part 1
26.1 26.2 26.3 26.4
Introduction HyperText Transfer Protocol (HTTP) Transactions Multitier Application Architecture Your First JSF Web App 26.4.1 The Default index.xhtml Document: Introducing Facelets
25.5 25.6 25.7 25.8
801 802 803 808 811 813 813 825 833 848 848
849 850 851 852 855 856 857 859 860 862 863 864 864 865 866 867 867 872 885 887 889 904 905 905 906
907 908 909 912 913 914
Contents
xvii
26.9
26.4.2 Examining the WebTimeBean Class 26.4.3 Building the WebTime JSF Web App in NetBeans Model-View-Controller Architecture of JSF Apps Common JSF Components Validation Using JSF Standard Validators Session Tracking 26.8.1 Cookies 26.8.2 Session Tracking with @SessionScoped Beans Wrap-Up
916 918 922 922 926 933 934 935 941
27
JavaServer™ Faces Web Apps: Part 2
942
27.1 27.2
27.3 27.4 27.5
Introduction Accessing Databases in Web Apps 27.2.1 Setting Up the Database 27.2.2 @ManagedBean Class AddressBean 27.2.3 index.xhtml Facelets Page 27.2.4 addentry.xhtml Facelets Page Ajax Adding Ajax Functionality to the Validation App Wrap-Up
28
Web Services
28.1 28.2 28.3 28.4 28.5 28.6
Introduction Web Service Basics Simple Object Access Protocol (SOAP) Representational State Transfer (REST) JavaScript Object Notation (JSON) Publishing and Consuming SOAP-Based Web Services 28.6.1 Creating a Web Application Project and Adding a Web Service Class in NetBeans 28.6.2 Defining the WelcomeSOAP Web Service in NetBeans 28.6.3 Publishing the WelcomeSOAP Web Service from NetBeans 28.6.4 Testing the WelcomeSOAP Web Service with GlassFish Application Server’s Tester Web Page 28.6.5 Describing a Web Service with the Web Service Description Language (WSDL) 28.6.6 Creating a Client to Consume the WelcomeSOAP Web Service 28.6.7 Consuming the WelcomeSOAP Web Service Publishing and Consuming REST-Based XML Web Services 28.7.1 Creating a REST-Based XML Web Service 28.7.2 Consuming a REST-Based XML Web Service Publishing and Consuming REST-Based JSON Web Services 28.8.1 Creating a REST-Based JSON Web Service 28.8.2 Consuming a REST-Based JSON Web Service
26.5 26.6 26.7 26.8
28.7 28.8
943 943 945 948 952 954 956 958 961
962 963 965 965 965 966 966 966 967 970 971 972 973 975 978 978 981 983 983 985
xviii
Contents
28.9
Session Tracking in a SOAP Web Service 28.9.1 Creating a Blackjack Web Service 28.9.2 Consuming the Blackjack Web Service 28.10 Consuming a Database-Driven SOAP Web Service 28.10.1 Creating the Reservation Database 28.10.2 Creating a Web Application to Interact with the Reservation Service 28.11 Equation Generator: Returning User-Defined Types 28.11.1 Creating the EquationGeneratorXML Web Service 28.11.2 Consuming the EquationGeneratorXML Web Service 28.11.3 Creating the EquationGeneratorJSON Web Service 28.11.4 Consuming the EquationGeneratorJSON Web Service 28.12 Wrap-Up
987 988 991 1002 1003 1006 1009 1012 1013 1017 1017 1020
A
Operator Precedence Chart
1022
B
ASCII Character Set
1024
C
Keywords and Reserved Words
1025
D
Primitive Types
1026
E
Using the Java API Documentation
1027
E.1 E.2
Introduction Navigating the Java API
F
Using the Debugger
F.1 F.2 F.3 F.4 F.5 F.6 F.7
Introduction Breakpoints and the run, stop, cont and print Commands The print and set Commands Controlling Execution Using the step, step up and next Commands The watch Command The clear Command Wrap-Up
G
Formatted Output
G.1 G.2 G.3
Introduction Streams Formatting Output with printf
1027 1028
1036 1037 1037 1041 1043 1046 1049 1051
1052 1053 1053 1053
Contents G.4 G.5 G.6 G.7 G.8 G.9 G.10 G.11 G.12 G.13 G.14
Printing Integers Printing Floating-Point Numbers Printing Strings and Characters Printing Dates and Times Other Conversion Characters Printing with Field Widths and Precisions Using Flags in the printf Format String Printing with Argument Indices Printing Literals and Escape Sequences Formatting Output with Class Formatter Wrap-Up
H
GroupLayout
H.1 H.2 H.3 H.4
Introduction GroupLayout Basics Building a ColorChooser GroupLayout Web Resources
I
Java Desktop Integration Components
I.1 I.2 I.3 I.4
Introduction Splash Screens Desktop Class Tray Icons
J
UML 2: Additional Diagram Types
J.1 J.2
Introduction Additional Diagram Types
Index
xix 1054 1055 1057 1058 1060 1062 1064 1068 1068 1069 1070
1071 1071 1071 1072 1082
1083 1083 1083 1085 1087
1089 1089 1089
1091
This page intentionally left blank
Preface Live in fragments no longer, only connect. —Edgar Morgan Foster Welcome to Java and Java for Programmers, Second Edition! This book presents leadingedge computing technologies for software developers. We focus on software engineering best practices. At the heart of the book is the Deitel signature “live-code approach”—concepts are presented in the context of complete working programs, rather than in code snippets. Each complete code example is accompanied by live sample executions. All the source code is available at www.deitel.com/books/javafp2/
As you read the book, if you have questions, send an e-mail to [email protected]; we’ll respond promptly. For updates on this book, visit the website shown above, follow us on Facebook (www.facebook.com/DeitelFan) and Twitter (@deitel), and subscribe to the Deitel ® Buzz Online newsletter (www.deitel.com/newsletter/subscribe.html).
Features Here are the key features of Java for Programmers, 2/e:
Java Standard Edition (SE) 7 • Easy to use as a Java SE 6 or Java SE 7 book. We cover the new Java SE 7 features in modular sections. Here’s some of the new functionality: Strings in switch statements, the try-with-resources statement for managing AutoClosable objects, multi-catch for defining a single exception handler to replace multiple exception handlers that perform the same task and inferring the types of generic objects from the variable they’re assigned to by using the notation. We also overview the new concurrency API features. • Java SE 7’s AutoClosable versions of Connection, Statement and ResultSet. With the source code for Chapter 25, Accessing Databases with JDBC, we provide a version of the chapter’s first example that’s implemented using Java SE 7’s AutoClosable versions of Connection, Statement and ResultSet. AutoClosable objects reduce the likelihood of resource leaks when you use them with Java SE 7’s try-with-resources statement, which automatically closes the AutoClosable objects allocated in the parentheses following the try keyword. Object Technology • Object-oriented programming and design. We review the basic concepts and terminology of object technology in Chapter 1. Readers develop their first customized classes and objects in Chapter 3.
xxii
Preface
•
Exception handling. We integrate basic exception handling early in the book and cover it in detail in Chapter 11, Exception Handling: A Deeper Look.
•
Class Arrays and ArrayList. Chapter 7 covers class Arrays—which contains methods for performing common array manipulations—and class ArrayList— which implements a dynamically resizable array-like data structure.
•
OO case studies. The early classes and objects presentation features Time, Employee and GradeBook class case studies that weave their way through multiple sections and chapters, gradually introducing deeper OO concepts.
•
Case Study: Using the UML to Develop an Object-Oriented Design and Java Implementation of an ATM. The UML™ (Unified Modeling Language™) is the industry-standard graphical language for modeling object-oriented systems. Chapters 12–13 include a case study on object-oriented design using the UML. We design and implement the software for a simple automated teller machine (ATM). We analyze a typical requirements document that specifies the system to be built. We determine the classes needed to implement that system, the attributes the classes need to have, the behaviors the classes need to exhibit and specify how the classes must interact with one another to meet the system requirements. From the design we produce a complete Java implementation. Readers often report having a “light-bulb moment”—the case study helps them “tie it all together” and really understand object orientation in Java.
•
Reordered generics presentation. We begin with generic class ArrayList in Chapter 7. Because you’ll understand basic generics concepts early in the book, our later data structures discussions provide a deeper treatment of generic collections— showing how to use the built-in collections of the Java API. We then show how to implement generic methods and classes.
Database and Web Development • JDBC 4. Chapter 25, Accessing Databases with JDBC, covers JDBC 4 and uses the Java DB/Apache Derby and MySQL database management systems. The chapter features an OO case study on developing a database-driven address book that demonstrates prepared statements and JDBC 4’s automatic driver discovery. • Java Server Faces (JSF) 2.0. Chapters 26–27 have been updated with JavaServer Faces (JSF) 2.0 technology, which greatly simplifies building JSF web applications. Chapter 26 includes examples on building web application GUIs, validating forms and session tracking. Chapter 27 discusses data-driven and Ajaxenabled JSF applications. The chapter features a database-driven multitier web address book that allows users to add and search for contacts. • Web services. Chapter 28, Web Services, demonstrates creating and consuming SOAP- and REST-based web services. Case studies include developing blackjack and airline reservation web services. • Java Web Start and the Java Network Launch Protocol (JNLP). We introduce Java Web Start and JNLP, which enable applets and applications to be launched via a web browser. Users can install locally for later execution. Programs can also request the user’s permission to access local system resources such as files—en-
Teaching Approach
xxiii
abling you to develop more robust applets and applications that execute safely using Java’s sandbox security model, which applies to downloaded code.
Multithreading • Multithreading. We completely reworked Chapter 23, Multithreading [special thanks to the guidance of Brian Goetz and Joseph Bowbeer—two of the co-authors of Java Concurrency in Practice, Addison-Wesley, 2006]. • SwingWorker class. We use class SwingWorker to create multithreaded user interfaces. GUI and Graphics • GUI and graphics presentation. Chapters 14, 15 and 22, and Appendix H present Java GUI and Graphics programming. • GroupLayout layout manager. We discuss the GroupLayout layout manager in the context of the GUI design tool in the NetBeans IDE. • JTable sorting and filtering capabilities. Chapter 25 uses these capabilities to sort the data in a JTable and filter it by regular expressions. Other Features • Android. Because of the tremendous interest in Android-based smartphones and tablets, we’ve included a three-chapter introduction to Android app development online at www.deitel.com/books/javafp. These chapters are from our new Deitel Developer Series book Android for Programmers: An App-Driven Approach. After you learn Java, you’ll find it straightforward to develop and run Android apps on the free Android emulator that you can download from developer.android.com. • Software engineering community concepts. We discuss agile software development, refactoring, design patterns, LAMP, SaaS (Software as a Service), PaaS (Platform as a Service), cloud computing, open-source software and more.
Teaching Approach Java for Programmers, 2/e, contains hundreds of complete working examples. We stress program clarity and concentrate on building well-engineered software. Syntax Shading. For readability, we syntax shade the code, similar to the way most integrated-development environments and code editors syntax color the code. Our syntaxshading conventions are: comments appear like this keywords appear like this constants and literal values appear like this all other code appears in black
Code Highlighting. We place gray rectangles around each program’s key code. Using Fonts for Emphasis. We place the key terms and the index’s page reference for each defining occurrence in bold text for easier reference. On-screen components are emphasized in the bold Helvetica font (e.g., the File menu) and Java program text in the Lucida font (e.g., int x = 5;).
xxiv
Preface
Web Access. All of the source-code examples can be downloaded from: www.deitel.com/books/javafp2 www.pearsonhighered.com/deitel
Objectives. The chapter opening quotations are followed by a list of chapter objectives. Illustrations/Figures. Abundant tables, line drawings, UML diagrams, programs and program outputs are included. Programming Tips. We include programming tips to help you focus on important aspects of program development. These tips and practices represent the best we’ve gleaned from a combined eight decades of programming and teaching experience.
Good Programming Practice The Good Programming Practices call attention to techniques that will help you produce programs that are clearer, more understandable and more maintainable.
Common Programming Error Pointing out these Common Programming Errors reduces the likelihood that you’ll make the same errors.
Error-Prevention Tip These tips contain suggestions for exposing and removing bugs from your programs; many of the tips describe aspects of Java that prevent bugs from getting into programs.
Performance Tip These tips highlight opportunities for making your programs run faster or minimizing the amount of memory that they occupy.
Portability Tip The Portability Tips help you write code that will run on a variety of platforms.
Software Engineering Observation The Software Engineering Observations highlight architectural and design issues that affect the construction of software systems, especially large-scale systems.
Look-and-Feel Observation These observations help you design attractive, user-friendly graphical user interfaces that conform to industry norms.
Thousands of Index Entries. We’ve included a comprehensive index, which is especially useful when you use the book as a reference.
Software Used in Java for Programmers, 2/e All the software you’ll need for this book is available free for download from the web. See the Before You Begin section that follows the Preface for links to each download.
Discounts on Deitel Developer Series Books
xxv
We wrote most of the examples in Java for Programmers, 2/e, using the free Java Standard Edition Development Kit (JDK) 6. For the Java SE 7 modules, we used the OpenJDK’s early access version of JDK 7 (download.java.net/jdk7/). In Chapters 26– 28, we also used the Netbeans IDE, and in Chapter 25, we used MySQL and MySQL Connector/J. You can find additional resources and software downloads in our Java Resource Centers at: www.deitel.com/ResourceCenters.html
Discounts on Deitel Developer Series Books If you’d like to receive information on professional Deitel Developer Series titles, including Android for Programmers: An App-Driven Approach, please register your copy of Java for Programmers, 2/e at informit.com/register. You’ll receive information on how to purchase Android for Programmers at a discount.
Java Fundamentals: Parts I, II and III, Second Edition LiveLessons Video Training Product Our Java Fundamentals: Parts I, II and III, Second Edition LiveLessons video training product shows you what you need to know to start building robust, powerful software with Java. It includes 20+ hours of expert training synchronized with Java for Programmers, 2/e. Check out our growing list of LiveLessons video products: • Java Fundamentals I and II • C# 2010 Fundamentals I, II, and III • C# 2008 Fundamentals I and II • C++ Fundamentals I and II • iPhone App-Development Fundamentals I and II • JavaScript Fundamentals I and II • Visual Basic 2010 Fundamentals I and II
Coming Soon • Java Fundamentals I, II and III, Second Edition • C Fundamentals I and II • Android App Development Fundamentals I and II • iPhone and iPad App-Development Fundamentals I and II, Second Edition For additional information about Deitel LiveLessons video products, visit: www.deitel.com/livelessons
Acknowledgments We’d like to thank Abbey Deitel and Barbara Deitel for long hours devoted to this project. Barbara devoted long hours to Internet research to support our writing efforts. Abbey wrote the new engaging Chapter 1 and the new cover copy. We’re fortunate to have worked on this project with the dedicated team of publishing professionals at Pearson. We appreciate
xxvi
Preface
the guidance, savvy and energy of Mark Taub, Editor-in-Chief of Computer Science. John Fuller managed the book’s production. Sandra Schroeder did the cover design.
Reviewers We wish to acknowledge the efforts of the reviewers who contributed to the recent editions of this content. They scrutinized the text and the programs and provided countless suggestions for improving the presentation: Lance Andersen (Oracle), Soundararajan Angusamy (Sun Microsystems), Joseph Bowbeer (Consultant), William E. Duncan (Louisiana State University), Diana Franklin (University of California, Santa Barbara), Edward F. Gehringer (North Carolina State University), Huiwei Guan (Northshore Community College), Ric Heishman (George Mason University), Dr. Heinz Kabutz (JavaSpecialists.eu), Patty Kraft (San Diego State University), Lawrence Premkumar (Sun Microsystems), Tim Margush (University of Akron), Sue McFarland Metzger (Villanova University), Shyamal Mitra (The University of Texas at Austin), Peter Pilgrim (Java Champion, Consultant), Manjeet Rege, Ph.D. (Rochester Institute of Technology), Manfred Riem (Java Champion, Consultant, Robert Half), Simon Ritter (Oracle), Susan Rodger (Duke University), Amr Sabry (Indiana University), José Antonio González Seco (Parliament of Andalusia), Sang Shin (Sun Microsystems), S. Sivakumar (Astra Infotech Private Limited), Raghavan “Rags” Srinivas (Intuit), Monica Sweat (Georgia Tech), Vinod Varma (Astra Infotech Private Limited) and Alexander Zuev (Sun Microsystems). Well, there you have it! As you read the book, we’d appreciate your comments, criticisms, corrections and suggestions for improvement. Please address all correspondence to: [email protected]
We’ll respond promptly. We hope you enjoy working with Java for Programmers, 2/e. Good luck! Paul and Harvey Deitel
About the Authors Paul J. Deitel, CEO and Chief Technical Officer of Deitel & Associates, Inc., is a graduate of MIT, where he studied Information Technology. He holds the Sun (now Oracle) Certified Java Programmer and Certified Java Developer certifications, and is an Oracle Java Champion. Through Deitel & Associates, Inc., he has delivered Java, C#, Visual Basic, C++, C and Internet programming courses to industry clients, including Cisco, IBM, Sun Microsystems, Dell, Siemens, Lucent Technologies, Fidelity, NASA at the Kennedy Space Center, the National Severe Storm Laboratory, White Sands Missile Range, Rogue Wave Software, Boeing, SunGard Higher Education, Stratus, Cambridge Technology Partners, One Wave, Hyperion Software, Adra Systems, Entergy, CableData Systems, Nortel Networks, Puma, iRobot, Invensys and many more. He and his co-author, Dr. Harvey M. Deitel, are the world’s best-selling programming-language textbook/professional book authors. Dr. Harvey M. Deitel, Chairman and Chief Strategy Officer of Deitel & Associates, Inc., has 50 years of experience in the computer field. Dr. Deitel earned B.S. and M.S. degrees from MIT and a Ph.D. from Boston University. He has extensive industry and academic experience, including earning tenure and serving as the Chairman of the Computer Science Department at Boston College before founding Deitel & Associates, Inc.,
About Deitel & Associates, Inc.
xxvii
with his son, Paul J. Deitel. He and Paul are the co-authors of dozens of books and multimedia packages and they are writing many more. With translations published in Japanese, German, Russian, Chinese, Spanish, Korean, French, Polish, Italian, Portuguese, Greek, Urdu and Turkish, the Deitels’ texts have earned international recognition. Dr. Deitel has delivered hundreds of professional seminars to major corporations, academic institutions, government organizations and the military.
About Deitel & Associates, Inc. Deitel & Associates, Inc., founded by Paul Deitel and Harvey Deitel, is an internationally recognized authoring, corporate training and software development organization specializing in computer programming languages, object technology, Android and iPhone app development, and Internet and web software technology. The company offers instructor-led training courses delivered at client sites worldwide on major programming languages and platforms, such as Java™, C, C++, Visual C#®, Visual Basic®, Objective-C, and iPhone and iPad app development, Android app development, XML®, Python®, object technology, Internet and web programming, and a growing list of additional programming and software development courses. The company’s clients include many of the world’s largest companies, government agencies, branches of the military, and academic institutions. Through its 35-year publishing partnership with Prentice Hall/Pearson, Deitel & Associates, Inc., publishes leading-edge programming professional books, college textbooks, and LiveLessons DVD- and web-based video courses. Deitel & Associates, Inc. and the authors can be reached at: [email protected]
To learn more about Deitel’s Dive Into® Series Corporate Training curriculum, visit: www.deitel.com/training/
subscribe to the free Deitel® Buzz Online e-mail newsletter at: www.deitel.com/newsletter/subscribe.html
and follow the authors on Facebook www.facebook.com/DeitelFan
and Twitter @deitel
To request a proposal for on-site, instructor-led training at your company or organization, e-mail [email protected]
Individuals wishing to purchase Deitel books and LiveLessons DVD training courses can do so through www.deitel.com. Bulk orders by corporations, the government, the military and academic institutions should be placed directly with Pearson. For more information, visit www.pearsoned.com/professional/index.htm.
This page intentionally left blank
Before You Begin This section contains information you should review before using this book and instructions to ensure that your computer is set up properly for use with this book. We’ll post updates (if any) to the Before You Begin section on the book’s website: www.deitel.com/books/javafp2/
Font and Naming Conventions We use fonts to distinguish between on-screen components (such as menu names and menu items) and Java code or commands. Our convention is to emphasize on-screen components in a sans-serif bold Helvetica font (for example, File menu) and to emphasize Java code and commands in a sans-serif Lucida font (for example, System.out.println()).
Software Used in the Book All the software you’ll need for this book is available free for download from the web.
Java SE Software Development Kit (JDK) 6 and 7 We wrote most of the examples in Java for Programmers, 2/e, using the free Java Standard Edition Development Kit (JDK) 6, which is available from: www.oracle.com/technetwork/java/javase/downloads/index.html
For the Java SE 7 modules, we used the OpenJDK’s early access version of JDK 7, which is available from: dlc.sun.com.edgesuite.net/jdk7/binaries-/index.html
Java DB, MySQL and MySQL Connector/J In Chapter 25, we use the Java DB and MySQL Community Edition database management systems. Java DB is part of the JDK installation. At the time of this writing, the JDK’s 64-bit installer was not properly installing Java DB. If you are using the 64-bit version of Java, you may need to install Java DB separately. You can download Java DB from: www.oracle.com/technetwork/java/javadb/downloads/index.html
At the time of this writing, the latest release of MySQL Community Edition was 5.5.8. To install MySQL Community Edition on Windows, Linux or Mac OS X, see the installation overview for your platform at: •
Windows: dev.mysql.com/doc/refman/5.5/en/windows-installation.html
•
Linux: dev.mysql.com/doc/refman/5.5/en/linux-installation-rpm.html
•
Mac OS X: dev.mysql.com/doc/refman/5.5/en/macosx-installation.html
xxx Carefully follow the instructions for downloading and installing the software on your platform. The downloads are available from: dev.mysql.com/downloads/mysql/
You also need to install MySQL Connector/J (the J stands for Java), which allows programs to use JDBC to interact with MySQL. MySQL Connector/J can be downloaded from dev.mysql.com/downloads/connector/j/
At the time of this writing, the current generally available release of MySQL Connector/J is 5.1.14. The documentation for Connector/J is located at dev.mysql.com/doc/refman/5.5/en/connector-j.html
To install MySQL Connector/J, carefully follow the installation instructions at: dev.mysql.com/doc/refman/5.5/en/connector-j-installing.html
We do not recommend modifying your system’s CLASSPATH environment variable, which is discussed in the installation instructions. Instead, we’ll show you how use MySQL Connector/J by specifying it as a command-line option when you execute your applications.
Obtaining the Code Examples The examples for Java for Programmers, 2/e are available for download at www.deitel.com/books/javafp2/
If you’re not already registered at our website, go to www.deitel.com and click the Register link below our logo in the upper-left corner of the page. Fill in your information. There’s no charge to register, and we do not share your information with anyone. We send you only account-management e-mails unless you register separately for our free Deitel ® Buzz Online e-mail newsletter at www.deitel.com/newsletter/subscribe.html. After registering for the site, you’ll receive a confirmation e-mail with your verification code. Click the link in the confirmation e-mail to complete your registration. Configure your e-mail client to allow e-mails from deitel.com to ensure that the confirmation email is not filtered as junk mail. Next, go to www.deitel.com and sign in using the Login link below our logo in the upper-left corner of the page. Go to www.deitel.com/books/javafp2/. You’ll find the link to download the examples under the heading Download Code Examples and Other Premium Content for Registered Users. Write down the location where you choose to save the ZIP file on your computer. We assume the examples are located at C:\Examples on your computer.
Setting the PATH Environment Variable The PATH environment variable on your computer designates which directories the computer searches when looking for applications, such as the applications that enable you to compile and run your Java applications (called javac and java, respectively). Carefully follow the installation instructions for Java on your platform to ensure that you set the PATH environment variable correctly.
Setting the CLASSPATH Environment Variable If you do not set the receive a message like:
PATH
xxxi
variable correctly, when you use the JDK’s tools, you’ll
'java' is not recognized as an internal or external command, operable program or batch file.
In this case, go back to the installation instructions for setting the PATH and recheck your steps. If you’ve downloaded a newer version of the JDK, you may need to change the name of the JDK’s installation directory in the PATH variable.
Setting the CLASSPATH Environment Variable If you attempt to run a Java program and receive a message like Exception in thread "main" java.lang.NoClassDefFoundError: YourClass
then your system has a CLASSPATH environment variable that must be modified. To fix the preceding error, follow the steps in setting the PATH environment variable, to locate the CLASSPATH variable, then edit the variable’s value to include the local directory—typically represented as a dot (.). On Windows add .;
at the beginning of the CLASSPATH’s value (with no spaces before or after these characters). On other platforms, replace the semicolon with the appropriate path separator characters—often a colon (:)
Java’s Nimbus Look-and-Feel Java comes bundled with an elegant, cross-platform look-and-feel known as Nimbus. For programs with graphical user interfaces, we’ve configured our systems to use Nimbus as the default look-and-feel. To set Nimbus as the default for all Java applications, you must create a text file named swing.properties in the lib folder of both your JDK installation folder and your JRE installation folder. Place the following line of code in the file: swing.defaultlaf=com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel
For more information on locating these installation folders visit java.sun.com/javase/ 6/webnotes/install/index.html. [Note: In addition to the standalone JRE, there’s a JRE nested in your JDK’s installation folder. If you’re using an IDE that depends on the JDK (e.g., NetBeans), you may also need to place the swing.properties file in the nested jre folder’s lib folder.]
This page intentionally left blank
1 Introduction
Man is still the most extraordinary computer of all. —John F. Kennedy
Good design is good business. —Thomas J. Watson, Founder of IBM
How wonderful it is that nobody need wait a single moment before starting to improve the world. —Anne Frank
Objectives In this chapter you’ll learn: I
Exciting recent developments in the computer field.
I
Basic object-technology concepts.
I
A typical Java program-development environment.
I
To test-drive a Java application.
I
Some key recent software technologies.
2
Chapter 1 Introduction
1.1 1.2 1.3 1.4
Introduction Introduction to Object Technology Open Source Software Java and a Typical Java Development Environment 1.5 Test-Driving a Java Application
1.6 Web 2.0: Going Social 1.7 Software Technologies 1.8 Keeping Up to Date with Information Technologies 1.9 Wrap-Up
1.1 Introduction Welcome to Java—the world’s most widely used computer programming language. In this book, you’ll learn object-oriented programming—today’s key programming methodology. You’ll create and work with many software objects in this text. Java is the preferred language for meeting many organizations’ enterprise programming needs. Java has also become the language of choice for implementing Internet-based applications and software for devices that communicate over a network. In use today are more than a billion general-purpose computers and billions more Java-enabled cell phones, smartphones and handheld devices (such as tablet computers). According to a study by eMarketer, the number of mobile Internet users will reach approximately 134 million by 2013.1 Other studies have projected smartphone sales to surpass personal computer sales in 20112 and tablet sales to account for over 20% of all personal computer sales by 2015.3 By 2014, the smartphone applications market is expected to exceed $40 billion,4 which is creating significant opportunities for programming mobile applications.
Java Editions: SE, EE and ME Java for Programmers, Second Edition is based on Java Standard Edition 6 (Java SE 6) and Java SE 7. Java is used in such a broad spectrum of applications that it has two other editions. The Java Enterprise Edition (Java EE), which we use later in the book, is geared toward developing large-scale, distributed networking applications and web-based applications. The Java Micro Edition (Java ME) is geared toward developing applications for small, memory-constrained devices, such as BlackBerry smartphones. Google’s Android operating system—used on numerous smartphones, tablets (small, lightweight mobile computers with touch screens), e-readers and other devices—uses a customized version of Java not based on Java ME.
1.2 Introduction to Object Technology Building software quickly, correctly and economically remains an elusive goal at a time when demands for new and more powerful software are soaring. Objects, or more precisely—as we’ll see in Chapter 3—the classes objects come from, are essentially reusable software components. There are date objects, time objects, audio objects, video objects, 1. 2. 3. 4.
www.circleid.com/posts/mobile_internet_users_to_reach_134_million_by_2013/. www.pcworld.com/article/171380/more_smartphones_than_desktop_pcs_by_2011.html. www.forrester.com/ER/Press/Release/0,1769,1340,00.html.
Inc., December 2010/January 2011, pages 116–123.
1.2 Introduction to Object Technology
3
automobile objects, people objects, etc. Almost any noun can be reasonably represented as a software object in terms of attributes (e.g., name, color and size) and behaviors (e.g., calculating, moving and communicating). Software developers are discovering that using a modular, object-oriented design and implementation approach can make software-development groups much more productive than was possible with earlier popular techniques like “structured programming”—object-oriented programs are often easier to understand, correct and modify.
The Automobile as an Object To help you understand objects and their contents, let’s begin with a simple analogy. Suppose you want to drive a car and make it go faster by pressing its accelerator pedal. What must happen before you can do this? Well, before you can drive a car, someone has to design it. A car typically begins as engineering drawings, similar to the blueprints that describe the design of a house. These drawings include the design for an accelerator pedal. The pedal hides from the driver the complex mechanisms that actually make the car go faster, just as the brake pedal hides the mechanisms that slow the car, and the steering wheel “hides” the mechanisms that turn the car. This enables people with little or no knowledge of how engines, braking and steering mechanisms work to drive a car easily. Just as you cannot cook meals in the kitchen of a blueprint, you cannot drive a car’s engineering drawings. Before you can drive a car, it must be built from the engineering drawings that describe it. A completed car has an actual accelerator pedal to make the car go faster, but even that’s not enough—the car won’t accelerate on its own (hopefully!), so the driver must press the pedal to accelerate the car. Methods and Classes Let’s use our car example to introduce some key object-oriented programming concepts. Performing a task in a program requires a method. The method houses the program statements that actually perform its tasks. The method hides these statements from its user, just as the accelerator pedal of a car hides from the driver the mechanisms of making the car go faster. In Java, we create a program unit called a class to house the set of methods that perform the class’s tasks. For example, a class that represents a bank account might contain one method to deposit money to an account, another to withdraw money from an account and a third to inquire what the account’s current balance is. A class is similar in concept to a car’s engineering drawings, which house the design of an accelerator pedal, steering wheel, and so on. Instantiation Just as someone has to build a car from its engineering drawings before you can actually drive a car, you must build an object of a class before a program can perform the tasks that the class’s methods define. The process of doing this is called instantiation. An object is then referred to as an instance of its class. Reuse Just as a car’s engineering drawings can be reused many times to build many cars, you can reuse a class many times to build many objects. Reuse of existing classes when building new classes and programs saves time and effort. Reuse also helps you build more reliable and effective systems, because existing classes and components often have gone through exten-
4
Chapter 1 Introduction
sive testing, debugging and performance tuning. Just as the notion of interchangeable parts was crucial to the Industrial Revolution, reusable classes are crucial to the software revolution that has been spurred by object technology.
Software Engineering Observation 1.1 Use a building-block approach to creating your programs. Avoid reinventing the wheel— use existing pieces wherever possible. This software reuse is a key benefit of object-oriented programming.
Messages and Methods Calls When you drive a car, pressing its gas pedal sends a message to the car to perform a task— that is, to go faster. Similarly, you send messages to an object. Each message is implemented as a method call that tells a method of the object to perform its task. For example, a program might call a particular bank account object’s deposit method to increase the account’s balance. Attributes and Instance Variables A car, besides having capabilities to accomplish tasks, also has attributes, such as its color, its number of doors, the amount of gas in its tank, its current speed and its record of total miles driven (i.e., its odometer reading). Like its capabilities, the car’s attributes are represented as part of its design in its engineering diagrams (which, for example, include an odometer and a fuel gauge). As you drive an actual car, these attributes are carried along with the car. Every car maintains its own attributes. For example, each car knows how much gas is in its own gas tank, but not how much is in the tanks of other cars. An object, similarly, has attributes that it carries along as it’s used in a program. These attributes are specified as part of the object’s class. For example, a bank account object has a balance attribute that represents the amount of money in the account. Each bank account object knows the balance in the account it represents, but not the balances of the other accounts in the bank. Attributes are specified by the class’s instance variables. Encapsulation Classes encapsulate (i.e., wrap) attributes and methods into objects—an object’s attributes and methods are intimately related. Objects may communicate with one another, but they’re normally not allowed to know how other objects are implemented—implementation details are hidden within the objects themselves. This information hiding, as we’ll see, is crucial to good software engineering. Inheritance A new class of objects can be created quickly and conveniently by inheritance—the new class absorbs the characteristics of an existing class, possibly customizing them and adding unique characteristics of its own. In our car analogy, an object of class “convertible” certainly is an object of the more general class “automobile,” but more specifically, the roof can be raised or lowered. Object-Oriented Analysis and Design (OOAD) Soon you’ll be writing programs in Java. How will you create the code (i.e., the program instructions) for your programs? Perhaps, like many programmers, you’ll simply turn on your computer and start typing. This approach may work for small programs (like the ones
1.3 Open Source Software
5
we present in the early chapters of the book), but what if you were asked to create a software system to control thousands of automated teller machines for a major bank? Or suppose you were asked to work on a team of 1,000 software developers building the next U.S. air traffic control system? For projects so large and complex, you should not simply sit down and start writing programs. To create the best solutions, you should follow a detailed analysis process for determining your project’s requirements (i.e., defining what the system is supposed to do) and developing a design that satisfies them (i.e., deciding how the system should do it). Ideally, you’d go through this process and carefully review the design (and have your design reviewed by other software professionals) before writing any code. If this process involves analyzing and designing your system from an object-oriented point of view, it’s called an object-oriented analysis and design (OOAD) process. Languages like Java are object oriented. Programming in such a language, called object-oriented programming (OOP), allows you to implement an object-oriented design as a working system.
The UML (Unified Modeling Language) Many different OOAD processes exist, but a single graphical language for communicating the results of any OOAD process has come into wide use. This language, known as the Unified Modeling Language (UML), is now the most widely used graphical scheme for modeling object-oriented systems. We present our first UML diagrams in Chapters 3 and 4, then use them in our deeper treatment of object-oriented programming through Chapter 11. In our ATM Software Engineering Case Study in Chapters 12–13 we present a simple subset of the UML’s features as we guide you through an object-oriented design experience.
1.3 Open Source Software The Linux operating system is perhaps the greatest success of the open-source movement. Open-source software is a software development style that departs from the proprietary development that dominated software’s early years. With open-source development, individuals and companies contribute their efforts in developing, maintaining and evolving software in exchange for the right to use that software for their own purposes, typically at no charge. Open-source code is often scrutinized by a much larger audience than proprietary software, so errors often get removed faster. Open source also encourages more innovation. Sun open sourced its implementation of the Java Development Kit and many of its related Java technologies. Some organizations in the open-source community are the Eclipse Foundation (the Eclipse Integrated Development Environment helps Java programmers conveniently develop software), the Mozilla Foundation (creators of the Firefox web browser), the Apache Software Foundation (creators of the Apache web server used to develop webbased applications) and SourceForge (which provides the tools for managing open source projects—it has over 260,000 of them under development). Rapid improvements to computing and communications, decreasing costs and open-source software have made it much easier and more economical to create a software-based business now than just a few decades ago. A great example is Facebook, which was launched from a college dorm room and built with open-source software.5 5.
developers.facebook.com/opensource/.
6
Chapter 1 Introduction
The Linux kernel is the core of the operating system. It’s developed by a loosely organized team of volunteers, and is popular in servers, personal computers and embedded systems. Unlike that of proprietary operating systems like Microsoft’s Windows and Apple’s Mac OS X, Linux source code (the program code) is available to the public for examination and modification and is free to download and install. As a result, users of the operating system benefit from a community of developers actively debugging and improving the kernel, an absence of licensing fees and restrictions, and the ability to completely customize the operating system to meet specific needs. A variety of issues—such as Microsoft’s market power, the small number of userfriendly Linux applications and the diversity of Linux distributions, such as Red Hat Linux, Ubuntu Linux and many others—have prevented widespread Linux use on desktop computers. But Linux has become extremely popular on servers and in embedded systems, such as Google’s Android-based smartphones.
Android Android—the fastest growing mobile and smartphone operating system—is based on the Linux kernel and Java. Experienced Java programmers can quickly dive into Android development. One benefit of developing Android apps is the openness of the platform. The operating system is open source and free. The Android operating system was developed by Android, Inc., which was acquired by Google in 2005. In 2007, the Open Handset Alliance™—a consortium of 34 companies initially and 79 by 2010—was formed to continue developing Android. As of December 2010, more than 300,000 Android smartphones were being activated each day!6 Android smartphones are now outselling iPhones.7 The Android operating system is used in numerous smartphones (such as the Motorola Droid, HTC EVO™ 4G, Samsung Vibrant™ and many more), e-reader devices (such as the Barnes and Noble Nook™), tablet computers (such as the Motorola Xoom, the Dell Streak, the Samsung Galaxy Tab and more), in-store touch-screen kiosks, cars, robots and multimedia players. Android smartphones include the functionality of a mobile phone, Internet client (for web browsing and Internet communication), MP3 player, gaming console, digital camera and more, wrapped into handheld devices with full-color multitouch screens—these allow you to control the device with gestures involving one touch or multiple simultaneous touches. You can download apps directly onto your Android device through Android Market and other app marketplaces. As of early 2011, there were over 280,000 apps in Google’s Android Market. Android App-Development Chapters on the Companion Website Because of the tremendous interest in Android-based devices and apps, we’ve included on the book’s website a three-chapter introduction to Android app development from our new book, Android for Programmers: An App-Driven Approach. After you learn Java, you’ll find it straightforward to begin developing and running Android apps. You can place your apps on the online Android Market (www.market.android.com).
6. 7.
www.pcmag.com/article2/0,2817,2374076,00.asp. mashable.com/2010/08/02/android-outselling-iphone-2/.
1.4 Java and a Typical Java Development Environment
7
1.4 Java and a Typical Java Development Environment The microprocessor revolution’s most important contribution to date is that it made possible the development of personal computers. Microprocessors are having a profound impact in intelligent consumer-electronic devices. Recognizing this, Sun Microsystems in 1991 funded an internal corporate research project led by James Gosling, which resulted in a C++-based object-oriented programming language Sun called Java. A key goal of Java is to be able to write programs that will run on a great variety of computer systems and computer-control devices. This is sometimes called “write once, run anywhere.” The web exploded in popularity in 1993, and Sun saw the potential of using Java to add dynamic content, such as interactivity and animations, to web pages. Java garnered the attention of the business community because of the phenomenal interest in the web. Java is now used to develop large-scale enterprise applications, to enhance the functionality of web servers (the computers that provide the content we see in our web browsers), to provide applications for consumer devices (e.g., cell phones, smartphones, television set-top boxes and more) and for many other purposes. Sun Microsystems was acquired by Oracle in 2009. At the JavaOne 2010 conference, Oracle announced that 97% of enterprise desktops, three billion handsets, and 80 million television devices run Java. There are currently over 9 million Java developers, up from 4.5 million in 2005.8 Java is now the most widely used software development language in the world.
Java Class Libraries You can create each class and method you need to form your Java programs. However, most Java programmers take advantage of the rich collections of existing classes and methods in the Java class libraries, which are also known as the Java APIs (Application Programming Interfaces).
Performance Tip 1.1 Using Java API classes and methods instead of writing your own versions can improve program performance, because they’re carefully written to perform efficiently. This also shortens program development time.
Portability Tip 1.1 Although it’s easier to write portable programs (i.e., programs that can run on many different types of computers) in Java than in most other programming languages, differences between compilers, JVMs and computers can make portability difficult to achieve. Simply writing programs in Java does not guarantee portability.
We now explain the commonly used steps in creating and executing a Java application using a Java development environment (illustrated in Figs. 1.1–1.5). Java programs normally go through five phases—edit, compile, load, verify and execute. We discuss these phases in the context of the Java SE Development Kit (JDK). You can download the most up-to-date JDK and its documentation from www.oracle.com/technetwork/java/ javase/downloads/index.html. Read the Before You Begin section of this book to ensure that
8.
jaxenter.com/how-many-java-developers-are-there-10462.html.
8
Chapter 1 Introduction
you set up your computer properly to compile and execute Java programs. You may also want to visit Oracle’s New to Java Center at: www.oracle.com/technetwork/topics/newtojava/overview/index.html
[Note: This website provides installation instructions for Windows, Linux and Mac OS X. If you aren’t using one of these operating systems, refer to the documentation for your system’s Java environment. If you encounter a problem with this link or any others referenced in this book, please check www.deitel.com/books/javafp2/ for errata and please notify us by e-mail at [email protected].]
Phase 1: Creating a Program Phase 1 consists of editing a file with an editor program, normally known simply as an editor (Fig. 1.1). You type a Java program (typically referred to as source code) using the editor, make any necessary corrections and save the program on a secondary storage device, such as your hard drive. A file name ending with the .java extension indicates that the file contains Java source code.
Phase 1: Edit
Editor Disk
Program is created in an editor and stored on disk in a file whose name ends with .java
Fig. 1.1 | Typical Java development environment—editing phase. Two editors widely used on Linux systems are vi and emacs. On Windows, Notepad will suffice. Many freeware and shareware editors are also available online, including EditPlus (www.editplus.com), TextPad (www.textpad.com) and jEdit (www.jedit.org). For organizations that develop substantial information systems, integrated development environments (IDEs) are available from many major software suppliers. IDEs provide tools that support the software development process, including editors for writing and editing programs and debuggers for locating logic errors—errors that cause programs to execute incorrectly. Popular IDEs include Eclipse (www.eclipse.org) and NetBeans (www.netbeans.org).
Phase 2: Compiling a Java Program into Bytecodes In Phase 2, you use the command javac (the Java compiler) to compile a program (Fig. 1.2). For example, to compile a program called Welcome.java, you’d type javac Welcome.java
in the command window of your system (i.e., the Command Prompt in Windows, the shell prompt in Linux or the Terminal application in Mac OS X). If the program compiles, the compiler produces a .class file called Welcome.class that contains the compiled version of the program. The Java compiler translates Java source code into bytecodes that represent the tasks to execute in the execution phase (Phase 5). Bytecodes are executed by the Java Virtual Machine (JVM)—a part of the JDK and the foundation of the Java platform. A virtual
1.4 Java and a Typical Java Development Environment
Phase 2: Compile
Compiler Disk
9
Compiler creates bytecodes and stores them on disk in a file whose name ends with .class
Fig. 1.2 | Typical Java development environment—compilation phase. machine (VM) is a software application that simulates a computer but hides the underlying operating system and hardware from the programs that interact with it. If the same VM is implemented on many computer platforms, applications that it executes can be used on all those platforms. The JVM is one of the most widely used virtual machines. Microsoft’s .NET uses a similar virtual-machine architecture. Unlike machine language, which is dependent on specific computer hardware, bytecodes are platform independent—they do not depend on a particular hardware platform. So, Java’s bytecodes are portable—without recompiling the source code, the same bytecodes can execute on any platform containing a JVM that understands the version of Java in which the bytecodes were compiled. The JVM is invoked by the java command. For example, to execute a Java application called Welcome, you’d type the command java Welcome
in a command window to invoke the JVM, which would then initiate the steps necessary to execute the application. This begins Phase 3.
Phase 3: Loading a Program into Memory In Phase 3, the JVM places the program in memory to execute it—this is known as loading (Fig. 1.3).The JVM’s class loader takes the .class files containing the program’s bytecodes and transfers them to primary memory. The class loader also loads any of the .class files provided by Java that your program uses. The .class files can be loaded from a disk on your system or over a network (e.g., your local college or company network, or the Internet). Primary Memory Phase 3: Load
Class Loader Class loader reads .class files containing bytecodes from disk and puts those bytecodes in memory ...
Disk
Fig. 1.3 | Typical Java development environment—loading phase. Phase 4: Bytecode Verification In Phase 4, as the classes are loaded, the bytecode verifier examines their bytecodes to ensure that they’re valid and do not violate Java’s security restrictions (Fig. 1.4). Java enforces
10
Chapter 1
Introduction
strong security to make sure that Java programs arriving over the network do not damage your files or your system (as computer viruses and worms might). Primary Memory Phase 4: Verify
Bytecode Verifier Bytecode verifier confirms that all bytecodes are valid and do not violate Java’s security restrictions ...
Fig. 1.4 | Typical Java development environment—verification phase. Phase 5: Execution In Phase 5, the JVM executes the program’s bytecodes, thus performing the actions specified by the program (Fig. 1.5). In early Java versions, the JVM was simply an interpreter for Java bytecodes. This caused most Java programs to execute slowly, because the JVM would interpret and execute one bytecode at a time. Some modern computer architectures can execute several instructions in parallel. Today’s JVMs typically execute bytecodes using a combination of interpretation and so-called just-in-time (JIT) compilation. In this process, the JVM analyzes the bytecodes as they’re interpreted, searching for hot spots— parts of the bytecodes that execute frequently. For these parts, a just-in-time (JIT) compiler—known as the Java HotSpot compiler—translates the bytecodes into the underlying computer’s machine language. When the JVM encounters these compiled parts again, the faster machine-language code executes. Thus Java programs actually go through two compilation phases—one in which source code is translated into bytecodes (for portability across JVMs on different computer platforms) and a second in which, during execution, Primary Memory Phase 5: Execute
Java Virtual Machine (JVM)
...
To execute the program, the JVM reads bytecodes and just-in-time (JIT) compiles (i.e., translates) them into a language that the computer can understand. As the program executes, it may store data values in primary memory.
Fig. 1.5 | Typical Java development environment—execution phase.
1.5 Test-Driving a Java Application
11
the bytecodes are translated into machine language for the actual computer on which the program executes.
Problems That May Occur at Execution Time Programs might not work on the first try. Each of the preceding phases can fail because of various errors that we’ll discuss throughout this book. For example, an executing program might try to divide by zero (an illegal operation for whole-number arithmetic in Java). This would cause the Java program to display an error message. If this occurred, you’d have to return to the edit phase, make the necessary corrections and proceed through the remaining phases again to determine that the corrections fixed the problem(s). [Note: Most programs in Java input or output data. When we say that a program displays a message, we normally mean that it displays that message on your computer’s screen. Messages and other data may be output to other devices, such as disks and hardcopy printers, or even to a network for transmission to other computers.]
Common Programming Error 1.1 Errors such as division by zero occur as a program runs, so they’re called runtime errors or execution-time errors. Fatal runtime errors cause programs to terminate immediately without having successfully performed their jobs. Nonfatal runtime errors allow programs to run to completion, often producing incorrect results.
1.5 Test-Driving a Java Application In this section, you’ll run and interact with your first Java application. You’ll begin by running an ATM application that simulates the transactions that take place when you use an ATM machine (e.g., withdrawing money, making deposits and checking your account balances). You’ll learn how to build this application in the object-oriented case study included in Chapters 12–13. For the purpose of this section, we assume you’re running Microsoft Windows.9 In the following steps, you’ll run the application and perform various transactions. The elements and functionality you see here are typical of what you’ll learn to program in this book. [Note: We use fonts to distinguish between features you see on a screen (e.g., the Command Prompt) and elements that are not directly related to a screen. Our convention is to emphasize screen features like titles and menus (e.g., the File menu) in a semibold sans-serif Helvetica font and to emphasize nonscreen elements, such as file names or input (e.g., ProgramName.java) in a sans-serif Lucida font. As you’ve already noticed, the defining occurrence of each key term in the text is set in bold. In the figures in this section, we highlight in gray the user input required by each step and point out significant parts of the application. To make these features more visible, we’ve changed the background color of the Command Prompt windows to white and the foreground color to black.] This is a simple text-only version. Later in the book, you’ll learn the techniques to rework this using GUI (graphical user interface) techniques.
9.
At www.deitel.com/books/javafp2/, we provide videos that help you get started with popular integrated development environments (IDEs) Eclipse and NetBeans.
12
Chapter 1
Introduction
1. Checking your setup. Read the Before You Begin section of the book to confirm that you’ve set up Java properly on your computer and that you’ve copied the book’s examples to your hard drive. 2. Locating the completed application. Open a Command Prompt window. This can be done by selecting Start > All Programs > Accessories > Command Prompt. Change to the ATM application directory by typing cd C:\examples\ch01\ATM, then press Enter (Fig. 1.6). The command cd is used to change directories. Using the cd command to change directories
File location of the ATM application
Fig. 1.6 | Opening a Command Prompt and changing directories. 3. Running the ATM application. Type the command java ATMCaseStudy and press Enter (Fig. 1.7). Recall that the java command, followed by the name of the application’s .class file (in this case, ATMCaseStudy), executes the application. Specifying the .class extension when using the java command results in an error. [Note: Java commands are case sensitive. It’s important to type the name of this application with a capital A, T and M in “ATM,” a capital C in “Case” and a capital S in “Study.” Otherwise, the application will not execute.] If you receive the error message, “Exception in thread "main" java.lang.NoClassDefFoundError: ATMCaseStudy," your system has a CLASSPATH problem. Please refer to the Before You Begin section of the book for instructions to help you fix this problem.
Fig. 1.7 | Using the java command to execute the ATM application. 4. Entering an account number. When the application first executes, it displays a "Welcome!" greeting and prompts you for an account number. Type 12345 at the "Please enter your account number:" prompt (Fig. 1.8) and press Enter. 5. Entering a PIN. Once a valid account number is entered, the application displays the prompt "Enter your PIN:". Type "54321" as your valid PIN (Personal Identification Number) and press Enter. The ATM main menu containing a list of
1.5 Test-Driving a Java Application
13
options will be displayed (Fig. 1.9). We’ll show how you can enter a PIN privately using a JPasswordField in Chapter 14. ATM welcome message
Enter account number prompt
Fig. 1.8 | Prompting the user for an account number. Enter valid PIN
ATM main menu
Fig. 1.9 | Entering a valid PIN number and displaying the ATM application’s main menu. 6. Viewing the account balance. Select option 1, "View my balance", from the ATM menu (Fig. 1.10). The application then displays two numbers—the Available balance ($1000.00) and the Total balance ($1200.00). The available balance is the maximum amount of money in your account which is available Account-balance information
Fig. 1.10 | ATM application displaying user account-balance information.
14
Chapter 1
Introduction
for withdrawal at a given time. In some cases, certain funds, such as recent deposits, are not immediately available for the user to withdraw, so the available balance may be less than the total balance, as it is here. After the account-balance information is shown, the application’s main menu is displayed again. 7. Withdrawing money from the account. Select option 2, "Withdraw cash", from the application menu. You’re then presented (Fig. 1.11) with a list of dollar amounts (e.g., 20, 40, 60, 100 and 200). You’re also given the option to cancel the transaction and return to the main menu. Withdraw $100 by selecting option 4. The application displays "Please take your cash now." and returns to the main menu. [Note: Unfortunately, this application only simulates the behavior of a real ATM and thus does not actually dispense money.] ATM withdrawal menu
Fig. 1.11 | Withdrawing money from the account and returning to the main menu. 8. Confirming that the account information has been updated. From the main menu, select option 1 again to view your current account balance (Fig. 1.12). Both the available balance and the total balance have been updated to reflect your withdrawal transaction.
Confirming updated account-balance information after withdrawal transaction
Fig. 1.12 | Checking the new balance.
1.6 Web 2.0: Going Social
15
9. Ending the transaction. To end your current ATM session, select option 4, "Exit", from the main menu (Fig. 1.13). The ATM will exit the system and display a goodbye message to the user. The application will then return to its original prompt, asking for the next user’s account number.
ATM goodbye message Account-number prompt for next user
Fig. 1.13 | Ending an ATM transaction session. 10. Exiting the ATM and closing the Command Prompt window. Most applications provide an option to exit and return to the Command Prompt directory from which the application was run. A real ATM does not provide a user with the option to turn off the ATM. Rather, when a user has completed all desired transactions and chosen the menu option to exit, the ATM resets itself and displays a prompt for the next user’s account number. As Fig. 1.13 illustrates, the ATM application here behaves similarly. Choosing the menu option to exit ends only the current user’s ATM session, not the entire ATM application. To actually exit the ATM application, click the close (x) button in the upper-right corner of the Command Prompt window. Closing the window causes the running application to terminate.
1.6 Web 2.0: Going Social The web literally exploded in the mid-to-late 1990s, but the “dot com” economic bust brought hard times in the early 2000s. The resurgence that began in 2004 or so has been named Web 2.0. Google is widely regarded as the signature company of Web 2.0. Some other companies with “Web 2.0 characteristics” are YouTube (video sharing), FaceBook (social networking), Twitter (microblogging), Groupon (social commerce), Foursquare (mobile check-in), Salesforce (business software offered as online services), Craigslist (free classified listings), Flickr (photo sharing), Second Life (a virtual world), Skype (Internet telephony) and Wikipedia (a free online encyclopedia).
Google In 1996, Stanford computer science Ph.D. candidates Larry Page and Sergey Brin began collaborating on a new search engine. In 1997, they changed the name to Google—a play on the mathematical term googol, a quantity represented by the number “one” followed by 100 “zeros” (or 10100)—a staggeringly large number. Google’s ability to return extremely accurate search results quickly helped it become the most widely used search engine and one of the most popular websites in the world. Google continues to be an innovator in search technologies. For example, Google Goggles is a fascinating mobile app (available on Android and iPhone) that allows you to
16
Chapter 1
Introduction
perform a Google search using a photo rather than entering text. You simply take pictures of landmarks, books (covers or barcodes), logos, art or wine bottle labels, and Google Goggles scans the photos and returns search results. You can also take a picture of text (for example, a restaurant menu or a sign) and Google Goggles will translate it for you.
Web Services and Mashups We include in this book a substantial treatment of web services (Chapter 28) and introduce the applications-development methodology of mashups in which you can rapidly develop powerful and intriguing applications by combining (often free) complementary web services and other forms of information feeds (Fig. 1.14). One of the first mashups was www.housingmaps.com, which quickly combines the real estate listings provided by www.craigslist.org with the mapping capabilities of Google Maps to offer maps that show the locations of apartments for rent in a given area. Web services source
How it’s used
Google Maps Facebook Foursquare LinkedIn YouTube Twitter Groupon Netflix eBay Wikipedia PayPal Last.fm Amazon eCommerce Salesforce.com Skype Microsoft Bing Flickr Zillow Yahoo Search WeatherBug
Mapping services Social networking Mobile check-in Social networking for business Video search Microblogging Social commerce Movie rentals Internet auctions Collaborative encyclopedia Payments Internet radio Shopping for books and more Customer Relationship Management (CRM) Internet telephony Search Photo sharing Real estate pricing Search Weather
Fig. 1.14 | Some popular web services (www.programmableweb.com/apis/ directory/1?sort=mashups).
Ajax Ajax is one of the premier Web 2.0 software technologies. Ajax helps Internet-based applications perform like desktop applications—a difficult task, given that such applications
1.6 Web 2.0: Going Social
17
suffer transmission delays as data is shuttled back and forth between your computer and server computers on the Internet. Using Ajax, applications like Google Maps have achieved excellent performance and approach the look-and-feel of desktop applications. Although we don’t discuss “raw” Ajax programming (which is quite complex) in this text, we do show in Chapter 27 how to build Ajax-enabled applications using JavaServer Faces (JSF) Ajax-enabled components.
Social Applications Over the last several years, there’s been a tremendous increase in the number of social applications on the web. Even though the computer industry is mature, these sites were still able to become phenomenally successful in a relatively short period of time. Figure 1.15 discusses a few of the social applications that are making an impact. Company
Description
Facebook
Facebook was launched from a Harvard dorm room in 2004 by classmates Mark Zuckerberg, Chris Hughes, Dustin Moskovitz and Eduardo Saverin and is already worth an estimated $70 billion. By January 2011, Facebook was the most active site on the Internet with more than 600 million users—nearly 9% of the Earth’s population—who spend 700 billion minutes on Facebook per month (www.time.com/time/specials/packages/article/0,28804,2036683_ 2037183,00.html). At its current growth rate (about 5% per month), Facebook will reach one billion users in 2012, out of the two billion Internet users! The activity on the site makes it extremely attractive for application developers. Each day, over 20 million applications are installed by Facebook users (www.facebook.com/press/info.php?statistics). Twitter was founded in 2006 by Jack Dorsey, Evan Williams and Isaac “Biz” Stone—all from the podcast company, Odeo. Twitter has revolutionized microblogging. Users post tweets—messages of up to 140 characters long. Approximately 95 million tweets are posted per day (twitter.com/about). You can follow the tweets of friends, celebrities, businesses, government representatives (including the U.S. President, who has 6.3 million followers), etc., or you can follow tweets by subject to track news, trends and more. At the time of this writing, Lady Gaga had the most followers (over 7.7 million). Twitter has become the point of origin for many breaking news stories worldwide. Groupon, a social commerce site, was launched by Andrew Mason in 2008. By January 2011, the company was valued around $15 billion, making it the fastest growing company ever! It’s now available in hundreds of markets worldwide. Groupon offers one daily deal in each market for restaurants, retailers, services, attractions and more. Deals are activated only after a minimum number of people sign up to buy the product or service. If you sign up for a deal and it has yet to meet the minimum, you might be inclined to tell others about the deal by email, Facebook, Twitter, etc. If the deal does not meet the minimum sales, it’s cancelled. One of the most successful national Groupon deals to date was a certificate for $50 worth of merchandise from a major apparel company for $25. Over 440,000 vouchers were sold in one day.
Twitter
Groupon
Fig. 1.15 | Social applications. (Part 1 of 2.)
18
Chapter 1
Introduction
Company
Description
Foursquare
Foursquare—launched in 2009 by Dennis Crowley and Naveen Selvadurai—is a mobile check-in application that allows you to notify your friends of your whereabouts. You can download the app to your smartphone and link it to your Facebook and Twitter accounts so your friends can follow you from multiple platforms. If you do not have a smartphone, you can check in by text message. Foursquare uses GPS to determine your exact location. Businesses use Foursquare to send offers to users in the area. Launched in March 2009, Foursquare already has over 5 million users worldwide. Skype is a software product that allows you to make mostly free voice and video calls over the Internet using a technology called VoIP (Voice over IP; IP stands for Internet Protocol). Skype was founded in 2003 by Niklas Zennström and Dane Janus Friis. Just two years later, the company was sold to eBay for $2.6 billion. YouTube is a video-sharing site that was founded in 2005. Within one year, the company was purchased by Google for $1.65 billion. YouTube now accounts for 10% of all Internet traffic (www.webpronews.com/topnews/2010/04/16/ facebook-and-youtube-get-the-most-business-internet-traffic). Within one week of the release of Apple’s iPhone 3GS—the first iPhone model to offer video—mobile uploads to YouTube grew 400% (www.hypebot.com/hypebot/ 2009/06/youtube-reports-1700-jump-in-mobile-video.html).
Skype
YouTube
Fig. 1.15 | Social applications. (Part 2 of 2.)
1.7 Software Technologies Figure 1.16 lists a number of buzzwords that you’ll hear in the software development community. We’ve created Resource Centers on most of these topics, with more on the way.
Technology
Description
Agile software development
Agile software development is a set of methodologies that try to get software implemented faster and using fewer resources than previous methodologies. Check out the Agile Alliance (www.agilealliance.org) and the Agile Manifesto (www.agilemanifesto.org). Refactoring involves reworking programs to make them clearer and easier to maintain while preserving their correctness and functionality. It’s widely employed with agile development methodologies. Many IDEs contain builtin refactoring tools to do major portions of the reworking automatically. Design patterns are proven architectures for constructing flexible and maintainable object-oriented software. The field of design patterns tries to enumerate those recurring patterns, encouraging software designers to reuse them to develop better-quality software using less time, money and effort.
Refactoring
Design patterns
Fig. 1.16 | Software technologies. (Part 1 of 2.)
1.7 Software Technologies
19
Technology
Description
LAMP
MySQL is an open-source database management system. PHP is the most popular open-source server-side “scripting” language for developing web applications. LAMP is an acronym for the open-source technologies that many developers use to build web applications—it stands for Linux, Apache, MySQL and PHP (or Perl or Python—two other scripting languages). Software has generally been viewed as a product; most software still is offered this way. To run an application, you buy it from a software vendor. You then install it on your computer and run it as needed. As new versions appear, you upgrade the software, often at considerable expense. This process can be cumbersome for organizations with tens of thousands of systems that must be maintained on a diverse array of computer equipment. With Software as a Service (SaaS), the software runs on servers elsewhere on the Internet. When that server is updated, all clients worldwide see the new capabilities—no local installation is needed. You access the service through a browser. Browsers are quite portable, so you can run the same applications on a wide variety of computers from anywhere in the world. Salesforce.com, Google, and Microsoft’s Office Live and Windows Live all offer SaaS. Platform as a Service (PaaS) provides a computing platform for developing and running applications as a service over the web, rather than installing the tools on your computer. PaaS providers include Google App Engine, Amazon EC2, Bungee Labs and more. SaaS and PaaS are examples of cloud computing in which software, platforms and infrastructure (e.g., processing power and storage) are hosted on demand over the Internet. This provides users with flexibility, scalability and cost savings. For example, consider a company’s data storage needs which can fluctuate significantly over the course of a year. Rather than investing in large-scale storage hardware—which can be costly to purchase, maintain and secure, and would most likely not be used to capacity at all times—the company could purchase cloud-based services (such as Amazon S3, Google Storage, Microsoft Windows Azure™, Nirvanix™ and others) dynamically as needed. Software Development Kits (SDKs) include the tools and documentation developers use to program applications. For example, you’ll use the Java Development Kit (JDK) to build and run Java applications.
Software as a Service (SaaS)
Platform as a Service (PaaS)
Cloud computing
Software Development Kit (SDK)
Fig. 1.16 | Software technologies. (Part 2 of 2.) Figure 1.17 describes software product release categories. Version
Description
Alpha
Alpha software is the earliest release of a software product that’s still under active development. Alpha versions are often buggy, incomplete and unstable, and are released to a relatively small number of developers for testing new features, getting early feedback, etc.
Fig. 1.17 | Software product release terminology. (Part 1 of 2.)
20
Chapter 1
Introduction
Version
Description
Beta
Beta versions are released to a larger number of developers later in the development process after most major bugs have been fixed and new features are nearly complete. Beta software is more stable, but still subject to change. Release candidates are generally feature complete and (supposedly) bug free, and ready for use by the community, which provides a diverse testing environment—the software is used on different systems, with varying constraints and for a variety of purposes. Any bugs that appear are corrected and eventually the final product is released to the general public. Software companies often distribute incremental updates over the Internet. Software that’s developed using this approach generally does not have version numbers (for example, Google search or Gmail). The software, which is hosted in the cloud (not installed on your computer), is constantly evolving so that users always have the latest version.
Release candidates
Continuous beta
Fig. 1.17 | Software product release terminology. (Part 2 of 2.)
1.8 Keeping Up to Date with Information Technologies Figure 1.18 lists key technical and business publications that will help you stay up-to-date with the latest news and trends and technology. You can also find a growing list of Internet- and web-related Resource Centers at www.deitel.com/ResourceCenters.html. Publication
URL
Bloomberg BusinessWeek CNET Computer World Engadget eWeek Fast Company Fortune InfoWorld Mashable PCWorld SD Times Slashdot Smarter Technology Technology Review Techcrunch Wired
www.businessweek.com news.cnet.com www.computerworld.com www.engadget.com www.eweek.com www.fastcompany.com/ money.cnn.com/magazines/fortune/ www.infoworld.com mashable.com www.pcworld.com www.sdtimes.com slashdot.org/ www.smartertechnology.com technologyreview.com techcrunch.com www.wired.com
Fig. 1.18 | Technical and business publications.
1.9 Wrap-Up
21
1.9 Wrap-Up In this chapter we discussed computer hardware, software, programming languages and operating systems. We overviewed a typical Java program development environment and you test-drove a Java application. We introduced the basics of object technology. We also discussed some key software development terminology. In Chapter 2, you’ll create your first Java applications. You’ll see how programs display messages on the screen and obtain information from the user at the keyboard for processing. You’ll use Java’s primitive data types and arithmetic operators in calculations and use Java’s equality and relational operators to write simple decision-making statements.
2 Introduction to Java Applications
What’s in a name? That which we call a rose By any other name would smell as sweet.
Objectives
—William Shakespeare
In this chapter you’ll learn:
When faced with a decision, I always ask, “What would be the most fun?”
I
To write simple Java applications.
I
To use input and output statements.
—Peggy Walker
I
Java’s primitive types.
I
To use arithmetic operators.
The chief merit of language is clearness.
I
The precedence of arithmetic operators.
I
To write decision-making statements.
I
To use relational and equality operators.
—Galen
One person can make a difference and every person should try. —John F. Kennedy
2.1 Introduction
2.1 Introduction 2.2 Your First Program in Java: Printing a Line of Text 2.3 Modifying Your First Java Program 2.4 Displaying Text with printf 2.5 Another Application: Adding Integers
23
2.6 Arithmetic 2.7 Decision Making: Equality and Relational Operators 2.8 Wrap-Up
2.1 Introduction This chapter introduces Java application programming. We begin with examples of programs that display messages on the screen. We then present a program that obtains two numbers from a user, calculates their sum and displays the result. The last example demonstrates how to make decisions. The application compares numbers, then displays messages that show the comparison results. This chapter uses tools from the JDK to compile and run programs. We’ve also posted Dive Into® videos at www.deitel.com/books/javafp2/ to help you get started with the popular Eclipse and NetBeans integrated development environments.
2.2 Your First Program in Java: Printing a Line of Text A Java application is a computer program that executes when you use the java command to launch the Java Virtual Machine (JVM). Later in this section we’ll discuss how to compile and run a Java application. First we consider a simple application that displays a line of text. Figure 2.1 shows the program followed by a box that displays its output. The program includes line numbers. We’ve added these for instructional purposes—they’re not part of a Java program. This example illustrates several important Java features. We’ll see that line 9 does the real work—displaying the phrase Welcome to Java Programming! on the screen. 1 2 3 4 5 6 7 8 9 10 11
// Fig. 2.1: Welcome1.java // Text-printing program. public class Welcome1 { // main method begins execution of Java application public static void main( String[] args ) { System.out.println( "Welcome to Java Programming!" ); } // end method main } // end class Welcome1
Welcome to Java Programming!
Fig. 2.1 | Text-printing program. Commenting Your Programs By convention, we begin every program with a comment indicating the figure number and file name. The comment in line 1 begins with //, indicating that it is an end-of-line com-
24
Chapter 2
Introduction to Java Applications
ment—it terminates at the end of the line on which the // appears. An end-of-line comment need not begin a line; it also can begin in the middle of a line and continue until the end (as in lines 10 and 11). Line 2 is a comment that describes the purpose of the program. Java also has traditional comments, which can be spread over several lines as in /* This is a traditional comment. It can be split over multiple lines */
These begin and end with delimiters, /* and */. The compiler ignores all text between the delimiters. Java incorporated traditional comments and end-of-line comments from the C and C++ programming languages, respectively. In this book, we use only // comments. Java provides comments of a third type, Javadoc comments. These are delimited by /** and */. The compiler ignores all text between the delimiters. Javadoc comments enable you to embed program documentation directly in your programs. Such comments are the preferred Java documenting format in industry. The javadoc utility program (part of the Java SE Development Kit) reads Javadoc comments and uses them to prepare your program’s documentation in HTML format.
Using Blank Lines Line 3 is a blank line. Blank lines, space characters and tabs make programs easier to read. Together, they’re known as white space (or whitespace). The compiler ignores white space. Declaring a Class Line 4 begins a class declaration for class Welcome1. Every Java program consists of at least one class that you (the programmer) define. The class keyword introduces a class declaration and is immediately followed by the class name (Welcome1). Keywords are reserved for use by Java and are always spelled with all lowercase letters. The complete list of keywords is shown in Appendix C. Class Names and Identifiers By convention, class names begin with a capital letter and capitalize the first letter of each word they include (e.g., SampleClassName). A class name is an identifier—a series of characters consisting of letters, digits, underscores ( _ ) and dollar signs ($) that does not begin with a digit and does not contain spaces. Some valid identifiers are Welcome1, $value, _value, m_inputField1 and button7. The name 7button is not a valid identifier because it begins with a digit, and the name input field is not a valid identifier because it contains a space. Normally, an identifier that does not begin with a capital letter is not a class name. Java is case sensitive—uppercase and lowercase letters are distinct—so value and Value are different (but both valid) identifiers. In Chapters 4–7, every class we define begins with the public keyword. For now, we simply require this keyword. For our application, the file name is Welcome1.java. You’ll learn more about public and non-public classes in Chapter 8.
Common Programming Error 2.1 A public class must be placed in a file that has the same name as the class (in terms of both spelling and capitalization) plus the .java extension; otherwise, a compilation error occurs. For example, public class Welcome must be placed in a file named Welcome.java.
2.2 Your First Program in Java: Printing a Line of Text
25
A left brace (as in line 5), {, begins the body of every class declaration. A corresponding right brace (at line 11), }, must end each class declaration. Lines 6–10 are indented.
Good Programming Practice 2.1 Indent the entire body of each class declaration one “level” between the left brace and the right brace that delimit the body of the class. We recommend using three spaces to form a level of indent. This format emphasizes the class declaration’s structure and makes it easier to read.
Good Programming Practice 2.2 Many IDEs insert indentation for you in all the right places. The Tab key may also be used to indent code, but tab stops vary among text editors. Most IDEs allow you to configure tabs such that a specified number of spaces is inserted each time you press the Tab key.
Declaring a Method Line 6 is an end-of-line comment indicating the purpose of lines 7–10. Line 7 is the starting point of every Java application. The parentheses after the identifier main indicate that it’s a method. Java class declarations normally contain one or more methods. For a Java application, one of the methods must be called main and must be defined as shown in line 7; otherwise, the Java Virtual Machine (JVM) will not execute the application. Methods perform tasks and can return information when they complete their tasks. Keyword void indicates that this method will not return any information. In line 7, the String[] args in parentheses is a required part of the method main’s declaration—we discuss this in Chapter 7. The left brace in line 8 begins the body of the method declaration. A corresponding right brace ends it (line 10). Line 9 in the method body is indented between the braces.
Good Programming Practice 2.3 Indent the entire body of each method declaration one “level” between the braces that define the body of the method.
Performing Output with System.out.println Line 9 instructs the computer to perform an action—namely, to print the string of characters contained between the double quotation marks (but not the quotation marks themselves). White-space characters in strings are not ignored by the compiler. Strings cannot span multiple lines of code, but as you’ll see later, this does not restrict you from using long strings in your code. The System.out object is known as the standard output object. It allows a Java applications to display information in the command window from which it executes. In recent versions of Microsoft Windows, the command window is the Command Prompt. In UNIX/Linux/Mac OS X, the command window is called a terminal window or a shell. Many programmers call it simply the command line. Method System.out.println displays a line of text in the command window. The string in the parentheses in line 9 is the method’s argument. When System.out.println completes its task, it positions the output cursor (the location where the next character will be displayed) at the beginning of the next line in the command window. The entire line 9, including System.out.println, the argument "Welcome to Java Programming!" in the parentheses and the semicolon (;), is called a statement. A method
26
Chapter 2
Introduction to Java Applications
typically contains one or more statements that perform its task. Most statements end with a semicolon. When the statement in line 9 executes, it displays Welcome to Java Programming! in the command window.
Using End-of-Line Comments on Right Braces for Readability We include an end-of-line comment after a closing brace that ends a method declaration and after a closing brace that ends a class declaration. For example, line 10 indicates the closing brace of method main, and line 11 indicates the closing brace of class Welcome1. Each comment indicates the method or class that the right brace terminates. Compiling and Executing Your First Java Application We assume you’re using the Java Development Kit’s command-line tools, not an IDE. Our Java Resource Centers at www.deitel.com/ResourceCenters.html provide links to tutorials that help you get started with several popular Java development tools, including NetBeans™, Eclipse™ and others. We’ve also posted NetBeans and Eclipse videos at www.deitel.com/books/javafp2/ to help you get started using these popular IDEs. To prepare to compile the program, open a command window and change to the directory where the program is stored. Many operating systems use the command cd to change directories. On Windows, for example, cd c:\examples\ch02\fig02_01
changes to the fig02_01 directory. On UNIX/Linux/Max OS X, the command cd ~/examples/ch02/fig02_01
changes to the fig02_01 directory. To compile the program, type javac Welcome1.java
If the program contains no syntax errors, this command creates a new file called (known as the class file for Welcome1) containing the platform-independent Java bytecodes that represent our application. When we use the java command to execute the application on a given platform, the JVM will translate these bytecodes into instructions that are understood by the underlying operating system and hardware. Welcome1.class
Error-Prevention Tip 2.1 When attempting to compile a program, if you receive a message such as “bad command or filename,” “javac: command not found” or “'javac' is not recognized as an internal or external command, operable program or batch file,” then your Java software installation was not completed properly. If you’re using the JDK, this indicates that the system’s PATH environment variable was not set properly. Please carefully review the installation instructions in the Before You Begin section of this book. On some systems, after correcting the PATH, you may need to reboot your computer or open a new command window for these settings to take effect.
Error-Prevention Tip 2.2 Each syntax-error message contains the file name and line number where the error occurred. For example, Welcome1.java:6 indicates that an error occurred at line 6 in Welcome1.java. The rest of the message provides information about the syntax error.
2.3 Modifying Your First Java Program
27
Error-Prevention Tip 2.3 The compiler error message “class Welcome1 is public, should be declared in a file named Welcome1.java” indicates that the file name does not match the name of the public class in the file or that you typed the class name incorrectly when compiling the class.
Figure 2.2 shows the program of Fig. 2.1 executing in a Microsoft® Windows® 7 Command Prompt window. To execute the program, type java Welcome1. This command launches the JVM, which loads the .class file for class Welcome1. The command omits the .class file-name extension; otherwise, the JVM will not execute the program. The JVM calls method main. Next, the statement at line 9 of main displays "Welcome to Java Programming!" [Note: Many environments show command prompts with black backgrounds and white text. We adjusted these settings in our environment to make our screen captures more readable.]
You type this command to execute the application
The program outputs to the screen Welcome to Java Programming!
Fig. 2.2 | Executing Welcome1 from the Command Prompt.
Error-Prevention Tip 2.4 When attempting to run a Java program, if you receive a message such as “Exception in your CLASSPATH environment variable has not been set properly. Please carefully review the installation instructions in the Before You Begin section of this book. On some systems, you may need to reboot your computer or open a new command window after configuring the CLASSPATH. thread "main" java.lang.NoClassDefFoundError: Welcome1,”
2.3 Modifying Your First Java Program In this section, we modify the example in Fig. 2.1 to print text on one line by using multiple statements and to print text on several lines by using a single statement.
Displaying a Single Line of Text with Multiple Statements Welcome to Java Programming! can be displayed several ways. Class Welcome2, shown in Fig. 2.3, uses two statements (lines 9–10) to produce the output shown in Fig. 2.1. [Note: From this point forward, we highlight the new and key features in each code listing, as we’ve done for lines 9–10.] The program is similar to Fig. 2.1, so we discuss only the changes here. Line 2 is an end-of-line comment stating the purpose of the program. Line 4 begins the Welcome2 class declaration. Lines 9–10 of method main display one line of text. The first statement uses System.out’s method print to display a string. Each print or println statement resumes displaying characters from where the last print or println statement stopped displaying
28
Chapter 2
Introduction to Java Applications
characters. Unlike println, after displaying its argument, print does not position the output cursor at the beginning of the next line in the command window—the next character the program displays will appear immediately after the last character that print displays. Thus, line 10 positions the first character in its argument (the letter “J”) immediately after the last character that line 9 displays (the space character before the string’s closing double-quote character). 1 2 3 4 5 6 7 8 9 10 11 12
// Fig. 2.3: Welcome2.java // Printing a line of text with multiple statements. public class Welcome2 { // main method begins execution of Java application public static void main( String[] args ) { System.out.print( "Welcome to " ); System.out.println( "Java Programming!" ); } // end method main } // end class Welcome2
Welcome to Java Programming!
Fig. 2.3 | Printing a line of text with multiple statements. Displaying Multiple Lines of Text with a Single Statement A single statement can display multiple lines by using newline characters, which indicate to System.out’s print and println methods when to position the output cursor at the beginning of the next line in the command window. Like blank lines, space characters and tab characters, newline characters are white-space characters. The program in Fig. 2.4 outputs four lines of text, using newline characters to determine when to begin each new line. Most of the program is identical to those in Fig. 2.1 and Fig. 2.3. 1 2 3 4 5 6 7 8 9 10 11
// Fig. 2.4: Welcome3.java // Printing multiple lines of text with a single statement. public class Welcome3 { // main method begins execution of Java application public static void main( String[] args ) { System.out.println( "Welcome\nto\nJava\nProgramming!" ); } // end method main } // end class Welcome3
Welcome to Java Programming!
Fig. 2.4 | Printing multiple lines of text with a single statement.
2.4 Displaying Text with printf
29
Line 2 is a comment stating the program’s purpose. Line 4 begins the Welcome3 class declaration. Line 9 displays four separate lines of text in the command window. Normally, the characters in a string are displayed exactly as they appear in the double quotes. Note, however, that the paired characters \ and n (repeated three times in the statement) do not appear on the screen. The backslash (\) is an escape character. which has special meaning to System.out’s print and println methods. When a backslash appears in a string, Java combines it with the next character to form an escape sequence. The escape sequence \n represents the newline character. When a newline character appears in a string being output with System.out, the newline character causes the screen’s output cursor to move to the beginning of the next line in the command window. Figure 2.5 lists several common escape sequences and describes how they affect the display of characters in the command window. For the complete list of escape sequences, visit java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.10.6. Escape sequence \n \t \r
\\ \"
Description Newline. Position the screen cursor at the beginning of the next line. Horizontal tab. Move the screen cursor to the next tab stop. Carriage return. Position the screen cursor at the beginning of the current line—do not advance to the next line. Any characters output after the carriage return overwrite the characters previously output on that line. Backslash. Used to print a backslash character. Double quote. Used to print a double-quote character. For example, System.out.println( "\"in quotes\"" );
displays "in
quotes".
Fig. 2.5 | Some common escape sequences.
2.4 Displaying Text with printf The System.out.printf method (f means “formatted”) displays formatted data. Figure 2.6 uses this method to output the strings "Welcome to" and "Java Programming!". Lines 9–10 System.out.printf( "%s\n%s\n", "Welcome to", "Java Programming!" );
call method System.out.printf to display the program’s output. The method call specifies three arguments. When a method requires multiple arguments, they’re placed in a comma-separated list. Lines 9–10 represent only one statement. Java allows large statements to be split over many lines. We indent line 10 to indicate that it’s a continuation of line 9.
Common Programming Error 2.2 Splitting a statement in the middle of an identifier or a string is a syntax error.
30
1 2 3 4 5 6 7 8 9 10 11 12
Chapter 2
Introduction to Java Applications
// Fig. 2.6: Welcome4.java // Displaying multiple lines with method System.out.printf. public class Welcome4 { // main method begins execution of Java application public static void main( String[] args ) { System.out.printf( "%s\n%s\n", "Welcome to", "Java Programming!" ); } // end method main } // end class Welcome4
Welcome to Java Programming!
Fig. 2.6 | Displaying multiple lines with method System.out.printf. Method printf’s first argument is a format string that may consist of fixed text and format specifiers. Fixed text is output by printf just as it would be by print or println. Each format specifier is a placeholder for a value and specifies the type of data to output. Format specifiers also may include optional formatting information. Format specifiers begin with a percent sign (%) followed by a character that represents the data type. For example, the format specifier %s is a placeholder for a string. The format string in line 9 specifies that printf should output two strings, each followed by a newline character. At the first format specifier’s position, printf substitutes the value of the first argument after the format string. At each subsequent format specifier’s position, printf substitutes the value of the next argument. So this example substitutes "Welcome to" for the first %s and "Java Programming!" for the second %s. The output shows that two lines of text are displayed. We introduce various formatting features as they’re needed in our examples. Appendix G presents the details of formatting output with printf.
2.5 Another Application: Adding Integers Our next application reads (or inputs) two integers (whole numbers, such as –22, 7, 0 and 1024) typed by a user at the keyboard, computes their sum and displays it. This program must keep track of the numbers supplied by the user for the calculation later in the program. Programs remember numbers and other data in the computer’s memory and access that data through program elements called variables. The program of Fig. 2.7 demonstrates these concepts. In the sample output, we use bold text to identify the user’s input (i.e., 45 and 72). 1 2 3 4
// Fig. 2.7: Addition.java // Addition program that displays the sum of two numbers. import java.util.Scanner; // program uses class Scanner
Fig. 2.7 | Addition program that displays the sum of two numbers. (Part 1 of 2.)
2.5 Another Application: Adding Integers
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
31
public class Addition { // main method begins execution of Java application public static void main( String[] args ) { // create a Scanner to obtain input from the command window Scanner input = new Scanner( System.in ); int number1; // first number to add int number2; // second number to add int sum; // sum of number1 and number2 System.out.print( "Enter first integer: " ); // prompt number1 = input.nextInt(); // read first number from user System.out.print( "Enter second integer: " ); // prompt number2 = input.nextInt(); // read second number from user sum = number1 + number2; // add numbers, then store total in sum System.out.printf( "Sum is %d\n", sum ); // display sum } // end method main } // end class Addition
Enter first integer: 45 Enter second integer: 72 Sum is 117
Fig. 2.7 | Addition program that displays the sum of two numbers. (Part 2 of 2.) Declarations Lines 1–2 Import
// Fig. 2.7: Addition.java // Addition program that displays the sum of two numbers.
state the figure number, file name and purpose of the program. A great strength of Java is its rich set of predefined classes that you can reuse rather than “reinventing the wheel.” These classes are grouped into packages—named groups of related classes—and are collectively referred to as the Java class library, or the Java Application Programming Interface (Java API). Line 3 import java.util.Scanner; // program uses class Scanner
is an import declaration that helps the compiler locate a class that’s used in this program. It indicates that this example uses Java’s predefined Scanner class (discussed shortly) from package java.util.
Common Programming Error 2.3 All import declarations must appear before the first class declaration in the file. Placing an import declaration inside or after a class declaration is a syntax error.
32
Chapter 2
Introduction to Java Applications
Error-Prevention Tip 2.5 Forgetting to include an import declaration for a class used in your program typically results in a compilation error containing a message such as “cannot find symbol.” When this occurs, check that you provided the proper import declarations and that the names in them are correct, including proper capitalization.
Declaring Class Addition Line 5 begins the declaration of class Addition. The file name for this public class must be Addition.java. Remember that the body of each class declaration starts with an opening left brace (line 6) and ends with a closing right brace (line 27). The application begins execution with the main method (lines 8–26). The left brace (line 9) marks the beginning of method main’s body, and the corresponding right brace (line 26) marks its end. Method main is indented one level in the body of class Addition, and the code in the body of main is indented another level for readability. Declaring and Creating a Scanner to Obtain User Input from the Keyboard All Java variables must be declared with a name and a type before they can be used. A variable’s name can be any valid identifier. Like other statements, declaration statements end with a semicolon (;). Line 11 is a variable declaration statement that specifies the name (input) and type (Scanner) of a variable that’s used in this program. A Scanner enables a program to read data (e.g., numbers and strings) for use in a program. The data can come from many sources, such as the user at the keyboard or a file on disk. Before using a Scanner, you must create it and specify the source of the data. Line 11 initalizes Scanner variable input in its declaration with the result of the expression to the right of the equals sign—new Scanner(System.in). This expression uses the new keyword to create a Scanner object that reads keystrokes from the keyboard. The standard input object, System.in, enables applications to read bytes of information typed by the user. The Scanner translates these bytes into types (like ints) that can be used in a program. Declaring Variables to Store Integers Lines 13–15 declare that variables number1, number2 and sum hold data of type int—they can hold integer values (whole numbers such as 72, –1127 and 0). These variables are not yet initialized. The range of values for an int is –2,147,483,648 to +2,147,483,647. [Note: Actual int values may not contain commas.] Other types of data include float and double, for holding real numbers, and char, for holding character data. Real numbers contain decimal points, such as 3.4, 0.0 and –11.19. Variables of type char represent individual characters, such as an uppercase letter (e.g., A), a digit (e.g., 7), a special character (e.g., * or %) or an escape sequence (e.g., the newline character, \n). The types int, float, double and char are called primitive types.Primitive-type names are keywords and must appear in all lowercase letters. Appendix D summarizes the characteristics of the primitive types (boolean, byte, char, short, int, long, float and double). Several variables of the same type may be declared in a single declaration with the variable names separated by commas (i.e., a comma-separated list of variable names). For example, lines 13–15 can also be written as:
2.5 Another Application: Adding Integers
33
int number1, // first number to add number2, // second number to add sum; // sum of number1 and number2
Prompting the User for Input Line 17 uses System.out.print to display the message "Enter first integer: ". We use method print here rather than println so that the user’s input appears on the same line as the prompt. Recall from Section 2.2 that identifiers starting with capital letters typically represent class names. Class System is part of package java.lang. Notice that class System is not imported with an import declaration at the beginning of the program.
Software Engineering Observation 2.1 By default, package java.lang is imported in every Java program; thus, classes in java.lang are the only ones in the Java API that do not require an import declaration.
Obtaining an int as Input from the User Line 18 uses Scanner object input’s nextInt method to obtain an integer from the user at the keyboard. At this point the program waits for the user to type the number and press the Enter key to submit the number to the program. Our program assumes that the user enters a valid integer value. If not, a runtime logic error will occur and the program will terminate. Chapter 11, Exception Handling: A Deeper Look, discusses how to make your programs more robust by enabling them to handle such errors. This is also known as making your program fault tolerant. In line 18, we place the result of the call to method nextInt (an int value) in variable number1 by using the assignment operator, =. The statement is read as “number1 gets the value of input.nextInt().” Everything to the right of the assignment operator, =, is always evaluated before the assignment is performed. Prompting for and Inputting a Second int Line 20 prompts the user to input the second integer. Line 21 reads the second integer and assigns it to variable number2. Using Variables in a Calculation Line 23 calculates the sum of the variables number1 and number2 then assigns the result to variable sum by using the assignment operator, =. When the program encounters the addition operation, it performs the calculation using the values stored in the variables number1 and number2. In the preceding statement, the addition operator is a binary operator—its two operands are the variables number1 and number2. Portions of statements that contain calculations are called expressions. In fact, an expression is any portion of a statement that has a value associated with it. For example, the value of the expression number1 + number2 is the sum of the numbers. Similarly, the value of the expression input.nextInt() is the integer typed by the user. Displaying the Result of the Calculation After the calculation has been performed, line 25 uses method System.out.printf to display the sum. The format specifier %d is a placeholder for an int value (in this case the value of sum)—the letter d stands for “decimal integer.” The remaining characters in the format
34
Chapter 2
Introduction to Java Applications
string are all fixed text. So, method printf displays "Sum is ", followed by the value of sum (in the position of the %d format specifier) and a newline. Calculations can also be performed inside printf statements. We could have combined the statements at lines 23 and 25 into the statement System.out.printf( "Sum is %d\n", ( number1 + number2 ) );
The parentheses around the expression number1 + number2 are not required—they’re included to emphasize that the value of the entire expression is output in the position of the %d format specifier.
Java API Documentation For each new Java API class we use, we indicate the package in which it’s located. This information helps you locate descriptions of each package and class in the Java API documentation. A web-based version of this documentation can be found at download.oracle.com/javase/6/docs/api/
You can download it from www.oracle.com/technetwork/java/javase/downloads/index.html
Appendix E shows how to use this documentation.
2.6 Arithmetic The arithmetic operators are summarized in Fig. 2.8. The asterisk (*) indicates multiplication, and the percent sign (%) is the remainder operator, which we’ll discuss shortly. Java operation
Operator
Algebraic expression
Java expression
Addition Subtraction Multiplication Division Remainder
+
f+7 p–c bm x x /y or -y or x ÷ y r mod s
f + 7
– * / %
p - c b * m x / y r % s
Fig. 2.8 | Arithmetic operators. Integer division yields an integer quotient. For example, the expression 7 / 4 evaluates to 1, and the expression 17 / 5 evaluates to 3. Any fractional part in integer division is simply discarded (i.e., truncated)—no rounding occurs. Java provides the remainder operator, %, which yields the remainder after division. The expression x % y yields the remainder after x is divided by y. Thus, 7 % 4 yields 3, and 17 % 5 yields 2. This operator is most commonly used with integer operands but can also be used with other arithmetic types.
Rules of Operator Precedence Java applies the operators in arithmetic expressions in a precise sequence determined by the rules of operator precedence, which are generally the same as those followed in algebra:
2.7 Decision Making: Equality and Relational Operators
35
1. Multiplication, division and remainder operations are applied first. If an expression contains several such operations, they’re applied from left to right. Multiplication, division and remainder operators have the same level of precedence. 2. Addition and subtraction operations are applied next. If an expression contains several such operations, the operators are applied from left to right. Addition and subtraction operators have the same level of precedence. These rules enable Java to apply operators in the correct order.1 When we say that operators are applied from left to right, we’re referring to their associativity. Some operators associate from right to left. Figure 2.9 summarizes these rules of operator precedence. A complete precedence chart is included in Appendix A. Operator(s)
Operation(s)
Order of evaluation (precedence)
* / %
Multiplication Division Remainder Addition Subtraction Assignment
Evaluated first. If there are several operators of this type, they’re evaluated from left to right.
+ =
Evaluated next. If there are several operators of this type, they’re evaluated from left to right. Evaluated last.
Fig. 2.9 | Precedence of arithmetic operators.
2.7 Decision Making: Equality and Relational Operators A condition is an expression that can be true or false. This section introduces Java’s if selection statement, which allows a program to make a decision based on a condition’s value. For example, the condition “grade is greater than or equal to 60” determines whether a student passed a test. If the condition in an if statement is true, the body of the if statement executes. If the condition is false, the body does not execute. We’ll see an example shortly. Conditions in if statements can be formed by using the equality operators (== and !=) and relational operators (>, = and
x > y
x is greater than y
=
x >= y
x is greater than or equal to y
number2 ) System.out.printf( "%d > %d\n", number1, number2 ); if ( number1 = number2 ) System.out.printf( "%d >= %d\n", number1, number2 ); } // end method main } // end class Comparison
Enter first integer: 777 Enter second integer: 777 777 == 777 777 = 777
Enter first integer: 1000 Enter second integer: 2000 1000 != 2000 1000 < 2000 1000 1000 2000 >= 1000
Fig. 2.11 | Compare integers using if statements, relational operators and equality operators. (Part 2 of 2.)
The declaration of class Comparison begins at line 6. The class’s main method (lines 9–40) begins the execution of the program. Line 12 declares Scanner variable input and assigns it a Scanner that inputs data from the standard input (i.e., the keyboard). Lines 14–15 declare the int variables used to store the values input from the user. Lines 17–18 prompt the user to enter the first integer and input the value, respectively. The input value is stored in variable number1. Lines 20–21 prompt the user to enter the second integer and input the value, respectively. The input value is stored in variable number2. Lines 23–24 compare the values of number1 and number2 to determine whether they’re equal. An if statement always begins with keyword if, followed by a condition in parentheses. An if statement expects one statement in its body, but may contain multiple statements if they’re enclosed in a set of braces ({}). The indentation of the body statement shown here is not required, but it improves the program’s readability by emphasizing that the statement in line 24 is part of the if statement that begins at line 23. Line 24 executes only if the numbers stored in variables number1 and number2 are equal (i.e., the condition is true). The if statements in lines 26–27, 29–30, 32–33, 35–36 and 38–39 compare
38
Chapter 2
Introduction to Java Applications
number1 and number2 using the operators !=, , =, respectively. If the condition in one or more of the if statements is true, the corresponding body statement executes.
Common Programming Error 2.4 Confusing the equality operator, ==, with the assignment operator, =, can cause a logic error or a syntax error. The equality operator should be read as “is equal to” and the assignment operator as “gets” or “gets the value of.” To avoid confusion, some people read the equality operator as “double equals” or “equals equals.”
There’s no semicolon (;) at the end of the first line of each if statement. Such a semicolon would result in a logic error at execution time. For example, if ( number1 == number2 ); // logic error System.out.printf( "%d == %d\n", number1, number2 );
would actually be interpreted by Java as if ( number1 == number2 ) ; // empty statement System.out.printf( "%d == %d\n", number1, number2 );
where the semicolon on the line by itself—called the empty statement—is the statement to execute if the condition in the if statement is true. When the empty statement executes, no task is performed. The program then continues with the output statement, which always executes, regardless of whether the condition is true or false, because the output statement is not part of the if statement. Figure 2.12 shows the operators discussed so far in decreasing order of precedence. All but the assignment operator, =, associate from left to right. The assignment operator, =, associates from right to left, so an expression like x = y = 0 is evaluated as if it had been written as x = (y = 0), which first assigns the value 0 to variable y, then assigns the result of that assignment, 0, to x. Operators *
/
+
-
<
>=
Associativity
Type
left to right left to right left to right left to right right to left
multiplicative additive relational equality assignment
Fig. 2.12 | Precedence and associativity of operators discussed.
2.8 Wrap-Up In this chapter, you learned many important features of Java, including displaying data on the screen in a Command Prompt, inputting data from the keyboard, performing calculations and making decisions. The applications presented here introduced you to basic programming concepts. In Chapter 3, you’ll learn how to implement your own classes and use objects of those classes in applications.
3 Introduction to Classes, Objects, Methods and Strings Nothing can have value without being an object of utility. —Karl Marx
Your public servants serve you right. —Adlai E. Stevenson
You’ll see something new. Two things. And I call them Thing One and Thing Two. —Dr. Theodor Seuss Geisel
Objectives In this chapter you’ll learn: I
How to declare a class and use it to create an object.
I
How to implement a class’s behaviors as methods.
I
How to implement a class’s attributes as instance variables and properties.
I
How to call an object’s methods to make them perform their tasks.
I
What instance variables of a class and local variables of a method are.
I
How to use a constructor to initialize an object’s data.
I
The differences between primitive and reference types.
40
Chapter 3
Introduction to Classes, Objects, Methods and Strings
3.1 Introduction 3.2 Declaring a Class with a Method and Instantiating an Object of a Class 3.3 Declaring a Method with a Parameter 3.4 Instance Variables, set Methods and get Methods 3.5 Primitive Types vs. Reference Types
3.6 Initializing Objects with Constructors 3.7 Floating-Point Numbers and Type double
3.8 Wrap-Up
3.1 Introduction We introduced the basic terminology and concepts of object-oriented programming in Section 1.2. In this chapter, we present a simple framework for organizing object-oriented applications in Java. First, we motivate the notion of classes with a real-world example. Then we present five applications to demonstrate creating and using your own classes.
3.2 Declaring a Class with a Method and Instantiating an Object of a Class In Sections 2.5 and 2.7, you created an object of the existing class Scanner, then used that object to read data from the keyboard. In this section, you’ll create a new class, then use it to create an object. We begin by delcaring classes GradeBook (Fig. 3.1) and GradeBookTest (Fig. 3.2). Class GradeBook (declared in the file GradeBook.java) will be used to display a message on the screen (Fig. 3.2) welcoming the instructor to the grade book application. Class GradeBookTest (declared in the file GradeBookTest.java) is an application class in which the main method will create and use an object of class GradeBook. Each class declaration that begins with keyword public must be stored in a file having the same name as the class and ending with the .java file-name extension. Thus, classes GradeBook and GradeBookTest must be declared in separate files, because each class is declared public.
Class GradeBook The GradeBook class declaration (Fig. 3.1) contains a displayMessage method (lines 7– 10) that displays a message on the screen. We’ll need to make an object of this class and call its method to execute line 9 and display the message. 1 2 3 4 5 6 7 8 9 10 11
// Fig. 3.1: GradeBook.java // Class declaration with one method. public class GradeBook { // display a welcome message to the GradeBook user public void displayMessage() { System.out.println( "Welcome to the Grade Book!" ); } // end method displayMessage } // end class GradeBook
Fig. 3.1 | Class declaration with one method.
3.2 Declaring a Class with a Method and Instantiating an Object of a Class
41
The class declaration begins in line 4. The keyword public is an access modifier. For now, we’ll simply declare every class public. Every class declaration contains keyword class followed immediately by the class’s name. Every class’s body is enclosed in a pair of left and right braces, as in lines 5 and 11 of class GradeBook. In Chapter 2, each class we declared had one method named main. Class GradeBook also has one method—displayMessage (lines 7–10). Recall that main is a special method that’s always called automatically by the Java Virtual Machine (JVM) when you execute an application. Most methods do not get called automatically. As you’ll soon see, you must call method displayMessage explicitly to tell it to perform its task. The method declaration begins with keyword public to indicate that the method is “available to the public”—it can be called from methods of other classes. Next is the method’s return type, which specifies the type of data the method returns to its caller after performing its task. The return type void indicates that this method will perform a task but will not return (i.e., give back) any information to its calling method. You’ve used methods that return information—for example, in Chapter 2 you used Scanner method nextInt to input an integer typed by the user at the keyboard. When nextInt reads a value from the user, it returns that value for use in the program. The name of the method, displayMessage, follows the return type. By convention, method names begin with a lowercase first letter and subsequent words in the name begin with a capital letter. The parentheses after the method name indicate that this is a method. Empty parentheses, as in line 7, indicate that this method does not require additional information to perform its task. Line 7 is commonly referred to as the method header. Every method’s body is delimited by left and right braces, as in lines 8 and 10. The body of a method contains one or more statements that perform the method’s task. In this case, the method contains one statement (line 9) that displays the message "Welcome to the Grade Book!" followed by a newline (because of println) in the command window. After this statement executes, the method has completed its task.
Class GradeBookTest Next, we’d like to use class GradeBook in an application. As you learned in Chapter 2, method main begins the execution of every application. A class that contains method main begins the execution of a Java application. Class GradeBook is not an application because it does not contain main. Therefore, if you try to execute GradeBook by typing java GradeBook in the command window, an error will occur. This was not a problem in Chapter 2, because every class you declared had a main method. To fix this problem, we must either declare a separate class that contains a main method or place a main method in class GradeBook. To help you prepare for the larger programs you’ll encounter later in this book and in industry, we use a separate class (GradeBookTest in this example) containing method main to test each new class we create in this chapter. Some programmers refer to such a class as a driver class. The GradeBookTest class declaration (Fig. 3.2) contains the main method that will control our application’s execution. The GradeBookTest class declaration begins in line 4 and ends in line 15. The class, like many that begin an application’s execution, contains only a main method. Lines 7–14 declare method main. A key part of enabling the JVM to locate and call method main to begin the application’s execution is the static keyword (line 7), which indicates that main is a static method. A static method is special, because you can call it
42
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Chapter 3
Introduction to Classes, Objects, Methods and Strings
// Fig. 3.2: GradeBookTest.java // Creating a GradeBook object and calling its displayMessage method. public class GradeBookTest { // main method begins program execution public static void main( String[] args ) { // create a GradeBook object and assign it to myGradeBook GradeBook myGradeBook = new GradeBook(); // call myGradeBook's displayMessage method myGradeBook.displayMessage(); } // end main } // end class GradeBookTest
Welcome to the Grade Book!
Fig. 3.2 | Creating a GradeBook object and calling its displayMessage method.
without first creating an object of the class in which the method is declared. We discuss static methods in detail in Chapter 6, Methods: A Deeper Look. In this application, we’d like to call class GradeBook’s displayMessage method to display the welcome message in the command window. Typically, you cannot call a method that belongs to another class until you create an object of that class, as shown in line 10. We begin by declaring variable myGradeBook. The variable’s type is GradeBook—the class we declared in Fig. 3.1. Each new class you create becomes a new type that can be used to declare variables and create objects. You can declare new class types as needed; this is one reason why Java is known as an extensible language. Variable myGradeBook is initialized (line 10) with the result of the class instance creation expression new GradeBook(). Keyword new creates a new object of the class specified to the right of the keyword (i.e., GradeBook). The parentheses to the right of GradeBook are required. As you’ll learn in Section 3.6, those parentheses in combination with a class name represent a call to a constructor, which is similar to a method but is used only at the time an object is created to initialize the object’s data. You’ll see that data can be placed in the parentheses to specify initial values for the object’s data. For now, we simply leave the parentheses empty. Just as we can use object System.out to call its methods print, printf and println, we can use object myGradeBook to call its method displayMessage. Line 13 calls the method displayMessage (lines 7–10 of Fig. 3.1) using myGradeBook followed by a dot separator (.), the method name displayMessage and an empty set of parentheses. This call causes the displayMessage method to perform its task. This method call differs from those in Chapter 2 that displayed information in a command window—each of those method calls provided arguments that specified the data to display. At the beginning of line 13, “myGradeBook.” indicates that main should use the myGradeBook object that was created in line 10. Line 7 of Fig. 3.1 indicates that method displayMessage has an empty parameter list—that is, displayMessage does not require additional information to per-
3.2 Declaring a Class with a Method and Instantiating an Object of a Class
43
form its task. For this reason, the method call (line 13 of Fig. 3.2) specifies an empty set of parentheses after the method name to indicate that no arguments are being passed to method displayMessage. When method displayMessage completes its task, method main continues executing at line 14. This is the end of method main, so the program terminates. Any class can contain a main method. The JVM invokes the main method only in the class used to execute the application. If an application has multiple classes that contain main, the one that’s invoked is the one in the class named in the java command.
Compiling an Application with Multiple Classes You must compile the classes in Fig. 3.1 and Fig. 3.2 before you can execute the application. First, change to the directory that contains the application’s source-code files. Next, type the command javac GradeBook.java GradeBookTest.java
to compile both classes at once. If the directory containing the application includes only this application’s files, you can compile all the classes in the directory with the command javac *.java
The asterisk (*) in *.java indicates that all files in the current directory that end with the file-name extension “.java” should be compiled.
UML Class Diagram for Class GradeBook Figure 3.3 presents a UML class diagram for class GradeBook of Fig. 3.1. In the UML, each class is modeled in a class diagram as a rectangle with three compartments. The top compartment contains the name of the class centered horizontally in boldface type. The middle compartment contains the class’s attributes, which correspond to instance variables (discussed in Section 3.4) in Java. In Fig. 3.3, the middle compartment is empty, because this GradeBook class does not have any attributes. The bottom compartment contains the class’s operations, which correspond to methods in Java. The UML models operations by listing the operation name preceded by an access modifier (in this case +) and followed by a set of parentheses. Class GradeBook has one method, displayMessage, so the bottom compartment of Fig. 3.3 lists one operation with this name. Method displayMessage does not require additional information to perform its tasks, so the parentheses following the method name in the class diagram are empty, just as they were in the method’s declaration in line 7 of Fig. 3.1. The plus sign (+) in front of the operation name indicates that displayMessage is a public operation in the UML (i.e., a public method in Java). We’ll often use UML class diagrams to summarize a class’s attributes and operations. GradeBook + displayMessage( )
Fig. 3.3 | UML class diagram indicating that class GradeBook has a public displayMessage
operation.
44
Chapter 3
Introduction to Classes, Objects, Methods and Strings
3.3 Declaring a Method with a Parameter In our car analogy from Section 1.2, we discussed the fact that pressing a car’s gas pedal sends a message to the car to perform a task—to go faster. But how fast should the car accelerate? As you know, the farther down you press the pedal, the faster the car accelerates. So the message to the car actually includes the task to perform and additional information that helps the car perform the task. This additional information is known as a parameter—the value of the parameter helps the car determine how fast to accelerate. Similarly, a method can require one or more parameters that represent additional information it needs to perform its task. Parameters are defined in a comma-separated parameter list, which is located inside the parentheses that follow the method name. Each parameter must specify a type and a variable name. The parameter list may contain any number of parameters, including none at all. Empty parentheses following the method name (as in Fig. 3.1, line 7) indicate that a method does not require any parameters.
Arguments to a Method A method call supplies values—called arguments—for each of the method’s parameters. For example, the method System.out.println requires an argument that specifies the data to output in a command window. Similarly, to make a deposit into a bank account, a deposit method specifies a parameter that represents the deposit amount. When the deposit method is called, an argument value representing the deposit amount is assigned to the method’s parameter. The method then makes a deposit of that amount. Class Declaration with a Method That Has One Parameter We now declare class GradeBook (Fig. 3.4) with a displayMessage method that displays the course name as part of the welcome message. (See the sample execution in Fig. 3.5.) The new method requires a parameter that represents the course name to output. 1 2 3 4 5 6 7 8 9 10 11 12
// Fig. 3.4: GradeBook.java // Class declaration with one method that has a parameter. public class GradeBook { // display a welcome message to the GradeBook user public void displayMessage( String courseName ) { System.out.printf( "Welcome to the grade book for\n%s!\n", courseName ); } // end method displayMessage } // end class GradeBook
Fig. 3.4 | Class declaration with one method that has a parameter. Before discussing the new features of class GradeBook, let’s see how the new class is used from the main method of class GradeBookTest (Fig. 3.5). Line 12 creates a Scanner named input for reading the course name from the user. Line 15 creates the GradeBook object myGradeBook. Line 18 prompts the user to enter a course name. Line 19 reads the name from the user and assigns it to the nameOfCourse variable, using Scanner method nextLine to perform the input. The user types the course name and presses Enter to
3.3 Declaring a Method with a Parameter
45
submit the course name to the program. Pressing Enter inserts a newline character at the end of the characters typed by the user. Method nextLine reads characters typed by the user until it encounters the newline character, then returns a String containing the characters up to, but not including, the newline. The newline character is discarded. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
// Fig. 3.5: GradeBookTest.java // Create GradeBook object and pass a String to // its displayMessage method. import java.util.Scanner; // program uses Scanner public class GradeBookTest { // main method begins program execution public static void main( String[] args ) { // create Scanner to obtain input from command window Scanner input = new Scanner( System.in ); // create a GradeBook object and assign it to myGradeBook GradeBook myGradeBook = new GradeBook(); // prompt for and input course name System.out.println( "Please enter the course name:" ); String nameOfCourse = input.nextLine(); // read a line of text System.out.println(); // outputs a blank line // call myGradeBook's displayMessage method // and pass nameOfCourse as an argument myGradeBook.displayMessage( nameOfCourse ); } // end main } // end class GradeBookTest
Please enter the course name: CS101 Introduction to Java Programming Welcome to the grade book for CS101 Introduction to Java Programming!
Fig. 3.5 | Create a GradeBook object and pass a String to its displayMessage method. Class Scanner also provides a similar method—next—that reads individual words. When the user presses Enter after typing input, method next reads characters until it encounters a white-space character (such as a space, tab or newline), then returns a String containing the characters up to, but not including, the white-space character (which is discarded). All information after the first white-space character is not lost—it can be read by other statements that call the Scanner’s methods later in the program. Line 20 outputs a blank line. Line 24 calls myGradeBooks’s displayMessage method. The variable nameOfCourse in parentheses is the argument that’s passed to method displayMessage so that the method can perform its task. The value of variable nameOfCourse in main becomes the value of method displayMessage’s parameter courseName in line 7 of Fig. 3.4. When you execute
46
Chapter 3
Introduction to Classes, Objects, Methods and Strings
this application, notice that method displayMessage outputs the name you type as part of the welcome message (Fig. 3.5).
More on Arguments and Parameters In Fig. 3.4, displayMessage’s parameter list (line 7) declares one parameter indicating that the method requires a String to perform its task. When the method is called, the argument value in the call is assigned to the corresponding parameter (courseName) in the method header. Then, the method body uses the value of the courseName parameter. Lines 9–10 of Fig. 3.4 display parameter courseName’s value, using the %s format specifier in printf’s format string. The parameter variable’s name (courseName in Fig. 3.4, line 7) can be the same or different from the argument variable’s name (nameOfCourse in Fig. 3.5, line 24). The number of arguments in a method call must match the number of parameters in the parameter list of the method’s declaration. Also, the argument types in the method call must be “consistent with” the types of the corresponding parameters in the method’s declaration—as you’ll see in Chapter 6, an argument’s type and its corresponding parameter’s type are not always required to be identical. In our example, the method call passes one argument of type String (nameOfCourse is declared as a String in line 19 of Fig. 3.5) and the method declaration specifies one parameter of type String (courseName is declared as a String in line 7 of Fig. 3.4). So in this example the type of the argument in the method call exactly matches the type of the parameter in the method header. Updated UML Class Diagram for Class GradeBook The UML class diagram of Fig. 3.6 models class GradeBook of Fig. 3.4. Like Fig. 3.1, this GradeBook class contains public operation displayMessage. However, this version of displayMessage has a parameter. The UML models a parameter a bit differently from Java by listing the parameter name, followed by a colon and the parameter type in the parentheses following the operation name. The UML has its own data types similar to those of Java (but, as you’ll see, not all the UML data types have the same names as the corresponding Java types). The UML type String does correspond to the Java type String. GradeBook method displayMessage (Fig. 3.4) has a String parameter named courseName, so Fig. 3.6 lists courseName : String between the parentheses following displayMessage. GradeBook + displayMessage( courseName : String )
Fig. 3.6 | UML class diagram indicating that class GradeBook has a displayMessage operation with a courseName parameter of UML type String.
Notes on import Declarations Notice the import declaration in Fig. 3.5 (line 4). This indicates to the compiler that the program uses class Scanner. Why do we need to import class Scanner, but not classes System, String or GradeBook? Classes System and String are in package java.lang, which is implicitly imported into every Java program, so all programs can use that package’s classes without explicitly importing them. Most other classes you’ll use in Java programs must be imported explicitly.
3.4 Instance Variables, set Methods and get Methods
47
There’s a special relationship between classes that are compiled in the same directory on disk, like classes GradeBook and GradeBookTest. By default, such classes are considered to be in the same package—known as the default package. Classes in the same package are implicitly imported into the source-code files of other classes in the same package. Thus, an import declaration is not required when one class in a package uses another in the same package—such as when class GradeBookTest uses class GradeBook. The import declaration in line 4 is not required if we always refer to class Scanner as java.util.Scanner, which includes the full package name and class name. This is known as the class’s fully qualified class name. For example, line 12 could be written as java.util.Scanner input = new java.util.Scanner( System.in );
Software Engineering Observation 3.1 The Java compiler does not require import declarations in a Java source-code file if the fully qualified class name is specified every time a class name is used in the source code. Most Java programmers prefer to use import declarations.
3.4 Instance Variables, set Methods and get Methods In Chapter 2, we declared all of an application’s variables in the application’s main method. Variables declared in the body of a particular method are local variables and can be used only in that method. When that method terminates, the values of its local variables are lost. Recall from Section 1.2 that an object has attributes that are carried with it as it’s used in a program. Such attributes exist before a method is called on an object, while the method is executing and after the method completes execution. A class normally consists of one or more methods that manipulate the attributes that belong to a particular object of the class. Attributes are represented as variables in a class declaration. Such variables are called fields and are declared inside a class declaration but outside the bodies of the class’s method declarations. When each object of a class maintains its own copy of an attribute, the field that represents the attribute is also known as an instance variable—each object (instance) of the class has a separate instance of the variable in memory. The example in this section demonstrates a GradeBook class that contains a courseName instance variable to represent a particular GradeBook object’s course name.
Class with an Instance Variable, a set Method and a get Method In our next application (Figs. 3.7–3.8), class GradeBook (Fig. 3.7) maintains the course name as an instance variable so that it can be used or modified at any time during an application’s execution. The class contains three methods—setCourseName, getCourseName and displayMessage. Method setCourseName stores a course name in a GradeBook. Method getCourseName obtains a GradeBook’s course name. Method displayMessage, which now specifies no parameters, still displays a welcome message that includes the course name; as you’ll see, the method now obtains the course name by calling a method in the same class—getCourseName. A typical instructor teaches more than one course, each with its own course name. Line 7 declares courseName as a variable of type String. Because the variable is declared in the body of the class but outside the bodies of the class’s methods (lines 10–13, 16–19 and 22–28), line 7 is a declaration for an instance variable. Every instance (i.e., object) of GradeBook
48
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
Chapter 3
Introduction to Classes, Objects, Methods and Strings
// Fig. 3.7: GradeBook.java // GradeBook class that contains a courseName instance variable // and methods to set and get its value. public class GradeBook { private String courseName; // course name for this GradeBook // method to set the course name public void setCourseName( String name ) { courseName = name; // store the course name } // end method setCourseName // method to retrieve the course name public String getCourseName() { return courseName; } // end method getCourseName // display a welcome message to the GradeBook user public void displayMessage() { // calls getCourseName to get the name of // the course this GradeBook represents System.out.printf( "Welcome to the grade book for\n%s!\n", getCourseName() ); } // end method displayMessage } // end class GradeBook
Fig. 3.7 |
GradeBook
class that contains a courseName instance variable and methods to set
and get its value.
class GradeBook contains one copy of each instance variable. For example, if there are two GradeBook objects, each object has its own copy of courseName. A benefit of making courseName an instance variable is that all the methods of the class (in this case, GradeBook) can manipulate any instance variables that appear in the class (in this case, courseName).
Access Modifiers public and private Most instance-variable declarations are preceded with the keyword private (as in line 7). Like public, keyword private is an access modifier. Variables or methods declared with access modifier private are accessible only to methods of the class in which they’re declared. Thus, variable courseName can be used only in methods setCourseName, getCourseName and displayMessage of (every object of) class GradeBook. Declaring instance variables with access modifier private is known as data hiding or information hiding. When a program creates (instantiates) an object of class GradeBook, variable courseName is encapsulated (hidden) in the object and can be accessed only by methods of the object’s class. This prevents courseName from being modified accidentally by a class in another part of the program. In class GradeBook, methods setCourseName and getCourseName manipulate the instance variable courseName.
3.4 Instance Variables, set Methods and get Methods
49
Software Engineering Observation 3.2 Precede each field and method declaration with an access modifier. Generally, instance variables should be declared private and methods public. (It’s appropriate to declare certain methods private, if they’ll be accessed only by other methods of the class.)
Good Programming Practice 3.1 We prefer to list a class’s fields first, so that, as you read the code, you see the names and types of the variables before they’re used in the class’s methods. You can list the class’s fields anywhere in the class outside its method declarations, but scattering them can lead to hard-to-read code.
Methods setCourseName and getCourseName Method setCourseName (lines 10–13) does not return any data when it completes its task, so its return type is void. The method receives one parameter—name—which represents the course name that will be passed to the method as an argument. Line 12 assigns name to instance variable courseName. Method getCourseName (lines 16–19) returns a particular GradeBook object’s courseName. The method has an empty parameter list, so it does not require additional information to perform its task. The method specifies that it returns a String—this is the method’s return type. When a method that specifies a return type other than void is called and completes its task, the method returns a result to its calling method. For example, when you go to an automated teller machine (ATM) and request your account balance, you expect the ATM to give you back a value that represents your balance. Similarly, when a statement calls method getCourseName on a GradeBook object, the statement expects to receive the GradeBook’s course name (in this case, a String, as specified in the method declaration’s return type). The return statement in line 18 passes the value of instance variable courseName back to the statement that calls method getCourseName. Consider, method displayMessage’s line 27, which calls method getCourseName. When the value is returned, the statement in lines 26–27 uses that value to output the course name. Similarly, if you have a method square that returns the square of its argument, you’d expect the statement int result = square( 2 );
to return 4 from method square and assign 4 to the variable result. If you have a method maximum that returns the largest of three integer arguments, you’d expect the statement int biggest = maximum( 27, 114, 51 );
to return 114 from method maximum and assign 114 to variable biggest. The statements in lines 12 and 18 each use courseName even though it was not declared in any of the methods. We can use courseName in GradeBook’s methods because courseName is an instance variable of the class.
Method displayMessage Method displayMessage (lines 22–28) does not return any data when it completes its task, so its return type is void. The method does not receive parameters, so the parameter list is empty. Lines 26–27 output a welcome message that includes the value of instance variable courseName, which is returned by the call to method getCourseName in line 27.
50
Chapter 3
Introduction to Classes, Objects, Methods and Strings
Notice that one method of a class (displayMessage in this case) can call another method of the same class by using just the method name (getCourseName in this case).
Class That Demonstrates Class GradeBook Class GradeBookTest (Fig. 3.8) creates one object of class GradeBook and demonstrates its methods. Line 14 creates a GradeBook object and assigns it to local variable myGradeBook of type GradeBook. Lines 17–18 display the initial course name calling the object’s getCourseName method. The first line of the output shows the name “null.” Unlike local variables, which are not automatically initialized, every field has a default initial value—a value provided by Java when you do not specify the field’s initial value. Thus, fields are not required to be explicitly initialized before they’re used in a program—unless they must be initialized to values other than their default values. The default value for a field of type String (like courseName in this example) is null, which we say more about in Section 3.5. GradeBookTest
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
// Fig. 3.8: GradeBookTest.java // Creating and manipulating a GradeBook object. import java.util.Scanner; // program uses Scanner public class GradeBookTest { // main method begins program execution public static void main( String[] args ) { // create Scanner to obtain input from command window Scanner input = new Scanner( System.in ); // create a GradeBook object and assign it to myGradeBook GradeBook myGradeBook = new GradeBook(); // display initial value of courseName System.out.printf( "Initial course name is: %s\n\n", myGradeBook.getCourseName() ); // prompt for and read course name System.out.println( "Please enter the course name:" ); String theName = input.nextLine(); // read a line of text myGradeBook.setCourseName( theName ); // set the course name System.out.println(); // outputs a blank line // display welcome message after specifying course name myGradeBook.displayMessage(); } // end main } // end class GradeBookTest
Initial course name is: null Please enter the course name: CS101 Introduction to Java Programming Welcome to the grade book for CS101 Introduction to Java Programming!
Fig. 3.8 | Creating and manipulating a GradeBook object.
3.4 Instance Variables, set Methods and get Methods
51
Line 21 prompts the user to enter a course name. Local String variable theName (declared in line 22) is initialized with the course name entered by the user, which is returned by the call to the nextLine method of the Scanner object input. Line 23 calls object myGradeBook’s setCourseName method and supplies theName as the method’s argument. When the method is called, the argument’s value is assigned to parameter name (line 10, Fig. 3.7) of method setCourseName (lines 10–13, Fig. 3.7). Then the parameter’s value is assigned to instance variable courseName (line 12, Fig. 3.7). Line 24 (Fig. 3.8) skips a line in the output, then line 27 calls object myGradeBook’s displayMessage method to display the welcome message containing the course name.
set and get Methods A class’s private fields can be manipulated only by the class’s methods. So a client of an object—that is, any class that calls the object’s methods—calls the class’s public methods to manipulate the private fields of an object of the class. This is why the statements in method main (Fig. 3.8) call the setCourseName, getCourseName and displayMessage methods on a GradeBook object. Classes often provide public methods to allow clients to set (i.e., assign values to) or get (i.e., obtain the values of) private instance variables. The names of these methods need not begin with set or get, but this naming convention is recommended and is the convention for special Java software components called JavaBeans, which can simplify programming in many Java integrated development environments (IDEs). The method that sets instance variable courseName in this example is called setCourseName, and the method that gets its value is called getCourseName. GradeBook UML Class Diagram with an Instance Variable and set and get Methods
Figure 3.9 contains an updated UML class diagram for the version of class GradeBook in Fig. 3.7. This diagram models class GradeBook’s instance variable courseName as an attribute in the middle compartment of the class. The UML represents instance variables as attributes by listing the attribute name, followed by a colon and the attribute type. The UML type of attribute courseName is String. Instance variable courseName is private in Java, so the class diagram lists a minus sign (–) access modifier in front of the corresponding attribute’s name. Class GradeBook contains three public methods, so the class diagram lists three operations in the third compartment. Recall that the plus sign (+) before each operation name indicates that the operation is public. Operation setCourseName has a String parameter called name. The UML indicates the return type of an operation by placing a colon and the return type after the parentheses following the operation name. MethGradeBook – courseName : String + setCourseName( name : String ) + getCourseName( ) : String + displayMessage( )
Fig. 3.9 | UML class diagram indicating that class GradeBook has a private courseName attribute of UML type String and three public operations—setCourseName (with a name parameter of UML type String), getCourseName (which returns UML type String) and displayMessage.
52
Chapter 3
Introduction to Classes, Objects, Methods and Strings
od getCourseName of class GradeBook (Fig. 3.7) has a String return type in Java, so the class diagram shows a String return type in the UML. Operations setCourseName and displayMessage do not return values (i.e., they return void in Java), so the UML class diagram does not specify a return type after the parentheses of these operations.
3.5 Primitive Types vs. Reference Types Java’s types are divided into primitive types and reference types. The primitive types are boolean, byte, char, short, int, long, float and double. All nonprimitive types are reference types, so classes, which specify the types of objects, are reference types. A primitive-type variable can store exactly one value of its declared type at a time. For example, an int variable can store one whole number (such as 7) at a time. When another value is assigned to that variable, its initial value is replaced. Primitive-type instance variables are initialized by default—variables of types byte, char, short, int, long, float and double are initialized to 0, and variables of type boolean are initialized to false. You can specify your own initial value for a primitive-type variable by assigning the variable a value in its declaration, as in private int numberOfStudents = 10;
Recall that local variables are not initialized by default.
Error-Prevention Tip 3.1 An attempt to use an uninitialized local variable causes a compilation error.
Programs use variables of reference types (normally called references) to store the locations of objects in the computer’s memory. Such a variable is said to refer to an object in the program. Objects that are referenced may each contain many instance variables. Line 14 of Fig. 3.8 creates an object of class GradeBook, and the variable myGradeBook contains a reference to that GradeBook object. Reference-type instance variables are initialized by default to the value null—a reserved word that represents a “reference to nothing.” This is why the first call to getCourseName in line 18 of Fig. 3.8 returned null—the value of courseName had not been set, so the default initial value null was returned. The complete list of reserved words and keywords is listed in Appendix C. When you use an object of another class, a reference to the object is required to invoke (i.e., call) its methods. In the application of Fig. 3.8, the statements in method main use the variable myGradeBook to send messages to the GradeBook object. These messages are calls to methods (like setCourseName and getCourseName) that enable the program to interact with the GradeBook object. For example, the statement in line 23 uses myGradeBook to send the setCourseName message to the GradeBook object. The message includes the argument that setCourseName requires to perform its task. The GradeBook object uses this information to set the courseName instance variable. Primitive-type variables do not refer to objects, so such variables cannot be used to invoke methods.
Software Engineering Observation 3.3 A variable’s declared type (e.g., int, double or GradeBook) indicates whether the variable is of a primitive or a reference type. If a variable is not of one of the eight primitive types, then it’s of a reference type.
3.6 Initializing Objects with Constructors
53
3.6 Initializing Objects with Constructors As mentioned in Section 3.4, when an object of class GradeBook (Fig. 3.7) is created, its instance variable courseName is initialized to null by default. What if you want to provide a course name when you create a GradeBook object? Each class you declare can provide a special method called a constructor that can be used to initialize an object of a class when the object is created. In fact, Java requires a constructor call for every object that’s created. Keyword new requests memory from the system to store an object, then calls the corresponding class’s constructor to initialize the object. The call is indicated by the parentheses after the class name. A constructor must have the same name as the class. For example, line 14 of Fig. 3.8 first uses new to create a GradeBook object. The empty parentheses after “new GradeBook” indicate a call to the class’s constructor without arguments. By default, the compiler provides a default constructor with no parameters in any class that does not explicitly include a constructor. When a class has only the default constructor, its instance variables are initialized to their default values. When you declare a class, you can provide your own constructor to specify custom initialization for objects of your class. For example, you might want to specify a course name for a GradeBook object when the object is created, as in GradeBook myGradeBook = new GradeBook( "CS101 Introduction to Java Programming" );
In this case, the argument "CS101 Introduction to Java Programming" is passed to the GradeBook object’s constructor and used to initialize the courseName. The preceding statement requires that the class provide a constructor with a String parameter. Figure 3.10 contains a modified GradeBook class with such a constructor. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
// Fig. 3.10: GradeBook.java // GradeBook class with a constructor to initialize the course name. public class GradeBook { private String courseName; // course name for this GradeBook // constructor initializes courseName with String argument public GradeBook( String name ) // constructor name is class name { courseName = name; // initializes courseName } // end constructor // method to set the course name public void setCourseName( String name ) { courseName = name; // store the course name } // end method setCourseName // method to retrieve the course name public String getCourseName() {
Fig. 3.10 |
GradeBook
class with a constructor to initialize the course name. (Part 1 of 2.)
54
23 24 25 26 27 28 29 30 31 32 33 34
Chapter 3
Introduction to Classes, Objects, Methods and Strings
return courseName; } // end method getCourseName // display a welcome message to the GradeBook user public void displayMessage() { // this statement calls getCourseName to get the // name of the course this GradeBook represents System.out.printf( "Welcome to the grade book for\n%s!\n", getCourseName() ); } // end method displayMessage } // end class GradeBook
Fig. 3.10 |
GradeBook
class with a constructor to initialize the course name. (Part 2 of 2.)
Lines 9–12 declare GradeBook’s constructor. Like a method, a constructor’s parameter list specifies the data it requires to perform its task. When you create a new object (as we’ll do in Fig. 3.11), this data is placed in the parentheses that follow the class name. Line 9 of Fig. 3.10 indicates that the constructor has a String parameter called name. The name passed to the constructor is assigned to instance variable courseName in line 11. Figure 3.11 initializes GradeBook objects using the constructor. Lines 11–12 create and initialize the GradeBook object gradeBook1. The GradeBook constructor is called with the argument "CS101 Introduction to Java Programming" to initialize the course name. The class instance creation expression in lines 11–12 returns a reference to the new object, which is assigned to the variable gradeBook1. Lines 13–14 repeat this process, this time passing the argument "CS102 Data Structures in Java" to initialize the course name for gradeBook2. Lines 17–20 use each object’s getCourseName method to obtain the course names and show that they were initialized when the objects were created. The output confirms that each GradeBook maintains its own copy of instance variable courseName.
Software Engineering Observation 3.4 Unless default initialization of your class’s instance variables is acceptable, provide a constructor to ensure that they’re properly initialized with meaningful values when each new object of your class is created. 1 2 3 4 5 6 7 8 9 10 11 12
// Fig. 3.11: GradeBookTest.java // GradeBook constructor used to specify the course name at the // time each GradeBook object is created. public class GradeBookTest { // main method begins program execution public static void main( String[] args ) { // create GradeBook object GradeBook gradeBook1 = new GradeBook( "CS101 Introduction to Java Programming" );
Fig. 3.11 |
constructor used to specify the course name at the time each GradeBook object is created. (Part 1 of 2.) GradeBook
3.6 Initializing Objects with Constructors
13 14 15 16 17 18 19 20 21 22
55
GradeBook gradeBook2 = new GradeBook( "CS102 Data Structures in Java" ); // display initial value of courseName for each GradeBook System.out.printf( "gradeBook1 course name is: %s\n", gradeBook1.getCourseName() ); System.out.printf( "gradeBook2 course name is: %s\n", gradeBook2.getCourseName() ); } // end main } // end class GradeBookTest
gradeBook1 course name is: CS101 Introduction to Java Programming gradeBook2 course name is: CS102 Data Structures in Java
Fig. 3.11 |
constructor used to specify the course name at the time each GradeBook object is created. (Part 2 of 2.) GradeBook
An important difference between constructors and methods is that constructors cannot return values, so they cannot specify a return type (not even void). Normally, constructors are declared public. If a class does not include a constructor, the class’s instance variables are initialized to their default values. If you declare any constructors for a class, the Java compiler will not create a default constructor for that class. Thus, we can no longer create a GradeBook object with new GradeBook() as we did in the earlier examples.
Adding the Constructor to Class GradeBook’s UML Class Diagram The UML class diagram of Fig. 3.12 models class GradeBook of Fig. 3.10, which has a constructor that has a name parameter of type String. Like operations, the UML models constructors in the third compartment of a class in a class diagram. To distinguish a constructor from a class’s operations, the UML requires that the word “constructor” be placed between guillemets (« and ») before the constructor’s name. It’s customary to list constructors before other operations in the third compartment. GradeBook – courseName : String «constructor» GradeBook( name : String ) + setCourseName( name : String ) + getCourseName( ) : String + displayMessage( )
Fig. 3.12 | UML class diagram indicating that class GradeBook has a constructor that has a name
parameter of UML type String.
Constructors with Multiple Parameters Sometimes you’ll want to initialize objects with multiple data items. For example, you could store the course name and the instructor’s name in a GradeBook object. In this case, the GradeBook’s constructor would be modified to receive two Strings, as in public GradeBook( String courseName, String instructorName )
56
Chapter 3
Introduction to Classes, Objects, Methods and Strings
and you’d call the GradeBook constructor as follows: GradeBook gradeBook = new GradeBook( "CS101 Introduction to Java Programming", "Sue Green" );
3.7 Floating-Point Numbers and Type double We now depart temporarily from our GradeBook case study to declare an Account class that maintains the balance of a bank account. Most account balances are not whole numbers (such as 0, –22 and 1024). For this reason, class Account represents the account balance as a floating-point number (i.e., a number with a decimal point, such as 7.33, 0.0975 or 1000.12345). Java provides two primitive types for storing floating-point numbers in memory—float and double. They differ primarily in that double variables can store numbers with larger magnitude and finer detail (i.e., more digits to the right of the decimal point—also known as the number’s precision) than float variables.
Floating-Point Number Precision and Memory Requirements Variables of type float represent single-precision floating-point numbers and can represent up to seven significant digits. Variables of type double represent double-precision floatingpoint numbers. These require twice as much memory as float variables and provide 15 significant digits—approximately double the precision of float variables. For the range of values required by most programs, variables of type float should suffice, but you can use double to “play it safe.” In some applications, even double variables will be inadequate. Most programmers represent floating-point numbers with type double. In fact, Java treats all floating-point numbers you type in a program’s source code (such as 7.33 and 0.0975) as double values by default. Such values in the source code are known as floating-point literals. See Appendix D, Primitive Types, for the ranges of values for floats and doubles. Although floating-point numbers are not always 100% precise, they have numerous applications. For example, when we speak of a “normal” body temperature of 98.6, we do not need to be precise to a large number of digits. When we read the temperature on a thermometer as 98.6, it may actually be 98.5999473210643. Calling this number simply 98.6 is fine for most applications involving body temperatures. Owing to the imprecise nature of floating-point numbers, type double is preferred over type float, because double variables can represent floating-point numbers more accurately. For this reason, we primarily use type double throughout the book. For precise floating-point numbers, Java provides class BigDecimal (package java.math). Floating-point numbers also arise as a result of division. In conventional arithmetic, when we divide 10 by 3, the result is 3.3333333…, with the sequence of 3s repeating infinitely. The computer allocates only a fixed amount of space to hold such a value, so clearly the stored floating-point value can be only an approximation. Class with an Instance Variable of Type double Our next application (Figs. 3.13–3.14) contains a class named Account (Fig. 3.13) that maintains the balance of a bank account. A typical bank services many accounts, each with its own balance, so line 7 declares an instance variable named balance of type double. It’s an instance variable because it’s declared in the body of the class but outside the class’s method declarations (lines 10–16, 19–22 and 25–28). Every instance (i.e., object) of class Account contains its own copy of balance. Account
3.7 Floating-Point Numbers and Type double
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
57
// Fig. 3.13: Account.java // Account class with a constructor to validate and // initialize instance variable balance of type double. public class Account { private double balance; // instance variable that stores the balance // constructor public Account( double initialBalance ) { // validate that initialBalance is greater than 0.0; // if it is not, balance is initialized to the default value 0.0 if ( initialBalance > 0.0 ) balance = initialBalance; } // end Account constructor // credit (add) an amount to the account public void credit( double amount ) { balance = balance + amount; // add amount to balance } // end method credit // return the account balance public double getBalance() { return balance; // gives the value of balance to the calling method } // end method getBalance } // end class Account
Fig. 3.13 |
Account class with a constructor to validate and initialize instance variable balance
of type double.
The class has a constructor and two methods. It’s common for someone opening an account to deposit money immediately, so the constructor (lines 10–16) receives a parameter initialBalance of type double that represents the starting balance. Lines 14–15 ensure that initialBalance is greater than 0.0. If so, initialBalance’s value is assigned to instance variable balance. Otherwise, balance remains at 0.0—its default initial value. Method credit (lines 19–22) does not return any data when it completes its task, so its return type is void. The method receives one parameter named amount—a double value that will be added to the balance. Line 21 adds amount to the current value of balance, then assigns the result to balance (thus replacing the prior balance amount). Method getBalance (lines 25–28) allows clients of the class (i.e., other classes that use this class) to obtain the value of a particular Account object’s balance. The method specifies return type double and an empty parameter list. Once again, the statements in lines 15, 21 and 27 use instance variable balance even though it was not declared in any of the methods. We can use balance in these methods because it’s an instance variable of the class.
Class to Use Class Account Class AccountTest (Fig. 3.14) creates two Account objects (lines 10–11) and initializes them with 50.00 and -7.53, respectively. Lines 14–17 output the balance in each Account AccountTest
58
Chapter 3
Introduction to Classes, Objects, Methods and Strings
by calling the Account’s getBalance method. When method getBalance is called for account1 from line 15, the value of account1’s balance is returned from line 27 of Fig. 3.13 and displayed by the System.out.printf statement (Fig. 3.14, lines 14–15). Similarly, when method getBalance is called for account2 from line 17, the value of account2’s balance is returned from line 27 of Fig. 3.13 and displayed by the System.out.printf statement (Fig. 3.14, lines 16–17). The balance of account2 is 0.00, because the constructor ensured that the account could not begin with a negative balance. The value is output by printf with the format specifier %.2f. The format specifier %f is used to output values of type float or double. The .2 between % and f represents the number of decimal places (2) that should be output to the right of the decimal point in the floating-point number—also known as the number’s precision. Any floating-point value output with %.2f will be rounded to the hundredths position—for example, 123.457 would be rounded to 123.46, 27.333 would be rounded to 27.33 and 123.455 would be rounded to 123.46. 1 2 3 4 5 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 33 34 35
// Fig. 3.14: AccountTest.java // Inputting and outputting floating-point numbers with Account objects. import java.util.Scanner; public class AccountTest { // main method begins execution of Java application public static void main( String[] args ) { Account account1 = new Account( 50.00 ); // create Account object Account account2 = new Account( -7.53 ); // create Account object // display initial balance of each object System.out.printf( "account1 balance: $%.2f\n", account1.getBalance() ); System.out.printf( "account2 balance: $%.2f\n\n", account2.getBalance() ); // create Scanner to obtain input from command window Scanner input = new Scanner( System.in ); double depositAmount; // deposit amount read from user System.out.print( "Enter deposit amount for account1: " ); // prompt depositAmount = input.nextDouble(); // obtain user input System.out.printf( "\nadding %.2f to account1 balance\n\n", depositAmount ); account1.credit( depositAmount ); // add to account1 balance // display balances System.out.printf( "account1 balance: $%.2f\n", account1.getBalance() ); System.out.printf( "account2 balance: $%.2f\n\n", account2.getBalance() ); System.out.print( "Enter deposit amount for account2: " ); // prompt
Fig. 3.14 | Inputting and outputting floating-point numbers with Account objects. (Part 1 of 2.)
3.7 Floating-Point Numbers and Type double
36 37 38 39 40 41 42 43 44 45 46 47
59
depositAmount = input.nextDouble(); // obtain user input System.out.printf( "\nadding %.2f to account2 balance\n\n", depositAmount ); account2.credit( depositAmount ); // add to account2 balance // display balances System.out.printf( "account1 balance: $%.2f\n", account1.getBalance() ); System.out.printf( "account2 balance: $%.2f\n", account2.getBalance() ); } // end main } // end class AccountTest
account1 balance: $50.00 account2 balance: $0.00 Enter deposit amount for account1: 25.53 adding 25.53 to account1 balance account1 balance: $75.53 account2 balance: $0.00 Enter deposit amount for account2: 123.45 adding 123.45 to account2 balance account1 balance: $75.53 account2 balance: $123.45
Fig. 3.14 | Inputting and outputting floating-point numbers with Account objects. (Part 2 of 2.) Line 21 declares local variable depositAmount to store each deposit amount entered by the user. Unlike the instance variable balance in class Account, local variable depositAmount in main is not initialized to 0.0 by default. However, this variable does not need to be initialized here, because its value will be determined by the user’s input. Line 23 prompts the user to enter a deposit amount for account1. Line 24 obtains the input from the user by calling Scanner object input’s nextDouble method, which returns a double value entered by the user. Lines 25–26 display the deposit amount. Line 27 calls object account1’s credit method and supplies depositAmount as the method’s argument. When the method is called, the argument’s value is assigned to parameter amount (line 19 of Fig. 3.13) of method credit (lines 19–22 of Fig. 3.13); then method credit adds that value to the balance (line 21 of Fig. 3.13). Lines 30–33 (Fig. 3.14) output the balances of both Accounts again to show that only account1’s balance changed. Line 35 prompts the user to enter a deposit amount for account2. Line 36 obtains the input from the user by calling Scanner object input’s nextDouble method. Lines 37–38 display the deposit amount. Line 39 calls object account2’s credit method and supplies depositAmount as the method’s argument; then method credit adds that value to the balance. Finally, lines 42–45 output the balances of both Accounts again to show that only account2’s balance changed.
60
Chapter 3
Introduction to Classes, Objects, Methods and Strings
UML Class Diagram for Class Account The UML class diagram in Fig. 3.15 models class Account of Fig. 3.13. The diagram models the private attribute balance with UML type Double to correspond to the class’s instance variable balance of Java type double. The diagram models class Account’s constructor with a parameter initialBalance of UML type Double in the third compartment of the class. The class’s two public methods are modeled as operations in the third compartment as well. The diagram models operation credit with an amount parameter of UML type Double (because the corresponding method has an amount parameter of Java type double), and operation getBalance with a return type of Double (because the corresponding Java method returns a double value). Account – balance : Double «constructor» Account( initialBalance : Double ) + credit( amount : Double ) + getBalance( ) : Double
Fig. 3.15 | UML class diagram indicating that class Account has a private balance attribute of UML type Double, a constructor (with a parameter of UML type Double) and two public operations—credit (with an amount parameter of UML type Double) and getBalance (returns UML type Double).
3.8 Wrap-Up In this chapter, you learned how to declare instance variables of a class to maintain data for each object of the class, and how to declare methods that operate on that data. You learned how to call a method to tell it to perform its task and how to pass information to methods as arguments. You learned the difference between a local variable of a method and an instance variable of a class and that only instance variables are initialized automatically. You also learned how to use a class’s constructor to specify the initial values for an object’s instance variables. Throughout the chapter, you saw how the UML can be used to create class diagrams that model the constructors, methods and attributes of classes. Finally, you learned about floating-point numbers—how to store them with variables of primitive type double, how to input them with a Scanner object and how to format them with printf and format specifier %f for display purposes. In the next chapter we begin our introduction to control statements, which specify the order in which a program’s actions are performed. You’ll use these in your methods to specify how they should perform their tasks.
4 Control Statements: Part 1
Let’s all move one place on. —Lewis Carroll
The wheel is come full circle. —William Shakespeare
How many apples fell on Newton’s head before he took the hint!
Objectives In this chapter you’ll learn: I
To use the if and if…else selection statements to choose among alternative actions.
I
To use the while repetition statement to execute statements in a program repeatedly.
I
To use counter-controlled repetition and sentinel-controlled repetition.
I
To use the compound assignment, increment and decrement operators.
I
The portability of primitive data types.
—Robert Frost
62
Chapter 4
Control Statements: Part 1
4.1 4.2 4.3 4.4
Introduction Control Structures if Single-Selection Statement if…else Double-Selection Statement 4.5 while Repetition Statement 4.6 Counter-Controlled Repetition
4.7 4.8 4.9 4.10 4.11 4.12
Sentinel-Controlled Repetition Nested Control Statements Compound Assignment Operators Increment and Decrement Operators Primitive Types Wrap-Up
4.1 Introduction In this chapter, we introduce Java’s if, if…else and while statements, three of the building blocks that allow you to specify the logic required for methods to perform their tasks. We devote a portion of this chapter (and Chapters 5 and 7) to further developing the GradeBook class introduced in Chapter 3. In particular, we add a method to the GradeBook class that uses control statements to calculate the average of a set of student grades. Another example demonstrates additional ways to combine control statements to solve a similar problem. We introduce Java’s compound assignment, increment and decrement operators. Finally, we discuss the portability of Java’s primitive types.
4.2 Control Structures Normally, statements in a program are executed one after the other in the order in which they’re written. This process is called sequential execution. Various Java statements, which we’ll soon discuss, enable you to specify that the next statement to execute is not necessarily the next one in sequence. This is called transfer of control. During the 1960s, it became clear that the indiscriminate use of transfers of control was the root of much difficulty experienced by software development groups. The blame was pointed at the goto statement (used in most programming languages of the time), which allows you to specify a transfer of control to one of a wide range of destinations in a program. The term structured programming became almost synonymous with “goto elimination.” [Note: Java does not have a goto statement; however, the word goto is reserved by Java and should not be used as an identifier in programs.] Bohm and Jacopini’s work demonstrated that all programs could be written in terms of only three control structures—the sequence structure, the selection structure and the repetition structure.1 When we introduce Java’s control structure implementations, we’ll refer to them in the terminology of the Java Language Specification as “control statements.”
Sequence Structure in Java The sequence structure is built into Java. Unless directed otherwise, the computer executes Java statements one after the other in the order in which they’re written—that is, in sequence. The activity diagram in Fig. 4.1 illustrates a typical sequence structure in which two calculations are performed in order. Java lets you have as many actions as you want in 1.
Bohm, C., and G. Jacopini, “Flow Diagrams, Turing Machines, and Languages with Only Two Formation Rules,” Communications of the ACM, Vol. 9, No. 5, May 1966, pp. 336–371.
4.2 Control Structures
add grade to total
add 1 to counter
63
Corresponding Java statement: total = total + grade;
Corresponding Java statement: counter = counter + 1;
Fig. 4.1 | Sequence structure activity diagram. a sequence structure. As we’ll soon see, anywhere a single action may be placed, we may place several actions in sequence. A UML activity diagram models the workflow (also called the activity) of a portion of a software system. Such workflows may include a portion of an algorithm, like the sequence structure in Fig. 4.1. Activity diagrams are composed of symbols, such as actionstate symbols (rectangles with their left and right sides replaced with outward arcs), diamonds and small circles. These symbols are connected by transition arrows, which represent the flow of the activity—that is, the order in which the actions should occur. Activity diagrams help you develop and represent algorithms. They also clearly show how control structures operate. We use the UML in this chapter and Chapter 5 to show control flow in control statements. In Chapters 12–13, we use the UML in a real-world automated-teller machine case study. Consider the sequence structure activity diagram in Fig. 4.1. It contains two action states that represent actions to perform. Each action state contains an action expression— for example, “add grade to total” or “add 1 to counter”—that specifies a particular action to perform. Other actions might include calculations or input/output operations. The arrows in the activity diagram represent transitions, which indicate the order in which the actions represented by the action states occur. The program that implements the activities illustrated by the diagram in Fig. 4.1 first adds grade to total, then adds 1 to counter. The solid circle at the top of the activity diagram represents the initial state—the beginning of the workflow before the program performs the modeled actions. The solid circle surrounded by a hollow circle that appears at the bottom of the diagram represents the final state—the end of the workflow after the program performs its actions. Figure 4.1 also includes rectangles with the upper-right corners folded over. These are UML notes (like comments in Java)—explanatory remarks that describe the purpose of symbols in the diagram. Figure 4.1 uses UML notes to show the Java code associated with each action state. A dotted line connects each note with the element it describes. Activity diagrams normally do not show the Java code that implements the activity. We do this here to illustrate how the diagram relates to Java code. For more information on the UML, see our case study (Chapters 12–13) or visit www.uml.org.
Selection Statements in Java Java has three types of selection statements (discussed in this chapter and Chapter 5). The if statement either performs (selects) an action, if a condition is true, or skips it, if the con-
64
Chapter 4
Control Statements: Part 1
dition is false. The if…else statement performs an action if a condition is true and performs a different action if the condition is false. The switch statement (Chapter 5) performs one of many different actions, depending on the value of an expression. The if statement is a single-selection statement because it selects or ignores a single action (or, as we’ll soon see, a single group of actions). The if…else statement is called a double-selection statement because it selects between two different actions (or groups of actions). The switch statement is called a multiple-selection statement because it selects among many different actions (or groups of actions).
Repetition Statements in Java Java provides three repetition statements (also called looping statements) that enable programs to perform statements repeatedly as long as a condition (called the loop-continuation condition) remains true. The repetition statements are the while, do…while and for statements. (Chapter 5 presents the do…while and for statements.) The while and for statements perform the action (or group of actions) in their bodies zero or more times— if the loop-continuation condition is initially false, the action (or group of actions) will not execute. The do…while statement performs the action (or group of actions) in its body one or more times. The words if, else, switch, while, do and for are Java keywords. A complete list of Java keywords appears in Appendix C. Summary of Control Statements in Java Java has only three kinds of control structures, which from this point forward we refer to as control statements: the sequence statement, selection statements (three types) and repetition statements (three types). Every program is formed by combining as many of these statements as is appropriate for the algorithm the program implements. We can model each control statement as an activity diagram. Like Fig. 4.1, each diagram contains an initial state and a final state that represent a control statement’s entry point and exit point, respectively. Single-entry/single-exit control statements make it easy to build programs— we simply connect the exit point of one to the entry point of the next. We call this controlstatement stacking. We’ll learn that there’s only one other way in which control statements may be connected—control-statement nesting—in which one control statement appears inside another. Thus, algorithms in Java programs are constructed from only three kinds of control statements, combined in only two ways. This is the essence of simplicity.
4.3 if Single-Selection Statement Programs use selection statements to choose among alternative courses of action. For example, suppose that the passing grade on an exam is 60. The statement if ( studentGrade >= 60 ) System.out.println( "Passed" );
determines whether the condition studentGrade >= 60 is true. If so, "Passed" is printed, and the next statement in order is performed. If the condition is false, the body statement is ignored, and the next statement in order is performed. Figure 4.2 illustrates the single-selection if statement. This figure contains the most important symbol in an activity diagram—the diamond, or decision symbol, which indicates that a decision is to be made. The workflow continues along a path determined by
4.4 if…else Double-Selection Statement
65
the symbol’s associated guard conditions, which can be true or false. Each transition arrow emerging from a decision symbol has a guard condition (specified in square brackets next to the arrow). If a guard condition is true, the workflow enters the action state to which the transition arrow points. In Fig. 4.2, if the grade is greater than or equal to 60, the program prints “Passed,” then transitions to the activity’s final state. If the grade is less than 60, the program immediately transitions to the final state without displaying a message.
[grade >= 60]
print “Passed”
[grade < 60]
Fig. 4.2 |
if
single-selection statement UML activity diagram.
The if statement is a single-entry/single-exit control statement. We’ll see that the activity diagrams for the remaining control statements also contain initial states, transition arrows, action states that indicate actions to perform, decision symbols (with associated guard conditions) that indicate decisions to be made, and final states.
4.4 if…else Double-Selection Statement The if single-selection statement performs an indicated action only when the condition is true; otherwise, the action is skipped. The if…else double-selection statement allows you to specify an action to perform when the condition is true and a different action when the condition is false. For example, the statement if ( grade >= 60 ) System.out.println( "Passed" ); else System.out.println( "Failed" );
prints "Passed" if the student’s grade is greater than or equal to 60, but prints "Failed" if it’s less than 60. In either case, after printing occurs, the next statement in sequence is performed. Figure 4.3 illustrates the flow of control in the if…else statement. Once again, the symbols in the UML activity diagram (besides the initial state, transition arrows and final state) represent action states and decisions.
print “Failed”
Fig. 4.3 |
if…else
[grade < 60]
[grade >= 60]
double-selection statement UML activity diagram.
print “Passed”
66
Chapter 4
Control Statements: Part 1
Conditional Operator (?:) Java provides the conditional operator (?:) that can be used in place of an if…else statement. This is Java’s only ternary operator (operator that takes three operands). Together, the operands and the ?: symbol form a conditional expression. The first operand (to the left of the ?) is a boolean expression (i.e., a condition that evaluates to a boolean value—true or false), the second operand (between the ? and :) is the value of the conditional expression if the boolean expression is true and the third operand (to the right of the :) is the value of the conditional expression if the boolean expression evaluates to false. For example, the statement System.out.println( studentGrade >= 60 ? "Passed" : "Failed" );
prints the value of println’s conditional-expression argument. The conditional expression in this statement evaluates to the string "Passed" if the boolean expression studentGrade >= 60 is true and to the string "Failed" if it’s false. Thus, this statement with the conditional operator performs essentially the same function as the if…else statement shown earlier in this section. The precedence of the conditional operator is low, so the entire conditional expression is normally placed in parentheses. We’ll see that conditional expressions can be used in some situations where if…else statements cannot.
Nested if…else Statements A program can test multiple cases by placing if…else statements inside other if…else statements to create nested if…else statements. For example, the following nested if…else statements print A for exam grades greater than or equal to 90, B for grades 80 to 89, C for grades 70 to 79, D for grades 60 to 69 and F for all other grades: if ( studentGrade >= 90 ) System.out.println( "A" ); else if ( studentGrade >= 80 ) System.out.println( "B" ); else if ( studentGrade >= 70 ) System.out.println( "C" ); else if ( studentGrade >= 60 ) System.out.println( "D" ); else System.out.println( "F" );
If variable studentGrade is greater than or equal to 90, the first four conditions in the nested if…else statement will be true, but only the statement in the if part of the first if…else statement will execute. After that statement executes, the else part of the “outermost” if…else statement is skipped. Many programmers prefer to write the preceding nested if…else statement as if ( studentGrade >= 90 ) System.out.println( "A" ); else if ( studentGrade >= 80 ) System.out.println( "B" ); else if ( studentGrade >= 70 ) System.out.println( "C" );
4.4 if…else Double-Selection Statement
67
else if ( studentGrade >= 60 ) System.out.println( "D" ); else System.out.println( "F" );
The two forms are identical except for the spacing and indentation, which the compiler ignores. The latter form avoids deep indentation of the code to the right. Such indentation often leaves little room on a line of source code, forcing lines to be split.
Dangling-else Problem The Java compiler always associates an else with the immediately preceding if unless told to do otherwise by the placement of braces ({ and }). This behavior can lead to what is referred to as the dangling-else problem. For example, if ( x > 5 ) if ( y > 5 ) System.out.println( "x and y are > 5" ); else System.out.println( "x is 5" is output. Otherwise, it appears that if x is not greater than 5, the else part of the if…else outputs the string "x is 5" ); else System.out.println( "x is 5"—is displayed. However, if the second condition is false, the string "x is 5" ); } else System.out.println( "x is = 0.0" ); } // end method setGrossSales // return gross sales amount public double getGrossSales() { return grossSales; } // end method getGrossSales // set commission rate public void setCommissionRate( double rate ) { if ( rate > 0.0 && rate < 1.0 ) commissionRate = rate; else throw new IllegalArgumentException( "Commission rate must be > 0.0 and < 1.0" ); } // end method setCommissionRate // return commission rate public double getCommissionRate() { return commissionRate; } // end method getCommissionRate // calculate earnings public double earnings() { return commissionRate * grossSales; } // end method earnings // return String representation of CommissionEmployee object @Override // indicates that this method overrides a superclass method public String toString() { return String.format( "%s: %s %s\n%s: %s\n%s: %.2f\n%s: %.2f", "commission employee", firstName, lastName,
Fig. 9.4 | (Part 2 of 3.)
CommissionEmployee
class represents an employee paid a percentage of gross sales.
232
Chapter 9 Object-Oriented Programming: Inheritance
104 "social security number", socialSecurityNumber, "gross sales", grossSales, 105 "commission rate", commissionRate ); 106 107 } // end method toString 108 } // end class CommissionEmployee
Fig. 9.4 |
CommissionEmployee
class represents an employee paid a percentage of gross sales.
(Part 3 of 3.)
Class CommissionEmployee’s Constructor Constructors are not inherited, so class CommissionEmployee does not inherit class Object’s constructor. However, a superclass’s constructors are still available to subclasses. In fact, the first task of any subclass constructor is to call its direct superclass’s constructor, either explicitly or implicitly (if no constructor call is specified), to ensure that the instance variables inherited from the superclass are initialized properly. In this example, class CommissionEmployee’s constructor calls class Object’s constructor implicitly. The syntax for calling a superclass constructor explicitly is discussed in Section 9.4.3. If the code does not include an explicit call to the superclass constructor, Java implicitly calls the superclass’s default or no-argument constructor. The comment in line 16 of Fig. 9.4 indicates where the implicit call to the superclass Object’s default constructor is made (you do not write the code for this call). Object’s default (empty) constructor does nothing. Even if a class does not have constructors, the default constructor that the compiler implicitly declares for the class will call the superclass’s default or no-argument constructor. After the implicit call to Object’s constructor, lines 17–21 of CommissionEmployee’s constructor assign values to the class’s instance variables. We do not validate the values of arguments first, last and ssn before assigning them to the corresponding instance variables. We could validate the first and last names—perhaps to ensure that they’re of a reasonable length. Similarly, a social security number could be validated using regular expressions (Section 16.7) to ensure that it contains nine digits, with or without dashes (e.g., 123-45-6789 or 123456789). Class CommissionEmployee’s earnings Method Method earnings (lines 93–96) calculates a CommissionEmployee’s earnings. Line 95 multiplies the commissionRate by the grossSales and returns the result. Class CommissionEmployee’s toString Method and the @Override Annotation Method toString (lines 99–107) is special—it’s one of the methods that every class inherits directly or indirectly from class Object (summarized in Section 9.7). Method toString returns a String representing an object. It’s called implicitly whenever an object must be converted to a String representation, such as when an object is output by printf or output by String method format via the %s format specifier. Class Object’s toString method returns a String that includes the name of the object’s class. It’s primarily a placeholder that can be overridden by a subclass to specify an appropriate String representation of the data in a subclass object. Method toString of class CommissionEmployee overrides (redefines) class Object’s toString method. When invoked, CommissionEmployee’s toString method uses String method format to return a String containing information about the CommissionEmployee. To override a superclass method, a subclass must declare a method
9.4 Relationship between Superclasses and Subclasses
233
with the same signature (method name, number of parameters, parameter types and order of parameter types) as the superclass method—Object’s toString method takes no parameters, so CommissionEmployee declares toString with no parameters. Line 99 uses the @Override annotation to indicate that method toString should override a superclass method. Annotations have several purposes. For example, when you attempt to override a superclass method, common errors include naming the subclass method incorrectly, or using the wrong number or types of parameters in the parameter list. Each of these problems creates an unintentional overload of the superclass method. If you then attempt to call the method on a subclass object, the superclass’s version is invoked and the subclass version is ignored—potentially leading to subtle logic errors. When the compiler encounters a method declared with @Override, it compares the method’s signature with the superclass’s method signatures. If there isn’t an exact match, the compiler issues an error message, such as “method does not override or implement a method from a supertype.” This indicates that you’ve accidentally overloaded a superclass method. You can then fix your method’s signature so that it matches one in the superclass. As you’ll see when we discuss web applications and web services in Chapters 26–28, annotations can also add complex support code to your classes to simplify the development process and can be used by servers to configure certain aspects of web applications.
Common Programming Error 9.1 Using an incorrect method signature when attempting to override a superclass method causes an unintentional method overload that can lead to subtle logic errors.
Error-Prevention Tip 9.1 Declare overridden methods with the @Override annotation to ensure at compilation time that you defined their signatures correctly. It’s always better to find errors at compile time rather than at runtime.
Common Programming Error 9.2 It’s a syntax error to override a method with a more restricted access modifier—a public method of the superclass cannot become a protected or private method in the subclass; a protected method of the superclass cannot become a private method in the subclass. Doing so would break the is-a relationship in which it’s required that all subclass objects be able to respond to method calls that are made to public methods declared in the superclass. If a public method, for example, could be overridden as a protected or private method, the subclass objects would not be able to respond to the same method calls as superclass objects. Once a method is declared public in a superclass, the method remains public for all that class’s direct and indirect subclasses.
Class CommissionEmployeeTest Figure 9.5 tests class CommissionEmployee. Lines 9–10 instantiate a CommissionEmployee object and invoke CommissionEmployee’s constructor (lines 13–22 of Fig. 9.4) to initialize it with "Sue" as the first name, "Jones" as the last name, "222-22-2222" as the social security number, 10000 as the gross sales amount and .06 as the commission rate. Lines 15– 24 use CommissionEmployee’s get methods to retrieve the object’s instance-variable values for output. Lines 26–27 invoke the object’s methods setGrossSales and setCommissionRate to change the values of instance variables grossSales and commissionRate. Lines
234
Chapter 9 Object-Oriented Programming: Inheritance
29–30 output the String representation of the updated CommissionEmployee. When an object is output using the %s format specifier, the object’s toString method is invoked implicitly to obtain the object’s String representation. [Note: In this chapter, we do not use the earnings methods of our classes—they’re used extensively in Chapter 10.] 1 2 3 4 5 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
// Fig. 9.5: CommissionEmployeeTest.java // CommissionEmployee class test program. public class CommissionEmployeeTest { public static void main( String[] args ) { // instantiate CommissionEmployee object CommissionEmployee employee = new CommissionEmployee( "Sue", "Jones", "222-22-2222", 10000, .06 ); // get commission employee data System.out.println( "Employee information obtained by get methods: \n" ); System.out.printf( "%s %s\n", "First name is", employee.getFirstName() ); System.out.printf( "%s %s\n", "Last name is", employee.getLastName() ); System.out.printf( "%s %s\n", "Social security number is", employee.getSocialSecurityNumber() ); System.out.printf( "%s %.2f\n", "Gross sales is", employee.getGrossSales() ); System.out.printf( "%s %.2f\n", "Commission rate is", employee.getCommissionRate() ); employee.setGrossSales( 500 ); // set gross sales employee.setCommissionRate( .1 ); // set commission rate System.out.printf( "\n%s:\n\n%s\n", "Updated employee information obtained by toString", employee ); } // end main } // end class CommissionEmployeeTest
Employee information obtained by get methods: First name is Sue Last name is Jones Social security number is 222-22-2222 Gross sales is 10000.00 Commission rate is 0.06 Updated employee information obtained by toString: commission employee: Sue Jones social security number: 222-22-2222 gross sales: 500.00 commission rate: 0.10
Fig. 9.5 |
CommissionEmployee
class test program.
9.4 Relationship between Superclasses and Subclasses
235
9.4.2 Creating and Using a BasePlusCommissionEmployee Class We now discuss the second part of our introduction to inheritance by declaring and testing (a completely new and independent) class BasePlusCommissionEmployee (Fig. 9.6), which contains a first name, last name, social security number, gross sales amount, commission rate and base salary. Class BasePlusCommissionEmployee’s public services include a BasePlusCommissionEmployee constructor (lines 15–25) and methods earnings (lines 112–115) and toString (lines 118–127). Lines 28–109 declare public get and set methods for the class’s private instance variables (declared in lines 7–12) firstName, lastName, socialSecurityNumber, grossSales, commissionRate and baseSalary. These variables and methods encapsulate all the necessary features of a base-salaried commission employee. Note the similarity between this class and class CommissionEmployee (Fig. 9.4)—in this example, we’ll not yet exploit that similarity.
1 2 3 4 5 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 33 34 35
// Fig. 9.6: BasePlusCommissionEmployee.java // BasePlusCommissionEmployee class represents an employee who receives // a base salary in addition to commission. public class BasePlusCommissionEmployee { private String firstName; private String lastName; private String socialSecurityNumber; private double grossSales; // gross weekly sales private double commissionRate; // commission percentage private double baseSalary; // base salary per week // six-argument constructor public BasePlusCommissionEmployee( String first, String last, String ssn, double sales, double rate, double salary ) { // implicit call to Object constructor occurs here firstName = first; lastName = last; socialSecurityNumber = ssn; setGrossSales( sales ); // validate and store gross sales setCommissionRate( rate ); // validate and store commission rate setBaseSalary( salary ); // validate and store base salary } // end six-argument BasePlusCommissionEmployee constructor // set first name public void setFirstName( String first ) { firstName = first; // should validate } // end method setFirstName // return first name public String getFirstName() {
Fig. 9.6 |
BasePlusCommissionEmployee class represents an employee who receives a base salary in addition to a commission. (Part 1 of 3.)
236
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
Chapter 9 Object-Oriented Programming: Inheritance
return firstName; } // end method getFirstName // set last name public void setLastName( String last ) { lastName = last; // should validate } // end method setLastName // return last name public String getLastName() { return lastName; } // end method getLastName // set social security number public void setSocialSecurityNumber( String ssn ) { socialSecurityNumber = ssn; // should validate } // end method setSocialSecurityNumber // return social security number public String getSocialSecurityNumber() { return socialSecurityNumber; } // end method getSocialSecurityNumber // set gross sales amount public void setGrossSales( double sales ) { if ( sales >= 0.0 ) grossSales = sales; else throw new IllegalArgumentException( "Gross sales must be >= 0.0" ); } // end method setGrossSales // return gross sales amount public double getGrossSales() { return grossSales; } // end method getGrossSales // set commission rate public void setCommissionRate( double rate ) { if ( rate > 0.0 && rate < 1.0 ) commissionRate = rate; else throw new IllegalArgumentException( "Commission rate must be > 0.0 and < 1.0" ); } // end method setCommissionRate
Fig. 9.6 |
BasePlusCommissionEmployee class represents an employee who receives a base salary in addition to a commission. (Part 2 of 3.)
9.4 Relationship between Superclasses and Subclasses
237
88 89 // return commission rate 90 public double getCommissionRate() 91 { 92 return commissionRate; 93 } // end method getCommissionRate 94 95 // set base salary 96 public void setBaseSalary( double salary ) 97 { 98 if ( salary >= 0.0 ) 99 baseSalary = salary; 100 else 101 throw new IllegalArgumentException( 102 "Base salary must be >= 0.0" ); 103 } // end method setBaseSalary 104 // return base salary 105 public double getBaseSalary() 106 { 107 return baseSalary; 108 } // end method getBaseSalary 109 110 111 // calculate earnings 112 public double earnings() 113 { 114 return baseSalary + ( commissionRate * grossSales ); 115 } // end method earnings 116 117 // return String representation of BasePlusCommissionEmployee 118 @Override // indicates that this method overrides a superclass method 119 public String toString() 120 { 121 return String.format( 122 "%s: %s %s\n%s: %s\n%s: %.2f\n%s: %.2f\n%s: %.2f", 123 "base-salaried commission employee", firstName, lastName, 124 "social security number", socialSecurityNumber, 125 "gross sales", grossSales, "commission rate", commissionRate, "base salary", baseSalary ); 126 127 } // end method toString 128 } // end class BasePlusCommissionEmployee
Fig. 9.6 |
BasePlusCommissionEmployee class represents an employee who receives a base salary in addition to a commission. (Part 3 of 3.)
Class BasePlusCommissionEmployee does not specify “extends Object” in line 5, so the class implicitly extends Object. Also, like class CommissionEmployee’s constructor (lines 13–22 of Fig. 9.4), class BasePlusCommissionEmployee’s constructor invokes class Object’s default constructor implicitly, as noted in the comment in line 18. Class BasePlusCommissionEmployee’s earnings method (lines 112–115) returns the result of adding the BasePlusCommissionEmployee’s base salary to the product of the commission rate and the employee’s gross sales.
238
Chapter 9 Object-Oriented Programming: Inheritance
Class BasePlusCommissionEmployee overrides Object method toString to return a containing the BasePlusCommissionEmployee’s information. Once again, we use format specifier %.2f to format the gross sales, commission rate and base salary with two digits of precision to the right of the decimal point (line 122). String
Testing Class BasePlusCommissionEmployee Figure 9.7 tests class BasePlusCommissionEmployee. Lines 9–11 create a BasePlusCommissionEmployee object and pass "Bob", "Lewis", "333-33-3333", 5000, .04 and 300 to the constructor as the first name, last name, social security number, gross sales, commission rate and base salary, respectively. Lines 16–27 use BasePlusCommissionEmployee’s get methods to retrieve the values of the object’s instance variables for output. Line 29 invokes the object’s setBaseSalary method to change the base salary. Method setBaseSalary (Fig. 9.6, lines 88–91) ensures that instance variable baseSalary is not assigned a negative value. Lines 31– 33 of Fig. 9.7 invoke method toString explicitly to get the object’s String representation. 1 2 3 4 5 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 33 34 35
// Fig. 9.7: BasePlusCommissionEmployeeTest.java // BasePlusCommissionEmployee test program. public class BasePlusCommissionEmployeeTest { public static void main( String[] args ) { // instantiate BasePlusCommissionEmployee object BasePlusCommissionEmployee employee = new BasePlusCommissionEmployee( "Bob", "Lewis", "333-33-3333", 5000, .04, 300 ); // get base-salaried commission employee data System.out.println( "Employee information obtained by get methods: \n" ); System.out.printf( "%s %s\n", "First name is", employee.getFirstName() ); System.out.printf( "%s %s\n", "Last name is", employee.getLastName() ); System.out.printf( "%s %s\n", "Social security number is", employee.getSocialSecurityNumber() ); System.out.printf( "%s %.2f\n", "Gross sales is", employee.getGrossSales() ); System.out.printf( "%s %.2f\n", "Commission rate is", employee.getCommissionRate() ); System.out.printf( "%s %.2f\n", "Base salary is", employee.getBaseSalary() ); employee.setBaseSalary( 1000 ); // set base salary System.out.printf( "\n%s:\n\n%s\n", "Updated employee information obtained by toString", employee.toString() ); } // end main } // end class BasePlusCommissionEmployeeTest
Fig. 9.7 |
BasePlusCommissionEmployee
test program. (Part 1 of 2.)
9.4 Relationship between Superclasses and Subclasses
239
Employee information obtained by get methods: First name is Bob Last name is Lewis Social security number is 333-33-3333 Gross sales is 5000.00 Commission rate is 0.04 Base salary is 300.00 Updated employee information obtained by toString: base-salaried commission employee: Bob Lewis social security number: 333-33-3333 gross sales: 5000.00 commission rate: 0.04 base salary: 1000.00
Fig. 9.7 |
BasePlusCommissionEmployee
test program. (Part 2 of 2.)
Notes on Class BasePlusCommissionEmployee Much of class BasePlusCommissionEmployee’s code (Fig. 9.6) is similar, or identical, to that of class CommissionEmployee (Fig. 9.4). For example, private instance variables firstName and lastName and methods setFirstName, getFirstName, setLastName and getLastName are identical to those of class CommissionEmployee. The classes also both contain private instance variables socialSecurityNumber, commissionRate and grossSales, and corresponding get and set methods. In addition, the BasePlusCommissionEmployee constructor is almost identical to that of class CommissionEmployee, except that BasePlusCommissionEmployee’s constructor also sets the baseSalary. The other additions to class BasePlusCommissionEmployee are private instance variable baseSalary and methods setBaseSalary and getBaseSalary. Class BasePlusCommissionEmployee’s toString method is nearly identical to that of class CommissionEmployee except that it also outputs instance variable baseSalary with two digits of precision to the right of the decimal point. We literally copied code from class CommissionEmployee and pasted it into class BasePlusCommissionEmployee, then modified class BasePlusCommissionEmployee to include a base salary and methods that manipulate the base salary. This “copy-and-paste” approach is often error prone and time consuming. Worse yet, it spreads copies of the same code throughout a system, creating a code-maintenance nightmare. Is there a way to “absorb” the instance variables and methods of one class in a way that makes them part of other classes without duplicating code? Next we answer this question, using a more elegant approach to building classes that emphasizes the benefits of inheritance.
Software Engineering Observation 9.3 With inheritance, the common instance variables and methods of all the classes in the hierarchy are declared in a superclass. When changes are made for these common features in the superclass—subclasses then inherit the changes. Without inheritance, changes would need to be made to all the source-code files that contain a copy of the code in question.
240
Chapter 9 Object-Oriented Programming: Inheritance
9.4.3 Creating a CommissionEmployee– BasePlusCommissionEmployee Inheritance Hierarchy Now we redeclare class BasePlusCommissionEmployee (Fig. 9.8) to extend class CommissionEmployee (Fig. 9.4). A BasePlusCommissionEmployee object is a CommissionEmployee, because inheritance passes on class CommissionEmployee’s capabilities. Class BasePlus-CommissionEmployee also has instance variable baseSalary (Fig. 9.8, line 6). Keyword extends (line 4) indicates inheritance. BasePlusCommissionEmployee inherits CommissionEmployee’s instance variables and methods, but only the superclass’s public and protected members are directly accessible in the subclass. The CommissionEmployee constructor is not inherited. So, the public BasePlusCommissionEmployee services include its constructor (lines 9–16), public methods inherited from CommissionEmployee, and methods setBaseSalary (lines 19–26), getBaseSalary (lines 29–32), earnings (lines 35–40) and toString (lines 43–53). Methods earnings and toString override the corresponding methods in class CommissionEmployee because their superclass versions do not properly calculate a BasePlusCommissionEmployee’s earnings or return an appropriate String representation. 1 2 3 4 5 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
// Fig. 9.8: BasePlusCommissionEmployee.java // private superclass members cannot be accessed in a subclass. public class BasePlusCommissionEmployee extends CommissionEmployee { private double baseSalary; // base salary per week // six-argument constructor public BasePlusCommissionEmployee( String first, String last, String ssn, double sales, double rate, double salary ) { // explicit call to superclass CommissionEmployee constructor super( first, last, ssn, sales, rate ); setBaseSalary( salary ); // validate and store base salary } // end six-argument BasePlusCommissionEmployee constructor // set base salary public void setBaseSalary( double salary ) { if ( salary >= 0.0 ) baseSalary = salary; else throw new IllegalArgumentException( "Base salary must be >= 0.0" ); } // end method setBaseSalary // return base salary public double getBaseSalary() { return baseSalary; } // end method getBaseSalary
Fig. 9.8 |
private
superclass members cannot be accessed in a subclass. (Part 1 of 2.)
9.4 Relationship between Superclasses and Subclasses
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
241
// calculate earnings @Override // indicates that this method overrides a superclass method public double earnings() { // not allowed: commissionRate and grossSales private in superclass return baseSalary + ( commissionRate * grossSales ); } // end method earnings // return String representation of BasePlusCommissionEmployee @Override // indicates that this method overrides a superclass method public String toString() { // not allowed: attempts to access private superclass members return String.format( "%s: %s %s\n%s: %s\n%s: %.2f\n%s: %.2f\n%s: %.2f", "base-salaried commission employee", firstName, lastName, "social security number", socialSecurityNumber, "gross sales", grossSales, "commission rate", commissionRate, "base salary", baseSalary ); } // end method toString } // end class BasePlusCommissionEmployee
BasePlusCommissionEmployee.java:39: commissionRate has private access in CommissionEmployee return baseSalary + ( commissionRate * grossSales ); ^ BasePlusCommissionEmployee.java:39: grossSales has private access in CommissionEmployee return baseSalary + ( commissionRate * grossSales ); ^ BasePlusCommissionEmployee.java:49: firstName has private access in CommissionEmployee "base-salaried commission employee", firstName, lastName, ^ BasePlusCommissionEmployee.java:49: lastName has private access in CommissionEmployee "base-salaried commission employee", firstName, lastName, ^ BasePlusCommissionEmployee.java:50: socialSecurityNumber has private access in CommissionEmployee "social security number", socialSecurityNumber, ^ BasePlusCommissionEmployee.java:51: grossSales has private access in CommissionEmployee "gross sales", grossSales, "commission rate", commissionRate, ^ BasePlusCommissionEmployee.java:51: commissionRate has private access in CommissionEmployee "gross sales", grossSales, "commission rate", commissionRate, ^ 7 errors
Fig. 9.8 |
private
superclass members cannot be accessed in a subclass. (Part 2 of 2.)
242
Chapter 9 Object-Oriented Programming: Inheritance
A Subclass’s Constructor Must Call Its Superclass’s Constructor Each subclass constructor must implicitly or explicitly call its superclass constructor to initialize the instance variables inherited from the superclass. Line 13 in BasePlusCommissionEmployee’s six-argument constructor (lines 9–16) explicitly calls class CommissionEmployee’s five-argument constructor (declared at lines 13–22 of Fig. 9.4) to initialize the superclass portion of a BasePlusCommissionEmployee object (i.e., variables firstName, lastName, socialSecurityNumber, grossSales and commissionRate). We do this by using the superclass constructor call syntax—keyword super, followed by a set of parentheses containing the superclass constructor arguments. The arguments first, last, ssn, sales and rate are used to initialize superclass members firstName, lastName, socialSecurityNumber, grossSales and commissionRate, respectively. If BasePlusCommissionEmployee’s constructor did not invoke the superclass’s constructor explicitly, Java would attempt to invoke the superclass’s no-argument or default constructor. Class CommissionEmployee does not have such a constructor, so the compiler would issue an error. The explicit superclass constructor call in line 13 of Fig. 9.8 must be the first statement in the subclass constructor’s body. When a superclass contains a no-argument constructor, you can use super() to call that constructor explicitly, but this is rarely done. Method Earnings The compiler generates errors for line 39 because superclass CommissionEmployee’s instance variables commissionRate and grossSales are private—subclass BasePlusCommissionEmployee’s methods are not allowed to access superclass CommissionEmployee’s private instance variables. The compiler issues additional errors at lines 49–51 of BasePlusCommissionEmployee’s toString method for the same reason. The errors in BasePlusCommissionEmployee could have been prevented by using the get methods inherited from class CommissionEmployee. For example, line 39 could have used getCommissionRate and getGrossSales to access CommissionEmployee’s private instance variables commissionRate and grossSales, respectively. Lines 49–51 also could have used appropriate get methods to retrieve the values of the superclass’s instance variables. BasePlusCommissionEmployee
9.4.4 CommissionEmployee–BasePlusCommissionEmployee Inheritance Hierarchy Using protected Instance Variables To enable class BasePlusCommissionEmployee to directly access superclass instance variables firstName, lastName, socialSecurityNumber, grossSales and commissionRate, we can declare those members as protected in the superclass. As we discussed in Section 9.3, a superclass’s protected members are accessible by all subclasses of that superclass. In the new CommissionEmployee class, we modified only lines 6–10 of Fig. 9.4 to declare the instance variables with the protected access modifier as follows: protected protected protected protected protected
String String String double double
firstName; lastName; socialSecurityNumber; grossSales; // gross weekly sales commissionRate; // commission percentage
The rest of the class declaration (which is not shown here) is identical to that of Fig. 9.4. We could have declared CommissionEmployee’s instance variables public to enable subclass BasePlusCommissionEmployee to access them. However, declaring public
9.4 Relationship between Superclasses and Subclasses
243
instance variables is poor software engineering because it allows unrestricted access to the these variables, greatly increasing the chance of errors. With protected instance variables, the subclass gets access to the instance variables, but classes that are not subclasses and classes that are not in the same package cannot access these variables directly—recall that protected class members are also visible to other classes in the same package.
Class BasePlusCommissionEmployee Class BasePlusCommissionEmployee (Fig. 9.9) extends the new version of class CommissionEmployee with protected instance variables. BasePlusCommissionEmployee objects inherit CommissionEmployee’s protected instance variables firstName, lastName, socialSecurityNumber, grossSales and commissionRate—all these variables are now protected members of BasePlusCommissionEmployee. As a result, the compiler does not generate errors when compiling line 37 of method earnings and lines 46–48 of method toString. If another class extends this version of class BasePlusCommissionEmployee, the new subclass also can access the protected members.
1 2 3 4 5 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
// Fig. 9.9: BasePlusCommissionEmployee.java // BasePlusCommissionEmployee inherits protected instance // variables from CommissionEmployee. public class BasePlusCommissionEmployee extends CommissionEmployee { private double baseSalary; // base salary per week // six-argument constructor public BasePlusCommissionEmployee( String first, String last, String ssn, double sales, double rate, double salary ) { super( first, last, ssn, sales, rate ); setBaseSalary( salary ); // validate and store base salary } // end six-argument BasePlusCommissionEmployee constructor // set base salary public void setBaseSalary( double salary ) { if ( salary >= 0.0 ) baseSalary = salary; else throw new IllegalArgumentException( "Base salary must be >= 0.0" ); } // end method setBaseSalary // return base salary public double getBaseSalary() { return baseSalary; } // end method getBaseSalary
Fig. 9.9 |
BasePlusCommissionEmployee
CommissionEmployee.
(Part 1 of 2.)
inherits protected instance variables from
244
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
Chapter 9 Object-Oriented Programming: Inheritance
// calculate earnings @Override // indicates that this method overrides a superclass method public double earnings() { return baseSalary + ( commissionRate * grossSales ); } // end method earnings // return String representation of BasePlusCommissionEmployee @Override // indicates that this method overrides a superclass method public String toString() { return String.format( "%s: %s %s\n%s: %s\n%s: %.2f\n%s: %.2f\n%s: %.2f", "base-salaried commission employee", firstName, lastName, "social security number", socialSecurityNumber, "gross sales", grossSales, "commission rate", commissionRate, "base salary", baseSalary ); } // end method toString } // end class BasePlusCommissionEmployee
Fig. 9.9 |
BasePlusCommissionEmployee
CommissionEmployee.
inherits protected instance variables from
(Part 2 of 2.)
When you create a BasePlusCommissionEmployee object, it contains all instance variables declared in the class hierarchy to that point—i.e., those from classes Object, CommissionEmployee and BasePlusCommissionEmployee. Class BasePlusCommissionEmployee does not inherit class CommissionEmployee’s constructor. However, class BasePlusCommissionEmployee’s six-argument constructor (lines 10–15) calls class CommissionEmployee’s five-argument constructor explicitly to initialize the instance variables that BasePlusCommissionEmployee inherited from class CommissionEmployee. Similarly, class CommissionEmployee’s constructor implicitly calls class Object’s constructor. BasePlusCommissionEmployee’s constructor must do this explicitly because CommissionEmployee does not provide a no-argument constructor that could be invoked implicitly.
Testing Class BasePlusCommissionEmployee The BasePlusCommissionEmployeeTest class for this example is identical to that of Fig. 9.7 and produces the same output, so we do not show it here. Although the version of class BasePlusCommissionEmployee in Fig. 9.6 does not use inheritance and the version in Fig. 9.9 does, both classes provide the same functionality. The source code in Fig. 9.9 (47 lines) is considerably shorter than that in Fig. 9.6 (116 lines), because most of BasePlusCommissionEmployee’s functionality is now inherited from CommissionEmployee— there’s now only one copy of the CommissionEmployee functionality. This makes the code easier to maintain, modify and debug, because the code related to a commission employee exists only in class CommissionEmployee. Notes on Using protected Instance Variables In this example, we declared superclass instance variables as protected so that subclasses could access them. Inheriting protected instance variables slightly increases performance, because we can directly access the variables in the subclass without incurring the overhead
9.4 Relationship between Superclasses and Subclasses
245
of a set or get method call. In most cases, however, it’s better to use private instance variables to encourage proper software engineering, and leave code optimization issues to the compiler. Your code will be easier to maintain, modify and debug. Using protected instance variables creates several potential problems. First, the subclass object can set an inherited variable’s value directly without using a set method. Therefore, a subclass object can assign an invalid value to the variable, possibl