Sei sulla pagina 1di 332

INSTRUCTOR

GUIDE

Java 2 Programming for Developers

Java 2 Programming for Developers

JAVA 2 PROGRAMMING FOR DEVELOPERS


Course Number: NH77954 (IGEE) Course Edition: 1.0 For software version: 1

ACKNOWLEDGEMENTS
Project Team
Curriculum Developer and Technical Writer: John W.E. Hall Copy and Technical Editor: J-P Altieri Reviewing Editor: Cory Brown Print Designer: Isolina Salgado

Project Support
Content Manager: Mark Onisk Development Assistance: Greg Moens

NOTICES
DISCLAIMER: While Element K Press LLC takes care to ensure the accuracy and quality of these materials, we cannot guarantee their accuracy, and all materials are provided without any warranty whatsoever, including, but not limited to, the implied warranties of merchantability or tness for a particular purpose. The name used in the data les for this course is that of a ctitious company. Any resemblance to current or future companies is purely coincidental. We do not believe we have used anyones name in creating this course, but if we have, please notify us and we will change the name in the next revision of the course. Element K is an independent provider of integrated training solutions for individuals, businesses, educational institutions, and government agencies. Use of screenshots, photographs of another entitys products, or another entitys product name or service in this book is for editorial purposes only. No such use should be construed to imply sponsorship or endorsement of the book by, nor any afliation of such entity with Element K. TRADEMARK NOTICES: Element K and the Element K logo are trademarks of Element K LLC. Java is a registered trademark of Sun Microsystems, Inc. in the U.S. and other countries; the Java products and services discussed or described may be trademarks of Sun Microsystems, Inc. All other product names and services used throughout this book may be common law or registered trademarks of their respective proprietors. Copyright 2002 Element K Content LLC. All rights reserved. Screenshots used for illustrative purposes are the property of the software proprietor. This publication, or any part thereof, may not be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording, storage in an information retrieval system, or otherwise, without express written permission of Element K, 500 Canal View Boulevard, Rochester, NY 14623, (585) 240-7500, (800) 434-3466. Element K Press LLCs World Wide Web site is located at www.elementkcourseware.com. This book conveys no rights in the software or other products about which it was written; all use or licensing of such software or other products is the responsibility of the user according to terms and conditions of the owner. Do not make illegal copies of books or software. If you believe that this book, related materials, or any other Element K materials are being reproduced or transmitted without permission, please call 1-800-478-7788.

ii

Java 2 Programming for Developers

JAVA 2 PROGRAMMING FOR DEVELOPERS


About This Course . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi Lesson 1: Javas Language Fundamentals. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Lesson 2: Flow Control and Data Structures. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 Lesson 3: Object-oriented Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 Lesson 4: Exception Handling and Garbage Collection. . . . . . . . . . . . . . . . . . . . . . 141 Lesson 5: The java.lang Package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 Lesson 6: Java GUIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179 Lesson 7: The java.io Package. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209 Lesson 8: Multi-threaded Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 Lesson 9: JDBC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277 Glossary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311

CONTENT OVERVIEW

Contents

iii

CONTENTS

JAVA 2 PROGRAMMING FOR DEVELOPERS

CONTENTS
About This Course . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi Course Setup Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xii How To Use This Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii

LESSON 1: JAVAS LANGUAGE FUNDAMENTALS


Topic 1A
Introduction to Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Task 1A-1 Reviewing the Benefits of Java . . . . . . . . . . . . . . . . . . . . . 4 Creating Java Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Task 1A-2 Creating a Hello World Application. . . . . . . . . . . . . . . . . . 7 Java Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Task 1A-3 Exploring the Java API Specification. . . . . . . . . . . . . . . . . . 10 12 12 14 14 16 17 19 22 23 23 24 28 30 30 31 33 34 36

Topic 1B

Datatypes, Identifiers, and Keywords. . . . . . . . . . . . . . . . . . . Primitive Datatypes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Task 1B-1 Primitive Datatypes and Strings . . . . . . . . . . . . . . . . . . . . . Identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Task 1B-2 Declaring Variables and Assigning Values . . . . . . . . . . . . . . . Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Logical Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Task 1C-1 Working with Java Operators . . . . . . . . . . . . . . . . . . . . . . . The instanceof Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Task 1C-2 Using the instanceof Operator . . . . . . . . . . . . . . . . . . . . . . Type Conversion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Task 1C-3 Typecasting and Type Conversion . . . . . . . . . . . . . . . . . . . .

Topic 1C

Topic 1D

Comparing Objects for Equality. . . . . . . . . . . . . . . . . . . . . . . . Object References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The == Operator. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The equals() Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Task 1D-1 Comparing Objects for Equality . . . . . . . . . . . . . . . . . . . . . Lesson Review 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

iv

Java 2 Programming for Developers

LESSON 2: FLOW CONTROL AND DATA STRUCTURES


Topic 2A
Flow Control Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The if Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Task 2A-1 Using the if Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . The if-else Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Task 2A-2 Using the if-else Statement . . . . . . . . . . . . . . . . . . . . . . . Nested ifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Task 2A-3 Using the if-else-if Statement . . . . . . . . . . . . . . . . . . . . . The switch Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Task 2A-4 Using the switch Statement . . . . . . . . . . . . . . . . . . . . . . . The while and do-while Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Task 2A-5 Using the while and do-while Loops . . . . . . . . . . . . . . . . . Check Your Skills 2-1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The for Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Task 2A-6 Using the for Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Check Your Skills 2-2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Abnormal Exiting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Task 2A-7 Abnormal Exiting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Check Your Skills 2-3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Apply Your Knowledge 2-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 38 39 40 41 42 44 47 50 53 55 60 60 63 64 64 67 70 71 72 73 76 77 79 81 83 83 86 89 90 91

CONTENTS

Topic 2B

Data Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Task 2B-1 Creating an Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Manipulating Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Task 2B-2 Manipulating an Array . . . . . . . . . . . . . . . . . . . . . . . . . . . Collections. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Task 2B-3 Choosing a Collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using Collections. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Task 2B-4 Working with Collections . . . . . . . . . . . . . . . . . . . . . . . . . . The Collections Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Task 2B-5 Manipulating a List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lesson Review 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

LESSON 3: OBJECT-ORIENTED PROGRAMMING


Topic 3A
Java Methods. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 Task 3A-1 Working with Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 Apply Your Knowledge 3-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100

Topic 3B

Classes, Packages, and Interfaces . . . . . . . . . . . . . . . . . . . . . .100 Task 3B-1 Understanding Classes and Instances . . . . . . . . . . . . . . . . . 104 Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
Contents v

CONTENTS

Task 3B-2 Working with Java Packages . . . . . . . . . . . . . . . . . . . . . . . 108 Access Modifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 Task 3B-3 Access Modifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 Task 3B-4 Using Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 Polymorphism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118

Topic 3C

Overloading and Overriding . . . . . . . . . . . . . . . . . . . . . . . . . . .118 Task 3C-1 Declaring and Using Overloaded Methods . . . . . . . . . . . . . . . 119 Overriding Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 Task 3C-2 Overriding a Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .124 Task 3D-1 Specify a Constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 Default Constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 Task 3D-2 Using the Default Constructor . . . . . . . . . . . . . . . . . . . . . . 128 Overloading Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 Task 3D-3 Using Overloaded Constructors . . . . . . . . . . . . . . . . . . . . . . 130 Inner Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .132 Task 3E-1 Using Inner Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 Lesson Review 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138

Topic 3D

Topic 3E

LESSON 4: EXCEPTION HANDLING AND GARBAGE COLLECTION


Topic 4A
Overview of Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .142 What are Exceptions? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 Throwing Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 Catching Exceptions with Exception Handlers . . . . . . . . . . . . . . . . . . . 143 Exception Handling: A Requirement in Java. . . . . . . . . . . . . . . . . . . . . 145 Task 4A-1 Following the Control Flow of an Exception Handler . . . . . . . 147 Runtime Exceptions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 Uncaught Exceptions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 Task 4A-2 Runtime Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 Writing Exception Handlers . . . . . . . . . . . . . . . . . . . . . . . . . . .150 Identifying Exception-throwing Code . . . . . . . . . . . . . . . . . . . . . . . . . . 150 Placing Code in a try Block. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 Writing the catch Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 Including a finally Block. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 Task 4B-1 Writing an Exception Handler . . . . . . . . . . . . . . . . . . . . . . 153 Garbage Collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .156 Task 4C-1 Performing Garbage Collection . . . . . . . . . . . . . . . . . . . . . . 157 Lesson Review 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159

Topic 4B

Topic 4C

vi

Java 2 Programming for Developers

LESSON 5: THE JAVA.LANG PACKAGE


Topic 5A
Classes and Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .162 Task 5A-1 Classes and Interfaces of the java.lang Package . . . . . . . . . . 163 Wrapper Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 The String Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .164 Task 5B-1 String Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165

CONTENTS

Topic 5B Topic 5C

The Math Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .169 Task 5C-1 Using the Math Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170 Apply Your Knowledge 5-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176 Lesson Review 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177

LESSON 6: JAVA GUIS


Topic 6A
Containers and Components . . . . . . . . . . . . . . . . . . . . . . . . . .180 Task 6A-1 Creating a GUI Application . . . . . . . . . . . . . . . . . . . . . . . . 183 Applets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185

Topic 6B

Layout Managers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .186 Task 6B-1 Layout Manager Review . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 Assigning a Layout Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 Task 6B-2 Using the Border Layout Manager . . . . . . . . . . . . . . . . . . . . 188 GridBagLayout Layout Manager. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189 Task 6B-3 Using a GridBagLayout . . . . . . . . . . . . . . . . . . . . . . . . . . . 191 Menus. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .195 Task 6C-1 Creating a Menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196

Topic 6C Topic 6D Topic 6E

Handling Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .198 Task 6D-1 Responding to an Action Event . . . . . . . . . . . . . . . . . . . . . 201 Apply Your Knowledge 6-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203

Java Graphics. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .204 Task 6E-1 Painting Shapes to a Screen . . . . . . . . . . . . . . . . . . . . . . . 205 Apply Your Knowledge 6-2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206 Lesson Review 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208

LESSON 7: THE JAVA.IO PACKAGE


Topic 7A
Overview of the java.io Package . . . . . . . . . . . . . . . . . . . . . . .210 The File Class. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210 Task 7A-1 Working with the File Class . . . . . . . . . . . . . . . . . . . . . . . . 212 Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
Contents vii

CONTENTS

Task 7A-2 Identifying Input and Output Streams . . . . . . . . . . . . . . . . . 217 Character Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 Task 7A-3 Identifying Readers and Writers . . . . . . . . . . . . . . . . . . . . . 221 Random Access Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222 Console Input and Output. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222 Task 7A-4 Reading Input from the Console . . . . . . . . . . . . . . . . . . . . . 223

Topic 7B Topic 7C

Reading Files. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .224 Steps to Reading a File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225 Task 7B-1 Reading Data from a File . . . . . . . . . . . . . . . . . . . . . . . . . 228 Writing Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .233 Steps to Writing a File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233 Task 7C-1 Writing Data to a File. . . . . . . . . . . . . . . . . . . . . . . . . . . . 236 Apply Your Knowledge 7-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239 Apply Your Knowledge 7-2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239 Reading and Writing Objects . . . . . . . . . . . . . . . . . . . . . . . . . .239 Object Serialization. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 Performing Object Serialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 Writing an Object to a File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 Reading an Object from a File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244 Task 7D-1 Serializing an Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244 Check Your Skills 7-1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246 Lesson Review 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247

Topic 7D

LESSON 8: MULTI-THREADED PROGRAMMING


Topic 8A
Overview of Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .250 Task 8A-1 Observing a Computers Processes . . . . . . . . . . . . . . . . . . . . 251 Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253 Task 8A-2 Observing a Multi-threaded Program . . . . . . . . . . . . . . . . . . 256

Topic 8B

Using Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .257 The Thread Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258 Creating a New Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258 Setting a Threads Runtime Properties . . . . . . . . . . . . . . . . . . . . . . . . . 259 Task 8B-1 Deciding Between Daemon and Non-daemon Threads . . . . . . . 261 Starting a Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261 Managing a Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262 Task 8B-2 Creating a Multi-threaded Program . . . . . . . . . . . . . . . . . . . 264

Topic 8C

Synchronization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .267 Monitors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267 Task 8C-1 Synchronizing a Light Show. . . . . . . . . . . . . . . . . . . . . . . . 270 Wait and Notify . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271 Task 8C-2 The Producer/Consumer Problem . . . . . . . . . . . . . . . . . . . . . 272

viii

Java 2 Programming for Developers

Lesson Review 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275

CONTENTS

LESSON 9: JDBC
Topic 9A
Overview of SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .278 The Bookstore Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278 Structured Query Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279 Obtaining Information from a Database. . . . . . . . . . . . . . . . . . . . . . . . 280 Task 9A-1 Working with the SELECT Statement . . . . . . . . . . . . . . . . . . 284 Manipulating Information in a Database . . . . . . . . . . . . . . . . . . . . . . . 285 Task 9A-2 Modifying Data in a Database . . . . . . . . . . . . . . . . . . . . . . 286 Using JDBC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .287 JDBC Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287 Task 9B-1 Configuring ODBC for Use with JDBC . . . . . . . . . . . . . . . . . . 288 Loading JDBC Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291 Connecting to a Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291 The Connection Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292 Issuing SQL Statements to the Database . . . . . . . . . . . . . . . . . . . . . . . 293 Processing a ResultSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295 Task 9B-2 Querying a Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298 Apply Your Knowledge 9-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302 Lesson Review 9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302

Topic 9B

Glossary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .305 Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .311

Contents

ix

Java 2 Programming for Developers

INTRODUCTION
Welcome to the New Horizons training team. Our goal is to provide you with the best computer training available and we know exactly what that takes. Our corporate heritage is based in training. In fact, we use our Student Manuals every day, in classes just like yours, so you can be condent that the material has been tested and proven to be effective. If you have any suggestions on how we can improve our products or services, please contact us.

ABOUT THIS COURSE

ABOUT THIS COURSE


This course provides developers who are procient in languages such as C, C++, C#, or Visual Basic with the foundations of Java 2 Standard Edition (J2SE) technology. Through the use of hands-on exercises, developers will explore the Java language fundamentals as well as concepts such as object-oriented design and graphical user interface design.

Course Prerequisites
To ensure your success, we recommend you rst take the following New Horizons courses or have equivalent knowledge: Introduction to Programming (2nd Edition) C Programming (2nd Edition) C++ - Introduction Visual C++ 6.0 - Desktop Application Development

Course Objectives
When youre done working your way through this book, youll be able to: Use Javas language fundamentals to create simple Java applications. Create programs that use Javas ow control structures and data structures. Discuss Javas object-oriented features, including classes, packages, interfaces, and inheritance. Describe Javas exception handling and garbage collection processes. Use the java.lang packages classes and interfaces to develop programs that manipulate strings and perform math calculations. Use the java.awt packages classes and interfaces to develop programs with graphical user interfaces (GUIs). Use the java.io packages classes and interfaces to develop programs that read and write les and objects. Create programs that use Javas multi-threading capabilities.
About This Course xi

Develop programs that use JDBC to interact with databases.

COURSE SETUP INFORMATION


Hardware and Software Requirements
To run this course, you will need: Networked Microsoft Windows NT 4.0 Workstation (Service Pack 6). Java 2 SDK, Standard Edition, v1.3 (or later). Microsoft Data Access Components (MDAC), v2.1 (or later).

Class Requirements
In order for the class to run properly, perform the procedures described below. 1. 2. 3. Install Windows NT 4.0 Workstation (along with Service Pack 6), Windows 98, or Windows 2000. Download and install the Java 2 SDK. The Java 2 SDK can be downloaded from http://java.sun.com/j2se. Add the bin directory of the SDK installation to the system path. For specic instructions on how to do this for a particular operating system, consult the SDK installation instructions. Download and install the Microsoft Data Access Components (MDAC). The MDAC can be downloaded from http://www.microsoft.com/data/ download.htm. If you are using Microsoft Office 98 or a newer release, you should already have MDAC installed. Verify that the Microsoft Access Driver is available by going into Control Panel and opening the ODBC Data Source Administrator. Click on the Drivers tab and verify that the Microsoft Access Driver is in the list. Install the course data les from the CD-ROM that comes with this book. To do so, open the contents of the CD-ROM and locate the 077_954 folder. Within this folder, you will nd another folder named Data. Open this folder and double-click on the 077954dd.exe le to start the installation process. Accept the default installation destination for the les. A folder named 077954, containing all the data les you will need to complete this course, will be created on your C drive.

4.

5.

6.

xii

Java 2 Programming for Developers

HOW TO USE THIS BOOK


You can use this book as a learning guide, a review tool, and a reference.

As a Learning Guide
Each lesson covers one broad topic or set of related topics. Lessons are arranged in order of increasing prociency with Java 2; skills you acquire in one lesson are used and developed in subsequent lessons. For this reason, you should work through the lessons in sequence. We organized each lesson into explanatory topics and step-by-step activities. Topics provide the theory you need to master Java 2; activities allow you to apply this theory to practical hands-on examples. You get to try out each new skill on a specially prepared sample le. This saves you typing time and allows you to concentrate on the technique at hand. Through the use of sample les, hands-on activities, illustrations that give you feedback at crucial steps, and supporting background information, this book provides you with the foundation and structure to learn Java 2 quickly and easily.

As a Review Tool
Any method of instruction is only as effective as the time and effort you are willing to invest in it. For this reason, we encourage you to spend some time reviewing the books more challenging topics and activities.

As a Reference
You can use the Concepts sections in this book as a rst source for denitions of terms, background information on given topics, and summaries of procedures.

About This Course

xiii

xiv

Java 2 Programming for Developers

Javas Language Fundamentals


Overview
To become uent in any programming language, you must rst master the fundamental syntax and basic expressions of the language. In this lesson, youll explore the basic units of the Java programming language, as well as the structure of Java programs and statements.

LESSON

1
Data Files Variables.java OperatorTest.java Lesson Time 2 hours

Objectives
To master Javas language fundamentals, you will: 1A Write, compile, and run a simple command-line Java application. Although the Java programming language was originally developed as a solution for smart, limited consumer devices, todays developers use Java in a wide range of applications. Java developers can write Java programs in a text editor, compile them with the Java compiler, and distribute them on a range of platforms. 1B Identify Javas datatypes, identiers, and keywords. Java includes eight primitive datatypes: byte, short, int, long, oat, double, char, and boolean. In addition, Java has 47 reserved words, or keywords. 1C Describe, identify, and use Javas arithmetic, comparative, and logical operators to perform operations. Operators are used to perform and evaluate expressions. Java includes a range of mathematical, comparative, and logical operators. 1D Identify different techniques that compare objects for equality. Comparing objects for equality, while it sounds easy enough, can sometimes be a difficult concept to understand. This is due to differences between what programmers consider to be equal and what Java considers to be equal. You will look at two different methods for comparing objects for equality.

Lesson 1: Javas Language Fundamentals

Topic 1A
Introduction to Java
Sun Microsystems launched Project Green during the late 80s to develop a programming language that could control, connect, and interact with a smart generation of consumer devices. The design goals for the language required that it be small, secure, and portable (it must run on Windows, Unix, Macintosh, and other operating systems without modication). James Gosling, the principal architect of this new language, called it Oak, after an oak tree outside his window. It was later discovered that another programming language was already called Oak, so it was renamed Java. Unfortunately for Sun Microsystems, the consumer marketplace was not ready for the next generation of smart devices. However, at about the same time, the Internet began to experience phenomenal growth and became ready for a platform-independent programming language. The Internet had become popular because of the simplicity of HyperText Markup Language (HTML), the markup language of the Internetyet the power of the Internet was at the same time being limited by the simplicity of this markup language. The limitations of HTML set the stage for the entry of Java. While other mature programming languages were in existence, Java fullled the primary requirements for a language on the Internet: it was small, secure, sophisticated, and portable. In 1995, Sun Microsystems introduced Java, proclaiming it as the universal programming language designed for the Internet. The intent was to allow developers the freedom to write software for their own platforms, and then to run their software, as designed, on any other platform without needing any modication whatsoever. Java was thus proudly proclaimed to be the write once, run anywhere language. The rest is history. The symbiotic relationship between Java and the Internet has resulted in explosive, historic growth for both Java and the Internet. Sun Microsystems has continued to upgrade Java to meet the growing needs of the Internet and to extend Javas potential uses to the computer desktop, consumer devices, and other markets.

You can get information about these releases at http://java.sun.com/ j2se/.

The Benefits of Java


When you develop a new language, your rst task is to determine and establish a consensus on two critical matters: one, the objectives of the language (what it is to accomplish); and two, the design criteria that the language must meet. The initial objective of the Java language was that it should have the ability to connect and control consumer devices such as toasters and water heaters. The Java development team established the design criteria for this initial Java language before embarking on its development. Once the language was developed, these design criteria would serve as built-in features of the new language, features which would translate into tangible benets for the Java developer and user communities. Java boasts the following characteristics and benets, as also shown in Figure 1-1: Object-oriented technologypromotes reusability.
2 Java 2 Programming for Developers

Component-based technologypromotes and facilitates software assembly. Portabilitypromotes platform independence. Smaller sizepromotes economy, efficiency, and the like.

Securitypromotes access control and management. Concurrenceallows for more than one activity at a time.

Figure 1-1: Characteristics and benets of Java. Object-orientation: Java is an object-oriented (OO) language, complete with all the advantages of an OO language, including the use of encapsulated, reusable components, and its relatively small size. Since software trends everywhere in todays marketplace favor object-oriented technology, adapting to Java has proven to be a smooth transition for everyone. Furthermore, since C++ is a leading object-oriented programming language, and since Java is similar to C++, it is easy for todays OO developers to transfer their skills and become procient in the world of Java. Object-orientation offers many benets, including ease of use for existing components through the abstraction of implementation details, reusability of design objects, and the ability to design and implement new classes, owing to a key feature known as inheritance, a built-in security factor, and an important feature known as modularity. Component-based: Java has a number of standard component APIs that allow programmers to develop software by putting already built components together. Since the components are encapsulated and use message-based interactions, it is easy to assemble existing components in the Java Class Library and to program the message-based interactions among the components, so as to accomplish the desired functionality. Portable: Java was conceived to be a write once, run anywhere language. As such, it is independent of both the operating system and the hardware platform. Java can run without modication on Windows, Macintosh, and Unix platforms. For example, you can develop your source code on a Windows 98 platform, compile the source le on a Macintosh, and deploy the class le on a Unix-based Web server. Small Size: Since Java is object-oriented and uses components; the resulting code is small in size. Smaller applets download faster on the Internet and place a lower load on the memory of the client computers it runs on. Java is safe. Traditionally, every new language goes through a long maturing cycle. By using many of the concepts used in C++, an already a robust, mature, and popular OO language, Java took a great leap forward in producing reliable software. Additionally, since Javas developers eliminated those features in C++ that are complex or crashprone, Java is truly a safe language.
Lesson 1: Javas Language Fundamentals 3
Characteristics and Benets of Java

Java Virtual Machine (JVM): A software or hardware environment that enables Java applications to run on a client computer.

Secure: Java must run within the context of the Java Virtual Machine (JVM) and not directly within the host operating system (the JVM enables Javas platformindependence). This additional layer incorporates a number of security safeguards so that the Java application or applet cannot sneak into the host operating system. Concurrent: By using threads that run concurrently and by specifying the synchronization between threads, Java enables the development of multi-threaded software. Multi-threaded software can allow the browser to use one thread to download some component, another thread to perform computations, and a third thread to perform graphical displays.

thread: The smallest pathway of an executable code. A Java application can process multiple threads at once.

TASK 1A-1:
Reviewing the Benefits of Java
1. What advantages does a component-based system offer? Answers will vary, but may include: Components improve productivity; instead of writing the software line by line, you assemble software components. Components help standardize programming concepts. Because you use a component over and over again, it will always perform the expected task, thereby providing maximum consistency. Components improve accountability for information systems assets. If every developer were to implement their own version of a certain task, you would have multiple pieces of software to perform the same task. A corporation would lose control over what software they have, and they would lose the ability to recommend a piece of software when given a task objective.

2.

What is the signicance of Javas write once, run anywhere nature? Give two examples of the usefulness of this feature. Answers will vary, but may include: As a developer, you are not required to learn a new operating system (OS) in order to develop Java programs. You can develop Java programs on the operating system that you are most comfortable with. Lets assume that your software is to run on a Sun Solaris environment and you are only familiar with the Windows environment. You will not be compelled to learn Unix shell commands in order to develop Java programs; you can develop your programs in Windows, and then deploy them in a Unix environment. You can be productive more quickly because you can develop your Java programs on the OS of your choice. As a manager, you do not have to send your project team to an intensive course in another operating system. You save a signicant amount of money and time. The quality of your Java program is likely to be better. If you were working with an unfamiliar OS, you would be distracted quite often by having to gure out secondary OS issues. By working in the OS that you are already familiar with, you can focus your attention entirely on the quality of the Java program.

Java 2 Programming for Developers

3.

When programmers say that one of the advantages of Java is concurrence, what do they mean? Concurrence means that Java can be used to develop multi-threaded software. This is advantageous because a Java application can perform two or more tasks concurrently and can, if needed, synchronize operations between threads.

4.

Identify the feature which is NOT one of the benets of Java. a. Multi-threading b. Security c. Platform-specic optimization d. Component-based e. Small size

5.

How does Java achieve its high level of security? Java is more secure than most languages because Java applications are processed by the Java Virtual Machine (JVM) rather than on the host system.

Creating Java Applications


Classes are the basic building blocks of Java applications. In object-oriented programing, a class is a template that contains the denitions of the variables and methods of an object. A Java application may be composed of one or many classes. Java classes are created from textual source code les that have the .java extension.

Code Comments
Comments are portions of a source code le that are ignored by the compiler. Typically, programmers use comments to make their code more legible and comprehensible. The Java Language Specication denes two kinds of code comments: traditional, multi-line comments and single line comments. You may be familiar with Javas traditional comment blocks from C or C++. The following code samples are two examples of Java comments: /* a traditional multi-line comment block */ // a single line comment has no terminator Java also denes a third type of comment, which is used by the JavaDoc application to create automatically generated code documentation. The following is an example of a documentation comment: /** a documentation comment */

class: An object-oriented programming template that contains the denitions of the variables and methods of an object.

comment: A portion of a source code le that is ignored by the compiler.

Java Development Tools


The Java 2 Software Developer Kit (SDK) includes the following command-line tools to help you develop Java applications.

Lesson 1: Javas Language Fundamentals

Tool
javac.exe

Description
The Java compiler. Checks source code and converts it into platform-independent bytecode with the .class extension. Launches Java applications by starting the Java runtime environment (JRE), loading a class, and calling the classs main method. Generates API documentation from Java source code les. Runs and debugs applets outside of a Web browser. Generates disassembled Java bytecodes.

java.exe

javadoc.exe appletviewer.exe javap.exe

Compiling and Running Java Applications


To compile a Java source code le you invoke javac at the Command Prompt and provide the name of the source le or les as a parameter. For example, to compile a source code le called C:\MyJava.java you would type:
C:\>javac MyJava.java

Once the javac compiler has compiled a source le into Java bytecodes, a client machines JVMwhich provides the bridge between the platform-independent bytecodes and the runtime operating systemcan execute the class le. For example, to execute a class le called MyJava.class, at the command line, you would type:
C:\>java MyJava

IDE: (Integrated Development Environment) A GUI programming environment that includes tools to facilitate the application development cycle.

The javac and java command-line applications are included in the Java Software Developers Kit (SDK) which can be freely downloaded from http:// java.sun.com. There are also a range of IDEs that provide GUI tools for developing, compiling, debugging, and running Java applications. When you run a Java program, the JVM begins execution in the programs main method. As in other programming languages, every application (although not every class) must include a main method. In Java, the main methods syntax must be:
public static void main (String [] args) { }

The keyword public is an access modier that indicates that any class can access the method. The static keyword indicates that this method applies to the class itself and not to instances of the class. The void keyword indicates that the method does not return a value. String [] args is an array of strings that can be passed to the method as it launches.

Java 2 Programming for Developers

TASK 1A-2:
Creating a Hello World Application
Objective: To create a simple Java application, composed of two class les, that displays a Hello World message. 1. 2. Open your text editor. To create a class called HelloWorld whose main method instantiates an instance of a class called Message and calls that classs printGreeting() method, type the following code:
// A "Hello World!" application public class HelloWorld { // The main method creates a new instance of a class // and calls one of its methods public static void main(String[] args){ Message myMessage = new Message(); myMessage.printGreeting(); } }
The code comments shown here are included for your benet. To save time, you may omit the comments in your application.

In the main method, the keywords public and static are modiers to the method declaration. The void keyword indicates that the method does not return a value. String [] args is an array of strings that may be passed to the method as it launches. 3. 4. Save the le as C:\077954\HelloWorld.java. Java source les must have the same name as the class that they contain. In your text editor, open a new, blank le. To create a second class called Message that contains a method called printGreeting() that prints Hello World! to the screen, type the following code:
public class Message { // A method called printGreeting() public void printGreeting() { // Print the greeting to the screen System.out.println("Hello World!"); } }
Make sure that your les are saved with the .java extension.

Although you could create this application in a single source le, creating two separate source les will help you become used to working in objectoriented programming languages. 5. Save the le as Message.java. Open the Command Prompt. Navigate to the C:\077954 directory.

Lesson 1: Javas Language Fundamentals

6.

At the command line, type javac and press [Enter]. A list of the Java compiler command-line options is displayed.

Observe the compiler syntax javac <Options> <Source Files>. You can use theg and the verbose options to help debug your programs or thed option to specify the location of the generated class les. 7. To compile your source code, type javac HelloWorld.java and press [Enter].

The javac Java compiler uses its default conguration to identify and compile the classes needed to run the HelloWorld application. 8. Open Windows Explorer and navigate to the C:\077954 directory. Notice that the compiler created two new les with the .class extension. Switch back to the Command Prompt.

Java 2 Programming for Developers

9.

To run your application, type java HelloWorld and press [Enter]. The HelloWorld class loads and calls the printGreeting() method of the Message class, which displaysHello World! to the screen.

10. Although its not a required step in compiling and running Java programs, you can use the javap tool to view a class les bytecodes. To view the bytecodes generated by the compiler for the Message class, type javap c Message and press [Enter]. The javap tool disassembles the class le and displays the platform-independent bytecodes which are executed by the JVM.

Java Resources
The single most important Java resource for new developers is the J2SE API Specication. The J2SE API Specication contains descriptions of all of the J2SE packages, classes, method, interfaces, and elds. You can nd the J2SE API Specication documentation at http://java.sun.com/j2se/1.4/docs/API. When you install the J2SE SDK, all of the classes and functionalities of the J2SE API become available to your Java applications. You will learn about many of the J2SE API packages throughout this course.

Lesson 1: Javas Language Fundamentals

Additionally, new developers might benet from perusing the Java Language Specication document. This technical document denes the structure and syntax of the Java language.

TASK 1A-3:
Exploring the Java API Specification
Objective: To gain familiarity with the Java API documentation. 1. Launch your browser and navigate to http://java.sun.com/j2se/1.4/docs/ api. The root page of the Java 2 Platform, Standard Edition API Specication is displayed. This specication denes all of the classes and interfaces included in J2SE. Observe the upper-left corner of the screen. The frame contains a list of the J2SE API packages, which each contain related groups of Java classes. Click on the java.applet package link. The interfaces and single class that are included in the java.applet package are displayed in the lower-left frame. In a later lesson, youll learn how to import packages into your source code les.

2.

10

Java 2 Programming for Developers

3.

In the lower-left frame, click on the Applet class. The Applets class specication, including its position in the class hierarchy, is displayed in your browsers main frame.

4. 5. 6.

Scroll down to the public class Applet denition. This section of the specication provides a brief description of the selected class. Scroll down to the Methods Summary section. All of the methods that can be applied to applets are listed here. Click on the destroy method. The syntax and denition of the method are displayed.

The J2SE API Specication provides descriptions for all of Javas classes and methods. As you become more familiar with the basics of Java programming, youll want to spend more time exploring the API specs. 7. Close your browser.

Lesson 1: Javas Language Fundamentals

11

Topic 1B
Datatypes, Identifiers, and Keywords
Java provides eight fundamental datatypes, known as primitive datatypes. There are four integer datatypes, two oating point datatypes, one character datatype, and one boolean datatype.
primitive datatypes: The core built-in datatypes that are not derived from any other class or type.

Primitive Datatypes
The size, range, and default values for each of the Java primitive datatypes is represented in the following table:

Primitive Datatypes

Datatype
byte short int long oat double char boolean

Size (Bits)
8 16 32 64 32 64 16 1

Value
Signed integer Signed integer Signed integer Signed integer Signed oating point Signed oating point A single Unicode character True or false

Range
-128 to +127 -32,768 to +32,767 -2,147,483,648 to +2,147,483,647 -(2^63) to +(2^63 - 1) 1.4E45 to 3.4E38 4.9E234 to 1.797E308 0 to 65,535 true or false

Default Value
0 0 0 0L 0.0F 0.0D \u0000 (null) false

Integer Datatypes
Four of Javas primitive datatypes are integer datatypes: byte, short, int, and long, of sizes 8, 16, 32, and 64 bits, respectively. All four integer types are signed integers, which means that half the range handles negative integer values and the remaining half handles positive integer values. Integral datatypes can use three forms of integer notation: decimal, octal, or hexadecimal. You designate decimal numbers just as you do in normal contexts. The numbers 422, 5, 73, and 12 are all decimal number literals. Octal values are specied by a leading zero and use the digits 0 through 7. Some examples of octal values are 0472, 06, and 0777. Hexadecimal numbers start with a zero and the letter x (either upper- or lowercase) followed by the digits 015 where 1015 are represented by the characters a through f (either upper- or lowercase). Some examples of hexadecimal notation are 0xB4D, 0XFC, 0x25, and 0XFFFFFF. These three different notation types are summarized in the table below:
As in other programming languages, octal and hexadecimal systems are available in Java.

integer: A non-fractional number that can be positive, negative, or zero.

Type
Decimal Octal Hexadecimal

Base
10 8 16

Prex
None 0 (a leading zero) 0x (leading zero then a lowercase or uppercase X)

Example
422, 5, 73 0472, 06, 0777 0xB4D, 0XFC, 0xFFFFFF

12

Java 2 Programming for Developers

Floating Point Datatypes


Floating point datatypes are used to store numbers that have fractional parts. Floating point numbers are also called real numbers. Most scientic, mathematical, and nancial computations result in values that contain fractional values. Java has two types: oat and double. Float is a single-precision value, while double is a double-precision value. The numbers 2.456, 238.14, and 93.0 are examples of oating point literals. You may also use the scientic notation 73.457E04 or 934234E-03 to specify oating point literals. To specify a oating point letter as a oat, append a lowercase or uppercase f after the literal. For example, Java would treat 49.325f as a oat and not a double.

oating point: A number that includes fractional parts. Also known as a real number.

Character Type
Java has one character type called char. Java uses 16 bits for this datatype, since it stores Unicode rather than ASCII characters, which would only require 8 bits. Unicode, which includes characters used in many languages, is particularly important in our global marketplace and global Internet initiatives. Character literals are enclosed in single quotes and may include any Unicode character. Possible character literals are: w,h, and &. Some characters cannot be entered by pressing a key on the keyboard. You can specify these characters by using escape sequences. The following table lists some commonly used escape sequences. Escape Sequence
\n \t \f \b \r \\ \ \

A number that contains fractional value defaults to a double as opposed to a oat even when the number is small enough to be a oat. This can lead to unexpected results in computations.

Description
New line Tab Form feed Backspace Carriage return Back slash Single quote Double quote

Unicode: A character set that includes all (or nearly all) of the alphabet characters in the world.

String Class
In Java, a string is not a primitive data type; nor is it an array of chars as it is in C. String literals are created as instances of the java.lang.String class. They are enclosed in double quotes and use the Unicode character set. For example:
"ABCDEFG"

You will explore some of the nuances of strings later in this course.

When you create a String object and assign it a value, the String variable is a reference variable that refers to the String literal, which is stored in a special area of memory called the String Constant Pool. This means that you cannot change the contents of a string (in Java, strings are said to be immutable) and that when you create two separate strings with the same character sequence, they actually reference the same object in memory (the character sequence as stored in the String Constant Pool). This is true unless you use the new keyword to instruct the processor to create a unique instance of a String object in the general memory heap.

reference variable: A variable that points to an object in memory rather than a primitive.

Lesson 1: Javas Language Fundamentals

13

Boolean Datatype
A boolean is one of two values: true or false. Some languages allow the use of numeric values such as 1 for true and 0 for false. Java, however, restricts you to a true or false value. You would typically use boolean literals when representing data items that can either be true or false. For example, the boolean variable hisElevatorGoesToTheTopFloor can only be true or false. Or, you may want to track the status of a projectprojectCompleted can either be a true or a false.

TASK 1B-1:
Primitive Datatypes and Strings
Objective: To demonstrate your knowledge of Javas primitive datatypes. 1. Match each primitive datatype on the left with its description on the right. d c a e g h b f 2. int char double long boolean short byte oat a. b. c. d. e. f. g. h. double precision number 8-bit signed integer a Unicode character 32-bit signed integer 64-bit signed integer single precision real number true or false 16-bit signed integer

For each of the eight primitive datatypes, give two examples of information that you encounter in your environment. Answers will vary.

3.

What, if anything, is wrong with the following code?


boolean b; b = 1;

Unlike several common programming languages, Java does not allow you to assign the digits 1 or 0 to boolean literals. 4. True or False? The String Constant Pool is a special area of memory in which strings of characters are stored. True.

Identifiers
In Java source code les, variables, classes, and methods must be named with legal Java identiers. Identiers can legally begin with: Any Unicode letter.
14 Java 2 Programming for Developers

A dollar sign character ($). An underscore character ( _ ).

Legal identiers cannot: Contain spaces. Be any of Javas reserved keywords. Include a character that is not a part of a standard alphabet (#, [, ], *, and others). Begin with a digit.

Keywords
The Java Language Specication denes a limited number of keywords. Keywords may not be used as identiers. The following table lists all of the Java keywords.
abstract case const * double nally if int new public super throw void boolean catch continue else oat implements interface package return switch throws volatile break char default extends for import long private short synchronized transient while byte class do nal goto * instanceof native protected static this try

The const and goto keywords are not implemented in Java even though they are reserved keywords. Use of these keywords will generate a compile error.

Declaring Variables and Assigning Values


When you program in Java, you must declare all variables before you can use them. To declare a variable, rst specify the datatype and then the name of the variable using the following syntax:
datatype variableName;
Unlike some programming languages, Java is casesensitive.

The datatype can be one of the eight primitive datatypes you reviewed earlier in this lesson or it can be an object or class datatype. For example, if you wish to develop a real estate application and want to declare an integer called numberOfBedrooms, the Java instruction or statement will be:
int numberOfBedrooms;

The name of the variable is numberOfBedrooms and the datatype is int. In other words, numberOfBedrooms is a variable that can hold integer values. Java also allows you to declare a variable and assign a value in a single step. To declare a String object called message and assign it a value of Hello World, type:
String message = "Hello World";

You might have noticed that the object datatype, String, is capitalized while the primitive datatype, int, is not. This is because objectsnot primitivesare always capitalized in Java.
Lesson 1: Javas Language Fundamentals 15

The Java Language Specication also allows you to declare multiple variables and to combine variable declaration and value assignment as shown here:
//Declare multiple variables of the same type int numberOfBedrooms, numberOfBathrooms; //Declare a variable and assign an initial value int numberOfBedrooms = 4; //Declare multiple variables and assign values int x = 1, y = 2;

Obviously, as a program executes, it does not always know the value of a variable when it is declared. In Java, as in other programming languages, you use the = operator to assign a value to a variable during the execution of a program. For example:
numberOfBedrooms = 3; numberOfBathrooms = 2;

TASK 1B-2:
Declaring Variables and Assigning Values
Objective: To declare and initialize variables. 1. 2. From the C:\077954 directory, open Variables.java in your text editor. In the main method, declare two ints called x and y.
public class Variables { public static void main(String[] args){ // Declare variables and assign values int x,y;

3.

Declare and initialize a string called s that refers to the value Hello.
public class Variables { public static void main(String[] args){ // Declare variables and assign values int x,y; String s = "Hello";

4.

Declare and initialize a boolean called truth that contains the value true and a oat called z that contains the value 3.5432f.
public class Variables { public static void main(String[] args){ // Declare variables and assign values int x,y; String s = "Hello"; boolean truth = true; float z = 3.5432f;

16

Java 2 Programming for Developers

5.

Assign the values 1 and 2 to the x and y variables.


public class Variables { public static void main(String[] args){ // Declare variables and assign values int x,y; String s = "Hello"; boolean truth = true; float z = 3.5432f; x = 1; y = 2;

6.

Observe the remainder of the code.


System.out.println(x); System.out.println(y); System.out.println(s); System.out.println(truth); System.out.println(z);

These lines print the value of each variable to the console. 7. Save and close the le. In the MS-DOS window, compile and execute the source code le. The variable values are displayed.

Topic 1C
Operators
An operator is a symbol or representation that indicates a specic kind of mathematical, logical, or character-based operation (or manipulation) that will be performed on or between values or operands.
operator: A symbol or representation that indicates a specic kind of mathematical, logical, or character-based operation (or manipulation) that will be performed on or between the basic values or operands.

Lesson 1: Javas Language Fundamentals

17

Arithmetic Operators
arithmetic operator: A symbol or representation that indicates a specic kind of arithmetic operation that will be performed on or between basic arithmetic or numeric values or operands.

An arithmetic operator is a symbol that represents an arithmetic operation that will be performed on or between numeric values or operands. Java provides ve basic arithmetic operators that perform numeric operations on numeric operands. Operator
+ * / %

Description
Addition Subtraction Multiplication Division Modulus (remainder)

Example
x = x + y; x = x y; x = x * y; x = x / y; x = x % y;

In addition, Java provides seven advanced arithmetic operators. While you can accomplish everything these advanced operators do with the basic operators described earlier, these advanced operators work as shortcutswhich means you type fewer characters when you use these advanced operators. The following table shows the advanced arithmetic operators. Operator
++

Description
Postx Increment and Assignment Prex Increment and Assignment Postx Decrement and Assignment Prex Decrement and Assignment Addition Assignment Subtraction Assignment Multiplication Assignment Division Assignment Modulus Assignment

Example
y = x++; y = ++x; y = x -- ; y = -- x; x += y; x = y; x *= y; x /= y; x %= y;

Explanation
y = x; x = x + 1; x = x + 1; y = x; y = x; x = x - 1; x = x - 1; y = x; x = x + y; x = x y; x = x * y; x = x / y; x = x % y;

+= = *= /= %=

Comparative Operators
A comparative operator is a symbol or representation that indicates a comparison operation for equality or inequality that will be performed between basic numeric, character-based, or date-based values or operands. The result of a comparison operation will always be a true or a false. Operator
== != < <= > >=

comparative operator: A symbol that represents a comparison operation for equality that will be performed between basic numeric, character-based, or date-based values or operands.

Description
Equals Not equals Less than Less than or equal to Greater than Greater than or equal to

Example
x==y x != y x<y x <= y x>y x >= y

18

Java 2 Programming for Developers

Logical Operators
Java provides logical operators to perform operations on boolean values or operands. A logical operator performs logical operations between two boolean values and yields a boolean result. The following table contains a list of Javas logical operators: Operator
& && | || ^ !
logical operator: A symbol or representation that indicates a logical operation that will be performed between boolean values or operands.

Description
AND Optimized AND OR Optimized OR XOR (eXclusive OR) NOT

Example
z=x&y z = x && y z=x|y z = x || y z=x^y z = !x

Java also provides the following advanced logical and assignment operators. Operator
&= |= ^= ?:

Description
AND Assignment OR Assignment XOR Assignment If-then-else

Example
x &= y x |= y x ^= y z = x>y ? 2*x : 2*y

Explanation
x = x & y; x = x | y; x = x ^ y; if (x > y) { z = 2*x; } else { z = 2*y; }

AND
When you use either AND operator (& or &&), the resulting boolean value is true if both conditions or operands are true. The resulting value is false if one or both of the operands is false. x
false false true true

y
false true false true

x&y
false false false true

x && y
false false false true

Java provides two operators to accomplish the AND operation: & and &&. When you use the & operator, Java evaluates both operands before it returns the result. When you use the && operator, Java will not evaluate the second operator if it can determine the result based on the rst operator. For example, if x is false, the result of an AND operation is false, regardless of whether y is true or false. So there is no need for the processor to evaluate y if it can determine the result based on knowing the value of x. Using the && operator will improve your applications performance.

OR
The OR operators ( | and || ) return false if both conditions or operands are false. The OR operators return true if any one of the operands is true.

Lesson 1: Javas Language Fundamentals

19

x
false false true true

y
false true false true

x|y
false true true true

x || y
false true true true

Java gives you two operators to accomplish the OR operation: | and ||. When you use the | operator, Java evaluates both operands before it returns a result. When you use the || operator, Java does not evaluate the second operator if it can determine the result based on the rst operator. For example, if x is true, the result is true regardless of whether y is true or false. There is no need for the program to evaluate y if it can determine the result based on knowing the value of x. Using the || operator will help to optimize the performance of your Java applications.

Exclusive OR
When you use the XOR operator, the result is false only if both conditions or operands are false or if both operands are true. Another way to look at the XOR is that the result is true if the two operands are different from one another, regardless of which one of them is true and which one is false. Java gives you the ^ operator to accomplish the XOR operation. x
false false true true

y
false true false true

x^y
false true true false

NOT Operator
The NOT operator negates or reverses a boolean value. If you perform a NOT operation on a true value, you would get a false. If you perform a NOT operation on a false value, you would get a true. x
true false

!x
false true

Bitwise Operators
Java includes several bitwise operators that manipulate the bit patterns that represent integral datatypes. The following table lists Javas bitwise operators: Operator
~ &

Description
A unary NOT operator; inverts an integer types bit pattern. Bitwise AND; compares the bits of two integer types and returns a 1 in the appropriate bit location if the same bit locations of both operands contain a 1, otherwise returns a 0 in the appropriate bit location.

20

Java 2 Programming for Developers

Operator
|

Description
Bitwise OR; compares the bits of two integer types and returns a 0 in the appropriate bit location if the bit sequence of both operands contain a 0. Otherwise the bits of the result will contain 1. Bitwise Exclusive OR; returns 0 if the appropriate bit locations both contain 1s or 0s. Right and left shift operators; shifts the bits of an integer type to the right or left, inserting zeros or ones (depending on whether the number is negative or positive) in the new bit locations. Right and left unsigned shift operators; shifts the bits of an integer type to the right or left, inserting zeros in the new bit locations.

^ >>, <<

>>>, <<<

For example, ~23 would evaluate to 24. This is because 23 is represented as:
0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1
In these examples, only the last 16 bits of the 32-bit integer are shown.

The ~ operator reverses the bits:


1 1 1 1 1 1 1 1 1 1 1 0 1 0 0 0

Converting this binary sequence to a decimal value yields 24. The statement 7 & 2 evaluates to 2, as shown here:
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0

Executing the bitwise AND operation results in:


0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0

. . . which evaluates to 2.

Operator Precedence
Javas operator precedence is presented in the following table. The operations shown in the top row have the highest precedence (they are executed rst) and the operations in the lowest row have the lowest precedence (they are executed last). Operators in Order of Precedence
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. [] () ++ ! Typecasting operations (covered in the next topic) */% + < <= > >= = = != & ^ | && || ?: = += = *= /= %= &= |= ^=

Lesson 1: Javas Language Fundamentals

21

TASK 1C-1:
Working with Java Operators
Objective: To demonstrate your knowledge of Java operators. 1. If you were to execute this code, what would be the value of x?
int x; x = 5 + 6 / 2 * (21%9);

14. Working through the order of operator precedence, the modulus operation in the parentheses is performed rst, followed by the division and the multiplication. Finally, the addition operation is performed. 2. What is the difference between these two statements?
y=x++; y=++x;

In the rst example, the value of x is assigned to y and then x is incremented. In the second example, x is incremented and the resulting value is assigned to y. 3. After the execution of this code, what is the value of x?
int x,y; x = 5 + 2 * (10-8); x += -2; y = ++x;

8. After the second line of code, x is equal to 9. In the next line, it is reduced by 2. Finally, it is incremented by 1. 4. After the execution of the following code, what is the value of x? What is the value of y?
boolean w,x,y; w = true; x =! w; y = x && w;

x is equal to false. y is equal to false. 5. What is the value of 7 | 2? If you need to, draw out the bit sequence. 7 | 2 evaluates to 7. Here is the bit sequence:
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0

7 | 2:
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1

. . . or 7.

22

Java 2 Programming for Developers

The instanceof Operator


The instanceof operator provides a mechanism to test whether an object is an instance of a particular classsuch as a String. The result of the instanceof operator is a boolean value. Because Java supports object polymorphism, you may not always know what kind of object a reference contains. You will learn more about polymorphism later in the course. The following code segment illustrates the syntax of the instanceof operator:
<object> instanceof <class type>

instanceof: An operator in Java that tests whether or not an object is an instance of a particular class type.

You could use the following code to test if an object is a String and output the result to the console:
String myString = "Hello World"; boolean x; x = myString instanceof String; System.out.println(x);

polymorphism: A feature of many objectoriented programming languages that enables objects to assume various forms.

TASK 1C-2:
Using the instanceof Operator
1. 2. In your text editor, open a blank, new le and save it as C:\077954\ InstanceOf.java. Create a class called InstanceOf that includes a main method.
public class InstanceOf { public static void main(String [] args) { } }

In Java programming, youll generally use the instanceof operator to determine what course of action your programs should take.

3.

Create a String object, called myString that contains the characters, Hello World, an Object called myObject that contains a reference to myString, and two booleans, x and y.
public class InstanceOf { public static void main(String [] args) { String myString = "Hello World"; Object myObject = myString; boolean x,y; } }

4.

Use the instanceof operator to determine if myString is a String object. Assign the result to x.
public class InstanceOf { public static void main(String [] args) { String myString = "Hello World"; Object myObject = myString; boolean x, y; x = myString instanceof String; } }

Lesson 1: Javas Language Fundamentals

23

5.

Determine if myObject is an Integer object. Assign the result to y.


public class InstanceOf { public static void main(String [] args) { String myString = "Hello World"; Object myObject = myString; boolean x, y; x = myString instanceof String; y = myObject instanceof Integer; } }

6.
In this example, the + operator is used to concatenate two strings.

Display the results to the screen.


public class InstanceOf { public static void main(String [] args) { String myString = "Hello World"; Object myObject = myString; boolean x, y; x = myString instanceof String; y = myObject instanceof Integer; System.out.println("myString is a String = " + x); System.out.println("myObject is an Integer = " + y); } }

7.

Save, compile, and run the program. Compare your output to the following screen:

Type Conversion
Java is picky about the compatibility of datatypes. This presents a serious problem in the real world. For example, the datatype resulting from an expression evaluation may not match the datatype of the variable to which the value is assigned or the corresponding datatype of the parameter in the method call. Either case will result in an error. To circumvent this problem, Java provides us with two mechanisms to convert one datatype into another. The rst is called type conversion, which is performed automatically. The second is called typecasting, which you control and perform. Java performs automatic type conversion when the code:
24 Java 2 Programming for Developers

Evaluates expressions. Performs assignments. Invokes methods and passes parameters to methods.

The following code illustrates Javas automatic type conversion during expression evaluation.
//Product of a byte and an int is an int int y = 10; byte z = 3; int x = y * z; //OK because z is promoted to int before evaluation byte x = y * z; //Results in a compile error

This code illustrates Javas automatic type conversion during assignment operations.
short x = 12; float y = x; //12 is widened to 12.0, its float equivalent

When Java converts from a narrower (or smaller) datatype to a wider (or larger) datatype, there will be no loss of precision or information. This conversion is called a widening conversion. Figure 1-2 represents the possibilities for primitive widening conversions that are safe from loss of precision.
Widening Conversions

Figure 1-2: Widening conversions. When you assign a value of one datatype to a variable of another datatype, Java will perform automatic conversion if: the two types are compatible; and the destination type is larger than the source datatype. So when you assign a byte value to an int variable, you do not have to explicitly perform a typecast; Java will automatically perform the conversion for you. When performing widening conversions, here are Javas compatibility rules: Integers and oating point datatypes ARE compatible. Numeric datatypes (integer and oating point) and char are NOT compatible. Numeric datatypes (integer and oating point) and boolean are NOT compatible. char and boolean are NOT compatible.

Lesson 1: Javas Language Fundamentals

25

Even though a oat datatype is a 32-bit oating point number, and a long is a 64-bit integer, you may lose precision in converting from a oat to a long. This is because the decimal portion of the oat will be discarded during the conversion. Hence, a oat to int conversion is not a widening conversion. Java does not automatically convert between incompatible types, nor does Java perform narrowing conversions. For these situations you must explicitly perform a typecast. For example, Java will not automatically convert a double or an int to a byte.

Typecasting
Typecasting, also known as casting, is the mechanism by which you can instruct Java to explicitly convert an existing value of a given datatype to a new value with a new datatype. In other words, typecasting is explicit type conversion that you control as opposed to automatic type conversions that Java controls. When you perform typecasting or explicit type conversions from a broader datatype to a narrower datatype, in what is called a narrowing conversion, a loss of precision can result. For example, a double with a value of 25.34 that is converted to an int will contain the value 25. Java does not round to the nearest value that can be contained in the target type; it simply discards the least signicant digits (in this case, the 34 to the right of the decimal point) of the number. Narrowing conversions can only be accomplished through an explicit typecast. To typecast, you use this syntax:
(type) expression

typecasting: Also called casting, the mechanism by which Java converts an existing value of a given datatype to a new value with a new datatype.

For example, you use (int) (31/5) to convert the resulting oating value of 6.2 to an int datatype value of 6. When you typecast a char value to an int value, you get the equivalent numeric code of that character in the character set. When you convert from the char datatype to the byte or short datatypes, you will be going in the reverse direction. This, too, would constitute a narrowing conversion. When you typecast an int value to a char value, you get the character in the character set with that numeric code. You cannot typecast a boolean datatype; it can only be a true or a false. Typecasting is at the third level from the top in the operator precedence. It takes precedence over many arithmetic operators, such as multiplication and division. As a result, you may accidentally typecast just the variable right next to the typecast operator as opposed to typecasting the resulting value. You must enclose the whole expression in parentheses to properly typecast the result of the expression. So, the safe syntax is:
(type) (expression)

You will learn more about objects later in this course.

Java also enables you to use the same syntax to typecast objects. To cast a given object to another object type, the target object must be a subclass of the source object. You can cast to a parent class by simply assigning the object a reference of the parent type.

Automatic Type Promotion


You have already seen that Java performs automatic type conversions when evaluating expressions. Lets consider two byte variables: x and y. Byte variables can hold integer values within the range 128 to +127. Lets assume that x and y both contain a value of 100. Consider the following expression:
26 Java 2 Programming for Developers

x * y

When you multiply these variables, the result is 10,000. A value of 10,000 is way beyond the upper range of the byte, the datatype of both operands. So this expression results in an overow and should not be allowed. To resolve this problem, Java automatically promotes or treats both as if each byte operand were an int operand when evaluating expressions. This ensures that the results will be within the int datatype of both operands. This resolution can trigger problem situations and compiler errors. This conversion takes place even if the resulting number is within the range byte datatype. Lets again consider two byte variables: x and y. Byte variables can hold integer values within the range 128 to +127. Lets assume that variable y contains a value of 25. Consider the following statement:
x = y * 4;

To the right side of the assignment operator, you have the expression y * 4 (which evaluates to 100well within the byte datatype range). But since Java performed an automatic type promotion for y when evaluating the expression, the result is of the int datatype even though the resulting value is small enough to t within the range of the byte datatype of the operand y. In effect, you are now assigning an int resulting value into a byte variable x. This would be a narrowing conversion and, therefore, not automatically performed by Java. You will have to explicitly perform this as follows:
x = (byte) (y * 4);

Here you are explicitly converting the int value of 100 to a byte value of 100 before assigning the result to variable x. Figure 1-3 shows the compiler error that results when your code attempts a implicit narrowing conversion from double to int.

Figure 1-3: Compiler error. The compiler informed you to explicitly perform a typecast from double to int. The problem code is:
monthlyStateTax = monthlySalary * 0.15;

You must explicitly typecast the result to int before you can assign this value to the int variable monthlyStateTax. You can explicitly typecast using the following statement:
monthlyStateTax = (int) (monthlySalary * 0.15);

Lesson 1: Javas Language Fundamentals

27

Because Java promotes byte and short operands to ints before performing calculations to avoid overow (or underow, in the case of negative numbers), you might wonder what happens if an int is overowed. Given that 2,147,483,647 is the maximum value that an int can contain, consider the following code:
int i = 1000000; System.out.println(i * i);

Java makes no attempt to handle the int overow and prints the output: -727379968 which is the truncated 32bit version of the result of i * i.

TASK 1C-3:
Typecasting and Type Conversion
Objective: To demonstrate your knowledge of typecasting concepts. 1. True or False? You can perform typecasting of a char value. True. 2. True or False? You can perform typecasting of a boolean value. False, booleans can only be true or a false. They cannot contain a 1 or a 0. 3. From the C:\077954 directory, open OperatorTest.java and observe its contents.
class OperatorTest { public static void main (String [] args) { //Declare class variables and assign values int salaryIncome = 50000; int interestIncome = 430; int totalIncome; int taxOwed; //Calculate totalIncome totalIncome = salaryIncome + interestIncome; //Calculate taxOwed based on 38% tax bracket taxOwed = totalIncome * 0.38; //Print the results System.out.println("Total Income = " + totalIncome); System.out.println("Total Tax = " + taxOwed); } }

The le contains a simple application that calculates the amount of income tax owed for a given income. Like many income tax calculators, this application uses an integer amount for the tax owed result.

28

Java 2 Programming for Developers

4.

Compile the application. An error is generated because the code attempts to assign a double value into an int. One way to x this is to use an explicit cast.

5.

Switch back to your text editor and locate the line with the problem code. The line with the problem code is:
taxOwed = totalIncome * 0.38;

6.

Perform explicit typecasting to x the problem. The updated line should read as follows:
taxOwed = (int) (totalIncome * 0.38);

7. 8.

Save and compile the application. Run the application.

Lesson 1: Javas Language Fundamentals

29

Topic 1D
Comparing Objects for Equality
The question, Does x = y? seems pretty straightforward. The truth is, this is not always an easy question to answer. Depending on what you mean by =, the answer youre given may not be the answer you expected. Learning how to properly compare objects for equality can help avoid possible errors in your programs.

Object References
When programming in Java, you usually declare variables to store objects for later use or examination. When you store an object (rather than a primitive such as an int or boolean) in a variable, what you are actually storing is a reference to that object which resides somewhere in memory. Where in memory it is stored is not important to you, because you always use the reference (or variable) to access the object. Consider the following code:
String myString; myString = new String("Hello");

reference: A pointer to an object in memory.

This code declares a variable of type String. A new String object is then created and assigned to the myString variable. Figure 1-4 illustrates what this code has done.

Figure 1-4: Storing an object reference in a variable. As you can see in Figure 1-4, the value Hello is not actually stored in the variable myString. Rather, an object reference is stored in the variable.

30

Java 2 Programming for Developers

The ExceptionPrimitive Datatypes


The exception to the example illustrated in Figure 1-4 is when you are dealing with primitive datatypes. Primitive datatypes are not stored as objects in memory. Therefore, when you store a primitive datatype in a variable, the datatypes valuenot an object referenceis stored. Consider the following code:
int counter = 1;

Here, the value 1 is stored in the variable, as shown in Figure 1-5.


Storing a Primitive Type in a Variable

Figure 1-5: Storing a primitive type in a variable.

The == Operator
Now that you are familiar with object references, youre ready to learn about comparing objects for equality. The == operator compares two primitive datatypes or two object references for equality. Depending on what is being compared (primitive datatypes or object references), the == operator behaves differently. If the == operator is used to compare two primitive datatypes, the result of the operator will be true if the values of the two primitive datatypes are true. For example:
int X = 5; int Y = 5;

== operator: An operator in Java that compares two primitive datatypes or two object references for equality.

Figure 1-6 illustrates what this code has done.


The Value 5 Assigned to Two Different Variables, X and Y

Lesson 1: Javas Language Fundamentals

31

Figure 1-6: The value 5 assigned to two different variables, X and Y. In this case, X == Y would return true because the primitive datatypes X and Y both contain the same value, 5. If the == operator is used to compare two object references, the result of the operator will be true only if the object references point to the same object in memory. For example:
String string1; string1 = new String("Hello"); String string2; string2 = new String("Hello");

Two new String objects have been created and stored in two different variables, string1 and string2. Figure 1-7 illustrates what this code has done.
Two Object References Pointing to Two Objects in Memory

32

Java 2 Programming for Developers

Figure 1-7: Two object references pointing to two objects in memory. Here, string1 == string2 would return false because these variables reference different objects in memory. Even though the values of the two strings are identical, the references to these strings are different. Therefore, the == operator does not consider these variables to be equal. In the next section, youll discover how you can compare objects to see if their values are equal.

The equals() Method


The equals() method was designed to compare objects for equality based on criteria other than object references. All classes in Java inherit the equals() method from the Object class. The equals() method is used like this:
someObject.equals( anotherObject );
Youll learn more about some of the concepts in this section later in the course.

The equals() method returns true if it determines that the class-specic requirements for equality have been met. This means that each class can dene what being equal means. Youll learn more about how classes inherit behaviors from one another in a later lesson. The equals() method of the Object class has very simple requirements. It will return true if the object references of two objects point to the same object in memory. This may sound exactly like the == operator, but as stated earlier, the Object class has very simple requirements for equality. All classes in Java inherit these simple requirements for equality, unless of course, a particular class overrides the equals() method.

Lesson 1: Javas Language Fundamentals

33

By overriding the equals() method, a Java class can dene its own rules for equality. For example, the String class overrides the equals() method so that it returns true if both strings contain the same characters. Now if you refer back to the situation in Figure 1-7, you see that string1.equals( string2 ); would return true because the characters that make up both strings are equal. If you were writing your own class, it is recommended that you override the equals() method in order to dene what the equality requirements for your class are. For example, if you were writing a class called Person, you might dene the equals() method to return true if two Person objects contain the same Social Security Number. This is demonstrated in the code segment below:
public class Person {
Only the code relevant to the equals() method is shown here.

public int ssn; public boolean equals( Object obj ) { // the result is always false, unless // criteria is met boolean result = false; // if obj is an instance of Person // and my ssn = obj's ssn, then // both both objects are equal // and the result is true. if ( obj instanceof Person ) { if ( this.ssn == ((Person)obj).ssn ) { result = true; } } return result; } }

TASK 1D-1:
Comparing Objects for Equality
Objective: To test your knowledge of comparing objects for equality. 1. Observe the following code:
String a = new String( "Java is fun." ); String b = new String( "Java is fun." ); String c = a;

Draw a picture similar to Figure 1-7 that illustrates the current state of the program. 2. What is the result of a == b? Why? The result is false, because a does not point to the same object in memory that b points to. This is because the code uses the new keyword to create two separate string objects.

34

Java 2 Programming for Developers

3.

What is the result of a.equals( b )? Why? The result is true, because the strings a and b contain the same characters.

4.

What is the result of a == c? Why? The result is true, because when c was created, it was initialized to point to the same object in memory as a points to.

5.

What is the result of b.equals( c )? Why? The result is true because the strings b and c contain the same characters.

6.

Observe the following code:


String a = String( "Java is fun." ); String b = String( "Java is fun." ); String c = a;

Draw another picture similar to Figure 1-7 that illustrates the current state of the program. 7. What is the result of a == b? Why? The result is true, because a and b point to the same set of characters in the String Constant Pool. When b is initialized, the JVM checks the String Constant Pool to determine if the string,Java is fun exists. In this case, it does because a is initialized before b. Therefore, b is given a reference to the same string as a. 8. What is the result of a.equals( b )? Why? The result is true, because the strings a and b contain the same characters.

Summary
In this lesson, you explored Java syntax, operators, and datatypesthe basic elements of the Java programming language. These fundamentals, which in many ways are similar to fundamentals of languages such as C and C++, are the essential building blocks of any Java application.

Lesson 1: Javas Language Fundamentals

35

Lesson Review
1A Discuss several of the key features and benets of the Java programming language.
Answers will vary, but may include object-orientation, component-based nature, portability, small application size, security, and concurrence. Describe the process and tools that are used to develop Java applications. The development cycle can be completed in three steps: Source code for a Java program is written in a text editor. The source code is compiled with the javac compiler command-line application. The resulting class les are executed in the Java Virtual Machine.

1B What is wrong with the following declaration?


float final = 3.6874f;

The declaration is illegal because it uses a keyword as an identier.

1C What is the purpose of the instanceof operator?


The instanceof operator allows you to test whether or not an object is an instance of a particular class type. Give an example of when you would use the instanceof operator. Answers will vary, but may include: Before casting an object to another class type. If your programs next course of action is dependant upon what class type an object is.

1D What is the difference between the == operator and the equals() method when comparing strings?
The == operator compares two String references and tests whether those references point to the same object in memory. The equals() method tests whether two strings have the same characters. How does the equals() method behave in a class if the class does not override the equals() method inherited by Object? It behaves just like the == operator.

36

Java 2 Programming for Developers

Flow Control and Data Structures


Overview
Javas ow control statements dictate how a program proceeds through its statements and code blocks. Javas data structures provide classes and methods that enable a program to store and manipulate data. In this lesson, youll explore Javas various loops and switches. Then, youll use several of these loops and switches to store, manipulate, and retrieve data in Javas data structures.

LESSON

2
Data Files IfElseTest.java DoWhileTest.java ForTest.java ArraySorter.java CollectionsDemo.java ListSorter.java NestedFor.java Lesson Time 3 hours

Objectives
To use ow control and data structures, you will: 2A Investigate the various if statements, the switch statement, the for loop, the while loop, and the do while loop. Looping and switching are essential components of any programming language. The Java Language Specication denes a number of loop and switch statements that enable your programs to evaluate conditions and perform actions based on those conditions. 2B Create various types of data structures to store and manipulate data. Javas data structures include arrays, vectors, hashes, and other tools to store series of data. Each data structure class includes methods for manipulating stored data.

Lesson 2: Flow Control and Data Structures

37

Topic 2A
Flow Control Structures
Life is like a Java programits full of choices. Imagine that you are a business owner, processing timesheets and computing taxes for your employees. If an employee works full-time, you compute their taxes and benets in a certain way. On the other hand, if an employee is part-time, you compute taxes and benets in another way. You have to change your course of action based on certain conditions being true or false.

The if Statement
Javas ow control structures are similar to the ow control structures in C and C++.

Java provides you with the if statement to make decisions and to change your applications course of action according to whether the condition (a boolean expression) is true or false. With the if statement, your application can execute a single line of code or a block of code when a condition is true. A block statement is a number of lines of code enclosed within curly braces: { and }. Consider the following code and note how it is displayed in Figure 2-1.
1 2 3 4 if ( salary > 100000) { System.out.println("A salary of " + salary + " is greater than 100,000"); }

if statement: A code statement that enables a program to perform a certain action only if a condition (boolean expression) is true.

The if Statement

Figure 2-1: The if statement.

38

Java 2 Programming for Developers

In line 1, the application evaluates a variable (the salary) and determines if it is greater than 100,000. If the value contained in the salary variable is a number greater than 100,000, then the condition is true. If salary contains a number that is either less than or equal to 100,000, the condition is false. If the condition is true, the application performs the action or code contained between the opening curly brace at the end of line 1 and the closing brace at the beginning of line 3. In this case, the whole action is contained in line 2. If the condition is false, the application skips ahead to the next block of code. Because the body of the if statement contains only a single statement, this code could also be written on a single line, as illustrated here:
if ( salary > 100000) System.out.println("A salary of " + salary + " is greater than 100,000");

TASK 2A-1:
Using the if Statement
Objective: To write, compile, and execute an application that contains an if statement. 1. In a new, blank document in your text editor, create a class called IfTest that contains a main method declaration.
class IfTest { public static void main (String [] args) {

} }

2.

Add code to initialize the salary variable.


class IfTest { public static void main (String args[]) { int salary = 110000; } }

3.

Add code for an if statement that will evaluate the salary variable and, if it is greater than 100,000, print A salary of salary is greater than 100,000.
class IfTest { public static void main (String [] args) { int salary = 110000; if ( salary > 100000) { System.out.println("A salary of " + salary + " is greater than 100,000"); } } }
Do not place a semicolon right after the if condition. This will give you unexpected results.

Lesson 2: Flow Control and Data Structures

39

4.

Save the le as IfTest.java. Compile and test the application. Because the value contained in the salary variable is greater than 100,000, the message inside the if block is printed.

5.

What would happen if the salary value was less than 100,000? Nothing would be displayed.

The if-else Statement


The if-else statement is an extension to the if statement. In the if statement, your application executed code only if a given condition was true. The application did nothing if the condition was false.
if-else statement: A code statement that enables a program to perform a certain action if a condition (boolean expression) is true and to perform an alternative action if the condition is false.

In the if-else statement, your application will also perform an alternative action if the condition is false. The following code illustrates an if-else statement.
1 2 3 4 5 6 7 if ( salary > 100000) { System.out.println("A salary of " + salary + " is greater than 100,000"); } else { System.out.println("A salary of " + salary + " is less than or equal to 100,000"); }

Line 1 evaluates if salary is greater than 100,000. If salary is greater than 100,000, then the condition is true and the rst block of code is executed. If salary is either less than or equal to 100,000, the condition is false and the block of code after the else keyword is executed.

Passing Values to the Main Method


In any Java application, the main method receives an array of strings as arguments. Conventionally, this array is stored in a variable called args []. When you have developed applications that are executed from the command line, you can enter values into the array of arguments by typing them as command-line arguments. For example, you can start an application called MyApp with the value 5 by typing:
C:\>java MyApp 5

40

Java 2 Programming for Developers

In this example, 5 is stored in the zero position of the args[] array and can be referenced by the variable args[0].
Youll learn more about arrays later in this lesson.

TASK 2A-2:
Using the if-else Statement
Objective: To write, compile, and execute an application that contains an if-else statement. 1. From the C:\077954 folder, open IfElseTest.java. This application takes a value entered at the command line and prints a message to the console if the value is greater than 100,000.
class IfElseTest { public static void main (String args[]) { // Get a value from the command line // and convert it to an integer int salary = Integer.parseInt(args[0]); if ( salary > 100000) { System.out.println("A salary of " + salary + " is greater than 100,000"); } } }

2.

Add an else statement to the end of the if block. The else statement will be executed if the value of salary is less than or equal to 100,000.
class IfElseTest { public static void main (String args[]) { // Get a value from the command line // and convert it to an integer int salary = Integer.parseInt(args[0]); if ( salary > 100000) { System.out.println("A salary of " + salary + " is greater than 100,000"); } else { System.out.println("A salary of " + salary + " is less than or equal to 100,000"); } } }
Do not put a semicolon after the condition or after the else. This will give you unexpected results.

3. 4.

Save and compile the application. Run the application with a parameter of 124000.
C:\077954>java IfElseTest 124000

Lesson 2: Flow Control and Data Structures

41

Because salary > 100000 evaluates to true, the if block of the branching statement is executed.

5.

Run the application with a parameter of 90000.


C:\077954>java IfElseTest 90000

Because salary > 100000 evaluates to false, the else block of the branching statement is executed.

Nested ifs
The if-else-if statement enables you to nest a second if statement that will only be processed in the event that the rst if condition is false. Consider the following code:
if-else-if statement: A code statement that enables you to nest a second if statement that will only be processed if the rst if condition is false.

42

Java 2 Programming for Developers

1 if ( salary > 100000) { 2 System.out.println("A salary of " + salary 3 + " is greater than 100,000"); 4 } else if (salary >= 50000) { 5 System.out.println("A salary of " + salary 6 + " is between 50,000 and 100,000"); 7 } else { 8 System.out.println("A salary of " + salary 9 + " is less than 50,000"); 10 }

This code is presented in a owchart format in Figure 2-2.


The if-else-if Statement (nested if)

Figure 2-2: The if-else-if statement (nested if). In line 1, the code evaluates whether or not the salary is greater than 100,000. If the value contained in the salary variable is a number greater than 100,000, then the condition is true. If salary contains a number that is either less than or equal to 100,000, then the condition is false. If the condition is true, the action or code contained between the opening curly brace at the end of line 1 and the closing brace at the beginning of line 3 is executed. In line 4, the keyword else indicates what code should be executed if the condition evaluated in line 1 is false and the salary variable is greater than or equal to 50,000. In line 7, the else keyword says what code should be executed if both of the previous conditions evaluated to false.

Lesson 2: Flow Control and Data Structures

43

TASK 2A-3:
Using the if-else-if Statement
Objective: To write, compile and test a small application containing an if-else-if statement. 1. Save the IfElseTest.java class from the previous activity as IfElseIfTest. java. Rename the class to IfElseIfTest.
class IfElseIfTest { public static void main (String args[]) { int salary = Integer.parseInt(args[0]); if ( salary > 100000) { System.out.println("A salary of " + salary + " is greater than 100,000"); } else { System.out.println("A salary of " + salary + " is less than or equal to 100,000"); } } }

2.
Do not put a semicolon after the condition or after the else. This will give you unexpected results.

Add code for the nested if.


class IfElseIfTest { public static void main (String args[]) { int salary = Integer.parseInt(args[0]); if ( salary > 100000) { System.out.println("A salary of " + salary + " is greater than 100,000"); } else if (salary >= 50000) { System.out.println("A salary of " + salary + " is between 50,000 and 100,000"); } else { System.out.println("A salary of " + salary + " is less than or equal to 100,000"); } } }

44

Java 2 Programming for Developers

3.

Modify the print statement in the else clause.


class IfElseIfTest { public static void main (String args[]) { int salary = Integer.parseInt(args[0]); if ( salary > 100000) { System.out.println("A salary of " + salary + " is greater than 100,000"); } else if (salary >= 50000) { System.out.println("A salary of " + salary + " is between 50,000 and 100,000"); } else { System.out.println("A salary of " + salary + " is less than 50,000"); } } }

4. 5.

Compile the application. Run the application with a parameter of 124000. java IfElseIfTest 124000 Your output should be similar to the following graphic:

The rst if condition on line 1 was true; it prints the line A salary of 124000 is greater than 100,000. 6. Run the application with a parameter between 50,000 and 100,000. java IfElseIfTest 75000

Lesson 2: Flow Control and Data Structures

45

Your output should be similar to the following graphic:

The rst if condition on line 1 is false and the second if condition on line 3 is true. It prints the line A salary of 75000 is between 50,000 and 100,000. 7. Run the application with a parameter less than 50,000. java IfElseIfTest 45000 Your output should be similar to the following graphic:

The rst if condition on line 1 is false and the second if condition on line 3 is false. It prints the line A salary of 45000 is less than 50,000.

46

Java 2 Programming for Developers

The switch Statement


The if-else statement enables you to change your course of action depending on whether the boolean expression (if condition) is true or false. The boolean expression could take only one of two values, thus limiting you to only one of two courses of action. The switch statement is not limited to a boolean expression; it can use byte, short, int, or char types. When the switch expression is evaluated byte, short, or char values are promoted to ints. The switch statement enables you to choose one of multiple courses of action, depending on the value of the expression. From a conceptual perspective, a switch statement is like an if statement, except that it can have more than two branches. The syntax for the switch statement is:
switch (expression) { case value1: code to process value1 goes here break; case value2 code to process value2 goes here break; default: code to process every other scenario goes here }

The switch statement is similar but not the same as the case statement in most other languages.

switch statement: A control structure that executes code branches based on an exact match between a passed parameter and the values dened by individual case statements.

Consider the following example:


switch (inputChar) { case 'A': case 'a': System.out.println("\"" break; case 'B': case 'b': System.out.println("\"" break; case 'C': case 'c': System.out.println("\"" break; case 'D': case 'd': System.out.println("\"" break; default': System.out.println("\"" break; }

+ args[0] + "\" for \"Apple\"");

+ args[0] + "\" for \"Boy\"");

+ args[0] + "\" for \"Cat\"");

+ args[0] + "\" for \"Dog\"");

+ args[0] + "\" - Whatever!");

The owchart for this code is provided in the Figure 2-3 below:
The switch Statement

Lesson 2: Flow Control and Data Structures

47

Figure 2-3: The switch statement. Java evaluates the expression inputChar. If it is an a or A, the program will print "A" for Apple. If it is an b or B, the program will print "B" for Boy. If it is an c or C, the program will print "C" for Cat. If it is an d or D, the program will print "D" for Dog. For every other value that inputChar can take, the program will print "Whatever!" When Java sees the switch keyword, it evaluates the expression enclosed in parentheses. Depending on the resulting value, it branches to the appropriate case branch. Once it starts processing at that branch, Java forgets everything about the decision and continues sequential processing through the subsequent branches. To avoid this situation, if you want your switch to execute only a single block, you must put a break statement at the end of every branch. The break statement tells the thread of execution to proceed to the end of the switch statement. The switch statement has some limitations: Switches can only branch based on equalities. You cannot use inequalities such as greater than or less than. The expression must result in a simple primitive datatype that can be typecast to int. You cannot use the larger primitives such as the long or the oat.

Make sure you have the break statement at the end of every case. Otherwise, you may get unexpected results.

Every switch statement can also be implemented using an if-else-if statement. The reverse is not true. Not every if-else-if statement can be implemented by a switch statement. In the following code you will observe the implementation of the switch statement that you explored using an if-else-if statement.

48

Java 2 Programming for Developers

if (inputChar = 'a' | inputChar = 'A') System.out.println("\"" + args[0] + } else if (inputChar = 'b' | inputChar System.out.println("\"" + args[0] + } else if (inputChar = 'c' | inputChar System.out.println("\"" + args[0] + } else if (inputChar = 'd' | inputChar System.out.println("\"" + args[0] + } else { System.out.println("\"" + args[0] + }

{ "\" for \"Apple\""); = 'B') { "\" for \"Boy\""); =' C') { "\" for \"Cat\""); =' D') { "\" for \"Dog\""); "\" - Whatever!");

The owchart for this code is presented in Figure 2-4.


The if Alternative to the Switch Statement

Figure 2-4: The if alternative to switch statement. When you have a choice between implementing your decision using a switch statement or an if-else-if statement, choose the switch statement. Some reasons for this recommendation are: Simplicity: A switch statements construction is easier to understand and follow than a nested if statement. Performance: An if-else-if construct must make a series of if-else decisions as it works through the nested ifs. With the switch statement, your program has only one decision to make.

Lesson 2: Flow Control and Data Structures

49

TASK 2A-4:
Using the switch Statement
Objective: To write, compile, and execute an application that contains a switch statement. 1. Create a new class called SwitchTest, and save the le as SwitchTest.java. The source le should be:
class SwitchTest { public static void main (String args[]) {

} }

2.

Add code to store a character passed in as a parameter.


class SwitchTest { public static void main (String args[]) { char inputChar = args[0].charAt(0); } }

3.

Add code for the switch statement.


class SwitchTest { public static void main (String args[]) { char inputChar = args[0].charAt(0); switch (inputChar) { } } }

4.

Add code to process an a.


class SwitchTest { public static void main (String args[]) { char inputChar = args[0].charAt(0); switch (inputChar) { case 'a': System.out.println(args[0] + " is for Apple"); break; } } }

5.

Add code to process a b.

50

Java 2 Programming for Developers

class SwitchTest { public static void main (String args[]) { char inputChar = args[0].charAt(0); switch (inputChar) { case 'a': System.out.println(args[0] + " is for Apple"); break; case 'b': System.out.println(args[0] + " is for Boy"); break; } } }

6.

Add code to process every other case.


class SwitchTest { public static void main (String args[]) { char inputChar = args[0].charAt(0); switch (inputChar) { case 'a': System.out.println(args[0] + " is for Apple"); break; case 'b': System.out.println(args[0] + " is for Boy"); break; default: System.out.println(args[0] + " - Whatever!"); break; } } }
Generally, a switch statement will contain more than three cases.

7. 8.

Save and compile the application. Run the application with the parameter value a by typing java SwitchTest a.

Lesson 2: Flow Control and Data Structures

51

The console prints a is for Apple, as shown in the following graphic:

9.

Run the application with the parameter value b. The console prints b is for boy.

10. Run the application with the parameter value M.

52

Java 2 Programming for Developers

The console prints the letter M, followed by - Whatever!, as shown in the following graphic:

The while and do-while Loops


You will encounter many situations in life where you have to repeat a certain course of action as long as a given condition is true. When the condition becomes false, you stop repeating the course of action, and go on with life. For example, as long as you have your job, you keep going to your office. When the condition becomes false and you do not have your job, you do not go to the office. Java provides the while loop to handle programming situations like this. The while loop is a conditional iteration; it keeps on iterating or looping as long as a specied condition is true. Once the condition becomes false, the loop exits. The general syntax for the while loop is:
while (condition) { // put code to be processed inside the loop here }

Consider the following example for the while loop.


1 class WhileTest { 2 public static void main (String args[]) { 3 4 int loopLimit = Integer.parseInt (args[0]); 5 int i = 1; 6 7 while (i <=loopLimit) { 8 System.out.println ("The loop count is: " + i); 9 i++; 10 } 11 } 12 }

In this example, you pass a parameter into the program. The program converts the String parameter args[0] to an int datatype and assigns it to the int variable, loopLimit. This enables you to test the looping with different limits.

Lesson 2: Flow Control and Data Structures

53

Now focus your attention on the while loop. In this while loop structure, the condition is that the variable i must be less than or equal to the parameter passed into the program. Keep in mind that i is initialized to a value of 1, right before the start of the loop. The loop code is contained between the opening curly brace after while (i <=loopLimit) and the closing curly brace is on its own line immediately after the line containing the statement i++;. System.out.println ("The loop count is: " + i); prints the loop count contained in the variable i. If the loop ends right after this line, the value of i will always be 1 and the program would be stuck in an innite loop. So, in the next line, the code increments the i by 1 (i++). The owchart for the while loop is presented in Figure 2-5.
The while Loop

Figure 2-5: The while loop. The do-while loop functions the same as the while loopwith one exception: the conditional testing is done after the code is processed (in the while loop, the conditional is tested before the loop statements are executed.). Thus, even if the condition were false when you get into the loop, the do-while loop assures you that the code will be processed at least once.
do { // put code to be processed inside the loop, here } while (condition);

do-while loop: A code statement that ensures that the code will be processed at least once.

Consider the following example for the do-while loop.


1 class WhileTest { 2 public static void main (String args[]) { 3 4 int loopLimit = Integer.parseInt (args[0]); 5 int i = 1; 6 7 do { 8 System.out.println ("The loop count is: " + i); 9 i++; 10 } while (i <=loopLimit); 11 } 12 }

54

Java 2 Programming for Developers

In this example, you pass a parameter into the program. In line 4, the String parameter args[0] is converted to an int datatype and assigned to the int variable loopLimit. This enables you to test the looping with different limits. Focus on the do-while loop structure. The variable i that is part of the test condition is initialized to a value of 1, right before the start of the loop. The loop code is contained between the opening curly brace after do and the closing curly brace after i++;. System.out.println ("The loop count is: " + i); prints the loop count contained in the variable i. If you end the loop right after this statement, the value of variable i will always be 1 and you would be stuck in an innite loop. So, in the next line, you increment the variable i by 1, which is represented by the statement i++;. After the closing curly brace, the condition while (i <=loopLimit); states that the variable i must be less than or equal to the parameter you passed into the program. The owchart for the do-while loop is presented in Figure 2-6.
The do-while Loop

Figure 2-6: The do-while loop.

TASK 2A-5:
Using the while and do-while Loops
Objective: To write, compile, and execute an application that contains a while loop and a do-while loop. 1. Create the body of a class named WhileTest.
class WhileTest { public static void main (String args[]) {

} }

Lesson 2: Flow Control and Data Structures

55

Save the le as WhileTest.java. 2. Add code to store a number passed in as a parameter.


class WhileTest { public static void main (String args[]) { int loopLimit = Integer.parseInt(args[0]); } }

The Integer.parseInt(args[0]); portion of this code uses the parseInt method of the Integer wrapper class to convert the number entered at the command line to an int. Youll learn more about this in a later lesson. 3. Add code to declare ia temporary variable to track the loop count.
class WhileTest { public static void main (String args[]) { int loopLimit = Integer.parseInt(args[0]); int i = 1; } }

4.

Add code for the while statement.


class WhileTest { public static void main (String args[]) { int loopLimit = Integer.parseInt(args[0]); int i = 1; while (i <=loopLimit) { } } }

5.

Add code for displaying the loop count.


class WhileTest { public static void main (String args[]) { int loopLimit = Integer.parseInt(args[0]); int i = 1; while (i <=loopLimit) { System.out.println ("The loop count is: " + i); } } }

56

Java 2 Programming for Developers

6.

Add code for incrementing variable i, the loop counter.


class WhileTest { public static void main (String args[]) { int loopLimit = Integer.parseInt(args[0]); int i = 1; while (i <=loopLimit) { System.out.println ("The loop count is: " + i); i++; } } }
If you do not change the value of variable i in the loop, it will always have its initial value of 1. The condition will never become true, and you will be stuck in the loop forever.

7. 8.

Save your changes. Compile the application. Run the application with the parameter value 10. The program loops through 10 times. Your output should be similar to the following graphic:

9.

From the C:\077954 folder, open the DoWhileTest.java source code le. The le contains the body of a Java class called DoWhileTest.
class DoWhileTest { public static void main (String args[]) { int loopLimit = Integer.parseInt (args[0]); int i = 1; // Add do-while statement here } }

Lesson 2: Flow Control and Data Structures

57

10. Add code for the do-while statement.


class DoWhileTest { public static void main (String args[]) { int loopLimit = Integer.parseInt (args[0]); int i = 1; // Add do-while statement here do { } while (i <=loopLimit); } }

11. Add code for displaying the loop count.


class DoWhileTest { public static void main (String args[]) { int loopLimit = Integer.parseInt (args[0]); int i = 1; // Add do-while statement here do { System.out.println("The loop count is: " + i); } while (i <=loopLimit) ; } }

12. Add code for incrementing variable i, the loop counter.


class DoWhileTest { public static void main (String args[]) { int loopLimit = Integer.parseInt (args[0]); int i = 1; // Add do-while statement here do { System.out.println("The loop count is: " + i); i++; } while (i <=loopLimit) ; } }

13. Save your changes. Compile and run the application with the parameter value 10.

58

Java 2 Programming for Developers

The application should loop through 10 times. The output should be similar to the following graphic:

14. Compare the results of the do-while with that of the while when you use a parameter of 20. The output is the same in both cases. It seems that there is no difference between the do-while and the while loops. 15. Run the DoWhileTest application with the parameter value 0. Your output should be similar to the following graphic:

If you ran the WhileTest application with a parameter of 0, no output would be produced because the while loop evaluates the condition before entering the body of the loop.

Lesson 2: Flow Control and Data Structures

59

Suggested Time: 5 minutes or less

CHECK YOUR SKILLS 2-1


Creating a Decrementing while Loop
In this practice activity, youll modify the WhileTest.java application so that it starts with the highest number rst and counts down to 1 before exiting the loop. 1. With the WhileTest.java source code le open in your text editor, rename the class to WhileRevTest. Youll also need to rename the source code le to WhileRevTest.java. Change the loop condition so that the loop continues until the loopLimit variable is greater than or equal to 1. Also, change the console message so that it displays the loopLimit variable.
class WhileRevTest { public static void main (String args[]) { int loopLimit = Integer.parseInt (args[0]); while (loopLimit >= 1) { System.out.println ("The loop count is: " + loopLimit);

2.

3.

Finally, change the count increment so that it decrements the loopLimit variable.
System.out.println("The loop count is: " + loopLimit); loopLimit--; } } }

4.

Save, compile, and test your application.

The for Loop


The for loop is a numeric loop with a mechanism to specify the starting value, the nal value, and a means to increment values after an iteration. With the while loop, you specied the starting value, the nal value, and the means of incrementing values after an iteration. The for loop structure incorporates each of these elements. The general syntax for the for statement is:
for (initialize; test; increment) { // put code to be processed inside the loop, here }

for loop: A numeric loop with a mechanism to specify the starting value, the nal value, and the way to increment values after an iteration.

The owchart for the for loop is presented in Figure 2-7.


The for Loop

60

Java 2 Programming for Developers

Figure 2-7: The for loop. When the Java processor enters the loop, it rst executes the initialization section of the loop statement. For example, you may use the code int i = 1; where the integer variable i serves as loop counter. If you include the counter variable declaration in the for loops initialization statement, the variable will be local to the loop and not accessible outside the loop. As a result, there will be no opportunity to use it outside the loop, whether deliberately or accidentally. After initialization, the processor will encounter the test part of the loop. For example, you may use the statement i <= 10;. This means that the program will iterate as long as the value of the variable i is less than or equal to 10. If the test you specify turns out to be false, Java will exit the loop. If the test is true, the processor will execute the body of the loop. After the body of the loop is processed, the processor will execute the increment portion of the loop. Then it goes back to the test and repeats the process until the test becomes false. for (int i = 1; i <= loopLimit; i++) { System.out.println ("The loop count is: " + i);} The annotated code is presented in Figure 2-8.

Lesson 2: Flow Control and Data Structures

61

Figure 2-8: The for loop example code. The owchart for this code is presented in Figure 2-9.
The for Loop Example

Figure 2-9: The for loop example. The initialize statement sets the variable i to 1. The test will be true as long as i is less than or equal to the variable called loopLimit. The increment statement, i++;, means that the processor will increment the variable i by 1. The body of the loop is the statement System.out.println ("The loop count is: " + i);. It prints the value of the loop counter variable i for every iteration of the loop.

62

Java 2 Programming for Developers

TASK 2A-6:
Using the for Loop
Objective: To create an application that uses a for loop. 1. From the C:\077954 folder, open the ForTest.java source code le. The le contains the body of a class called ForTest.
class ForTest { public static void main (String args[]) { int loopLimit = Integer.parseInt (args[0]); } }

2.

Add code for the for loop.


class ForTest { public static void main (String args[]) { int loopLimit = Integer.parseInt (args[0]); for (int i = 1; i <= loopLimit; i++) { } } }
Do not put a semicolon at the end of the for line. This will give you unexpected results.

3.

Add code for displaying the loop count.


class ForTest { public static void main (String args[]) { int loopLimit = Integer.parseInt (args[0]); for (int i = 1; i <= loopLimit; i++) { System.out.println ("The loop count is: " + i); } } }
The character indicates that a single line of code has been displayed on multiple lines. In your code, omit the character and the line break.

4.

Save, compile, and run the application with the parameter value 10. The console prints the loop count starting at 1 and ending with 10. Your out-

Lesson 2: Flow Control and Data Structures

63

put should be similar to the following graphic:

Suggested Time: 5 minutes or less

CHECK YOUR SKILLS 2-2


1. Modify the application to start with the highest number rst and count down to 1.
class ForRevTest { public static void main (String args[]) { int loopLimit = Integer.parseInt (args[0]); for (int i = loopLimit; i >= 1; i--) { System.out.println ("The loop count is: " + i); } } }

2.

Test your changes.

Abnormal Exiting
When you encounter certain situations in life, you decide to suddenly discontinue your routine. For example, if you are at work and the re alarm sounds, you will immediately and abnormally (as in not part of the normal daily routine) exit your workplace. Java provides keywords that enable you to abnormally terminate your programs current process and exit. These keywords are continue and break.

64

Java 2 Programming for Developers

The continue Statement


Consider another payroll processing program. You get the number of hours worked from the employees timesheets, and compute their wages accordingly. You do this for the rst person, then the second, then the third, and so on. You get to the fth person and their employment status is part-time. You do not pay them for holidays; therefore, you need to go ahead and compute wages for the next person. Java provides you with the keyword continue to handle situations such as this. The continue keyword tells the Java processor to go directly to the next iteration of the loop. If you use continue as a statement by itself, it will always go to the next iteration, and the code that follows the continue statement will never be executed. When you use continue, you must execute it only if a certain condition is true. In the payroll processing example, you can use the following statement to go to the next iteration if they are part-time (or PT) employees: if (status = "PT") continue; The owchart for this payroll processing program is presented in Figure 2-10, using the while loop.
The continue Statement

The continue statement must only be implemented if a condition becomes true. Otherwise, the code that follows the continue will never be executed.

Figure 2-10: The continue statement. For any iteration, you will get to the decision to continue if the employee status = PT. If this condition is true, you will go directly to the next iteration without processing part 2 of the body of the loop. If this condition is false, you will process part 2 of the body of the loop before you go to the next iteration.

Lesson 2: Flow Control and Data Structures

65

The break Statement


When the re alarm goes off, you are conditioned to stop doing what you are doing and exit the physical situation immediately. Java provides the keyword break to accomplish an immediate exit. The keyword break tells Java to immediately exit the loop. If you use the break statement by itself, during the rst iteration, Java will encounter the break and exit the loop. So it will never execute the code in the loop that follows the break, and it will not iterate. In other words, it will only execute the code that precedes the break, and only do so once. Lets consider another example: going shopping for as long as you like. You check your cash status and you suddenly nd that you have no more cash therefore, you must exit your shopping spree. The owchart to do this is presented in Figure 2-11.
The break Statement

The break statement must only be implemented if a condition becomes true. Otherwise, it would function as if there were no looping.

Figure 2-11: The break statement. The code to test and exit is:
if (outOfCash) break;

On each iteration, the processor tests to see if the Out of cash condition is true. If the condition is true, the loop exits.

66

Java 2 Programming for Developers

TASK 2A-7:
Abnormal Exiting
Objective: To create a method to abnormally exit an application using continue and break. 1. Save the le ForTest.java from the previous activity as EarlyOutTest.java and rename the class to EarlyOutTest; the source code should be:
class EarlyOutTest { public static void main (String args[]) { int loopLimit = Integer.parseInt (args[0]); for (int i = 1; i <= loopLimit; i++) { System.out.println ("The loop count is: " + i); } } }

2.

Modify the System.out.println line. Change println to print and add a \n line break to the beginning of the string in parentheses. When youre nished, your code will look like this:
class EarlyOutTest { public static void main (String args[]) { int loopLimit = Integer.parseInt (args[0]); for (int i = 1; i <= loopLimit; i++) { System.out.print ("\nFirst stage of: " + i); } } }

3.

Add a second System.out.print to display text after the continue statement. Youll add the continue statement in the next step.
class EarlyOutTest { public static void main (String args[]) { int loopLimit = Integer.parseInt (args[0]); for (int i = 1; i <= loopLimit; i++) { System.out.print ("\nFirst stage of: " + i); System.out.print ("-- Second stage of: " + i); } } }

Lesson 2: Flow Control and Data Structures

67

4.

Include a continue statement that performs an early termination during the loops third iteration (skipping the second stage).
class EarlyOutTest { public static void main (String args[]) { int loopLimit = Integer.parseInt (args[0]); for (int i = 1; i <= loopLimit; i++) { System.out.print ("\nFirst stage of: " + i); if (i == 3) continue; System.out.print ("-- Second stage of: " + i); } } }

5.

Include a break to exit the loop at the 12th iteration.


class EarlyOutTest { public static void main (String args[]) { int loopLimit = Integer.parseInt (args[0]); for (int i = 1; i <= loopLimit; i++) { System.out.print ("\nFirst stage of: " + i); if (i == 12) break; System.out.print (" - did NOT break"); if ( i == 3 ) continue; System.out.print ("-- Second stage of: " + i); } } }

6. 7.

Save your changes. Compile the application. Run the application with a parameter of 10.

68

Java 2 Programming for Developers

Your output should be similar to the following graphic:

8.

Observe your output. The second stage is not printed for the third iteration of the loop because the continue statement caused the loop to jump forward to its next iteration. The loop completes at loop count 10.

9.

Run the application with the parameter value 14. Your output should be similar to the following graphic:

10. Observe your output. This time, the loop encounters the break on iteration 12 and exits from the loop.

Lesson 2: Flow Control and Data Structures

69

Suggested Time: 5 minutes or less

CHECK YOUR SKILLS 2-3


Using the continue Statement
1. Open the NestedFor.java source code le and examine the code. The application prints lines that contain a descending, and then ascending, number of asterisks. Compile and execute the code with a parameter of 10. Notice that at the center of the output there are two lines that each print a single asterisk. How do you think you could cause the application to skip one of the lines that prints a single asterisk? You could use the continue statement to skip forward to the next iteration of one of the loops. 4. Modify the program NestedFor.java so that it displays the following pattern that has only a single asterisk in the middle line. Use the continue statement.
********** ********* ******** ******* ****** ***** **** *** ** * ** *** **** ***** ****** ******* ******** ********* ********** class NestedFor { public static void main (String args[]) { int loopLimit = Integer.parseInt (args[0]); for (int i = loopLimit; i >= 1; i--) { for (int j = 1; j <= loopLimit; j++) { System.out.print ("*"); } System.out.println (" "); } for (int i = 1; i <= loopLimit; i++) {

2. 3.

70

Java 2 Programming for Developers

if (i == 1) continue; for (int j = 1; j <= loopLimit; j++) { System.out.print ("*"); } System.out.println (" "); } } }

5.

Compile and execute the code with a parameter of 10.

Apply Your Knowledge 2-1


Using Nested Loops
1. Create an application that displays the following pattern:
******************* ********* ********* ******** ******** ******* ******* ****** ****** ***** ***** **** **** *** *** ** ** * * ** ** *** *** **** **** ***** ***** ****** ****** ******* ******* ******** ******** ********* ********* *******************

Suggested Time: 45 minutes

Lesson 2: Flow Control and Data Structures

71

2.

Create an application that displays the following pattern:


* ** *** **** ***** ****** ******* ******** ********* ********** ********* ******** ******* ****** ***** **** *** ** *

3.

Create a program that will print all primary numbers up to 10,000. (A primary number is a number that can only be evenly divided by the number 1 and by the number itself. An example is the number 23. It can only be evenly divided by the numbers 1 and 23. Another example of a prime number is the number 17.) Create a program that will print the following sequence up to 1,000: Each number is the sum of the two numbers that precede it. The starting number is 1. When determining the second number, assume that you have a 0 (zero) to the left of the rst number. The rst 6 numbers in this sequence would be: 1 1 2 3 5 8. This sequence is also called the Fibonacci sequence. The ratio of successive numbers in the Fibonacci sequence converges to 1.62. This ratio is considered to be the golden ratio for aesthetically pleasing architectural length-to-width ratios.

4.

Topic 2B
Data Structures
Data structures are key features in any programming language. They allow you to store and process pieces of data together as a single object. Java provides several categories of data structures, including arrays and collections. In this topic, you will explore these data structures and learn how to create, populate, and manipulate them.

72

Java 2 Programming for Developers

Arrays
Arrays are mechanisms that are common to almost all programming languages. In Java, arrays are non-resizable data structures that store multiple objects or primitive types together as a single object. The objects you store in a Java array must all be of the same type. Figure 2-12 graphically illustrates an array of int elements. As you can see, Java arrays are zero-based; that is, the rst object in a Java array is indexed by the number 0.

array: A non-resizable data structure that stores multiple objects or primitive types together as a single object.

Figure 2-12: An example array.

Creating Arrays
Creating arrays is a lot like creating any other kind of object in Java. An array needs to be declared and initialized.

Declaring Arrays
Typically, arrays are declared by placing a set of square brackets immediately after a datatype, followed by the name you want to use to refer to the array. For example, to create an array of integers called numbers, you would use the following code:
int[] numbers;

You can also declare an array by placing a set of square brackets immediately after the variable name. For example, the following code is equivalent to the code in the previous example:
int numbers[];

Arrays can also contain a series of objects. For example, to create an array of strings, you would use:
String[] words;

or:
String words[];

Simply declaring an array doesnt mean that you can start using it. The next step is to initialize the array.

Initializing an Array
Creating the actual array in memory occurs when you initialize the array. After you declare an array, you use the keyword new to initialize it. At this time, you also need to specify how large you want the array to be. For example:
int[] numbers; numbers = new int[10];

The code above declares a variable called numbers to be an array of integers. It then creates a new integer array, of size 10, and assigns it to the variable numbers. Similarly, you can initialize an array of objects the same way:

Arrays cant have a negative size. If you initialize an array to have a negative size, an exception will be thrown.

Lesson 2: Flow Control and Data Structures

73

String[] words = new String[5];

The only difference between an array of primitive types and an array of objects is that an array of primitive types actually contains values. An array of objects contains references to objects in memory.

When an array is initialized it starts out empty, meaning all of the arrays elements are null. Also, the size of an array cannot be increased or decreased after being initialized.

Storing Data in an Array


After you have initialized an array, you can begin to store data in it. This is done by assigning values to the individual array elements. Array elements are accessed using the array name and the index number of the array element. In our integer array example, if you wanted to store a value in the rst element, you would use the following syntax:
numbers[0] = 2;

This assigns the value 2 to the rst element in the array. Remember that arrays are zero-based. Since numbers is an integer array of size 10, you can store values in elements 09. If you try to store a value in element 10 or higher, a runtime exception will be thrown.

Creating a Fully Populated Array


When working with arrays, keep in mind that the highest array index that you can access is always one less than the total size of the array.

Java provides a mechanism that allows you to create and populate an entire array with only one line of code. For example, to create a fully populated array of strings, you could use the following syntax:
String[] languages = { "Java", "C", "C++", "VB" };

All the values are placed between curly brackets and separated by commas. This code is equivalent to the following:
String[] languages = new String[4]; languages[0] = "Java"; languages[1] = "C"; languages[2] = "C++"; languages[3] = "VB";

Retrieving Data from an Array


Retrieving data from an array is just as easy as storing data. You simply use the array name and the index number of the element you want to retrieve. For example, to output the value of the second element of our String array, you would use the following code:
System.out.println( words[1] );

Once again, since arrays are zero-based, the second element has an index number of 1. And since words is a String array of size 5, you can retrieve values from elements 04. If you try to retrieve a value from element 5 or higher, a runtime exception will be thrown. If you attempt to retrieve a value from an array element for which no value has been previously set, null will be returned. Keep in mind that you can always test an element to see if it equals null before you use it:
if ( words[3] != null ) { // use the array element }

74

Java 2 Programming for Developers

Determining the Size of an Array


All arrays in Java have a property called length that allows you to obtain the size of any array. This is very useful for processing arrays because you no longer need to hard-code array index values. Consider the following code, which loops through an array and prints its contents to the console. In this example, names is an array of Strings and names.length refers to the array property, length.
public void outputNames( String[] names ) { int numberOfNames = names.length; for ( int i = 0; i < numberOfNames; i++ ) { System.out.println( names[i] ); } }
Dont place parentheses after length. If you do, your code will not compile. This is because length is a property, not a method.

Multi-dimensional Arrays
Java arrays arent restricted to one dimension. They can be two-, three-, even four-dimensional. This is possible because of the fact that arrays can contain other arrays. The syntax for declaring a two-dimensional array is very similar to a one-dimensional array:
char[][] charGrid = new char[3][5];

The code above creates a two-dimensional grid of characters. In terms of memory allocation, the grid can be looked at as an array containing ve arrays of characters. Each array of characters contains three characters. Figure 2-13 illustrates this.
A Two-dimensional Array

Figure 2-13: A two-dimensional array.

Lesson 2: Flow Control and Data Structures

75

TASK 2B-1:
Creating an Array
Objective: To declare and initialize an array. 1. Consider the following array:

2.

On a blank sheet of paper, write the code necessary to create and populate this array. You can name the array anything you wish. Dont use the shortcut method for creating and populating the array at this point.
int[] numbers; numbers = new int[8]; numbers[0] numbers[1] numbers[2] numbers[3] numbers[4] numbers[5] numbers[6] numbers[7] = = = = = = = = 47; 45; 50; 36; 15; 60; 51; 67;

3.

Try using the shortcut method for creating and populating the array. Write your solution in the space below.
int[] numbers = { 47, 45, 50, 36, 15, 60, 51, 67 };

4.

In your text editor, create a source code le called NumArrays.java that contains a class called NumArrays and an empty main method.
public class NumArrays{ public static void main(String[] args){ } }

5.

In the main method, declare and initialize an array of integers called numbers that contains 47, 45, 50, 36, 15, 60, 51, and 67.
public class NumArrays{ public static void main(String[] args){ int [] numbers = {47, 45, 50, 36, 15, 60, 51, 67}; } }

76

Java 2 Programming for Developers

6.

Declare and initialize an int called numberOfInts that contains the numbers arrays length property.
public class NumArrays{ public static void main(String[] args){ int [] numbers = {47, 45, 50, 36, 15, 60, 51, 67}; int numberOfInts = numbers.length; } }

7.

Using a for loop, iterate through the array and display its contents to the screen.
public class NumArrays{ public static void main(String[] args){ int [] numbers = {47, 45, 50, 36, 15, 60, 51, 67}; int numberOfInts = numbers.length; for (int i=0; i<numberOfInts; i++){ System.out.println(numbers[i]); } } }

8.

Compile and test your class. Your output should look like the following graphic:

Manipulating Arrays
Javas Arrays class denes many useful methods used to manipulate arrays. Using the Arrays class, you can: Test two arrays for equality. Fill an array with a specied value so that every array element contains the value. Sort the elements of an array. Perform a binary search on a sorted array.
Youll learn more about classes and methods in the next lesson.

Lesson 2: Flow Control and Data Structures

77

Testing Arrays for Equality


There are a couple ways to test two arrays for equality. The rst is to use the == operator, which will compare two array references to see if they point to the same array in memory. For example:
int[] array1; int[] array2; ... array1 == array2;

If you need to test whether two different arrays in memory contain the same elements, then you can use the equals() method of the Arrays class. For example:
int[] array1; int[] array2; ... Arrays.equals( array1, array2 );

The equals() method returns true if the arrays are the same size and both arrays contain the same elements, in the same order. Notice that you dont need to create an Arrays object in order to use the equals() method. This is because all the methods in the Arrays class are static.

Filling an Array
Some students may be unfamiliar with static methods. You should briey explain how static methods differ from regular methods.

If you want to quickly store a default value in all of an arrays elements, you can use the fill() method of the Arrays class. For example:
int[] data = new int[100]; Arrays.fill( data, 0 );

The code segment above creates an array of integers, of size 100, and assigns the value 0 to every element in the array. Assigning a default value to every element in an array is sometimes more useful than leaving every element in the array null. It is also safer, because null references have a potential for throwing the runtime exception, NullPointerException.

Sorting Arrays
Sorting arrays used to involve complicated algorithms and nested for loops. However, with the Arrays class, sorting an array is as simple as invoking the sort() method. This method is very easy to use:
String[] names; ... Arrays.sort( names );

The code above sorts an array of names without any for loops or complicated algorithms.

78

Java 2 Programming for Developers

Primitive types can always be sorted. However, you can only sort an array of objects if the objects implement the Comparable interface. When an object implements the Comparable interface, it allows the object to compare itself to other objects of the same type. Thus, sorting is possible.

Performing a Binary Search on an Array


Binary searches are very fast and efficient. The Arrays class allows you to perform a binary search on an array by using the binarySearch() method. There are two requirements for using the binarySearch() method on an array: 1. The elements of the array must be sorted. 2. The elements of the array must be comparable, meaning they must implement the Comparable interface, or they need to be a primitive type.

The String class implements the Comparable interface, as do a few other classes. To nd out which classes, consult the J2SE API documentation.

The binarySearch() method searches for a value within an array. If the value is found, the method returns the array index of the value. If the value is not found, the method returns a negative value. The following code example demonstrates the binarySearch() method:
int[] numbers = { 35, 28, 72, 50, 93, 4 }; // be sure to sort the array first! Arrays.sort( numbers ); // locate the number 50 int location = Arrays.binarySearch( numbers, 50 );

The variable location would contain the array index of the value 50.

TASK 2B-2:
Manipulating an Array
Objective: To use the Arrays class to sort an array. You will also practice iterating over the elements of an array. 1. In your text editor, open ArraySorter.java. The rst part of the programs main method creates an array called numbers and populates it with random integers. Youll learn more about creating random integers in a later lesson. Scroll down to the comment, // output the array before sorting. After the comment, add code to create a loop that outputs the contents of the array before they are sorted.
// output the array before sorting System.out.println("Before:"); for (int i = 0; i < numbers.length; i++) { System.out.println(numbers[i]); }

2.

Lesson 2: Flow Control and Data Structures

79

3.

Copy the loop and paste it into the after sorting section of code.
// output the array after sorting System.out.println("After:"); for (int i = 0; i < numbers.length; i++) { System.out.println(numbers[i]); }

4.

Compile and run the program. Your output should be similar to the following, except your numbers will be different:

Observe that both outputs are the same. 5. In the main() method, nd the comment that states:
// add code to sort the array

Immediately after this line, insert the following code:


Arrays.sort(numbers);

6.

Compile and run the program. Your output should be similar to the following graphic, except your numbers will be different:

Notice that the second time the array is printed, it is now sorted.

80

Java 2 Programming for Developers

Collections
Arrays are great for storing data. However, in an object-oriented language such as Java, arrays dont seem to t in. This may be due to the fact that arrays contain no methods and only one public eld. To address this problem, Java introduced collections. Collections are similar to arrays in that they can store multiple objects together as a single object. Beyond that, they are very different. Some of the differences between arrays and collections include: Unlike arrays, collections are resizable. There is no need to dene their size when you initialize them. As you add more elements to a collection (or remove them), the collection simply resizes itself automatically. With arrays, you have to store like datatypes together. For example, the array has to contain all integers, or all strings. With collections, you can store different types of objects together in the same collection. Collections are object-oriented. Elements of a collection are not accessed by enclosing an index value in square brackets. Instead, well-dened methods are used to store, retrieve, and manipulate the data within a collection. This also allows for collections to contain functionality. For example, some collections dont allow duplicate elements, while others do. Arrays simply store data, with no available methods or other functionality. Primitive datatypes cannot be stored in collections. This is because collections store objects, and primitive datatypes are not objects.

collection: A storage mechanism in Java that takes an object-oriented approach to the storage, retrieval, and manipulation of data.

Some collections allow you to dene their initial size. This is not required, but can improve the performance of the collection.

Collections come in many shapes, sizes, and behaviors. All can be found in the java.util package. There are two general categories of collectionssets and lists.

Sets
A set is a collection that does not allow duplicate elements to be stored within it. Java provides two different set classesHashSet and TreeSet. A hash set does not maintain any particular order on its elements. This means that the order in which you add elements to a hash set is probably not the order in which they are stored. A tree set, on the other hand, maintains its elements in ascending order. A tree set also allows you direct access to the rst and last elements in the set. In terms of performance, a hash set can store data slightly faster than a tree set. This is because a tree set contains the overhead of maintaining elements in ascending order. A hash set does not require this overhead and is, therefore, faster. Deciding which one to use depends on if you require sorted data.

Lists
A list is a collection that maintains the order in which elements are added. This allows for positional access to the list, meaning that elements can be stored and retrieved from specic locations. Another characteristic of a list is that they can contain duplicate elements.

Maintaining order does not necessarily mean sorted. It simply means that the collection keeps track of the positions of the elements.

Lesson 2: Flow Control and Data Structures

81

Java provides three different list classes: Vector, ArrayList, and LinkedList. All three basically provide the same functionality. You can add data to them, in addition to retrieving and removing data from them. You can access the elements by an index number, similar to arrays. The difference between these three types is how they are implemented by Java. Vectors and array lists are implemented using arrays. Linked lists, on the other hand, are implemented using linked nodes, as shown in Figure 2-14.
Illustration of a Linked List

Figure 2-14: Illustration of a linked list. The elements of a linked list are called nodes. Each node has a pointer to the next node in the list.
node: A single element of a linked list.

Large amounts of data refers to 100 elements or more.

The difference in performance between vectors, array lists, and linked lists will depend on how the particular collection is used. Differences in performance are generally negligible while working with small amounts of data. However, large amounts of data can begin to show differences in performance. Vectors and array lists perform better than linked lists if data is always added to the end of the collection. This is because vectors and array lists always keep some empty elements at the end of their underlying arrays. When a new element is added to a vector or array list, the new element is simply placed in one of these empty array elements. Linked lists dont keep any empty nodes available, so when you add a new element to the end of a linked list, a new node needs to be createdand this slows performance. If you will be frequently inserting data into the middle of a collection, LinkedList performs better than Vector or ArrayList. When you insert an element into the middle of a vector or an array list, the elements of their underlying arrays need to be shifted around. A linked list, on the other hand, never has to shift elements; it simply moves pointers around. For example, Figure 2-15 shows an element being inserted between the rst and second elements of a linked list.

If students are having trouble understanding the insertion of an element into a linked list, you may want to walk them through a visual demonstration.

Insertion of an Element into a Linked List

Figure 2-15: Insertion of an element into a linked list. You should notice in Figure 2-15 that an insertion of an element into a linked list does not require any shifting or reallocation of the original nodes in the list. The new node is simply created and the pointers are updated to reect the new node. As with sets, choosing which particular type of list to use will depend on your needs as a programmer and how you will be using the list.

82

Java 2 Programming for Developers

TASK 2B-3:
Choosing a Collection
Objective: To choose the appropriate data structure for use with a specic programming situation. Performance should be the main consideration when choosing the type of collection. 1. Your program requires a data structure that keeps its elements in ascending order and does not allow duplicate elements. The data structure will need to hold approximately 1,000 elements. Which type of collection would you use for this situation and why? TreeSet should be used because this particular data structure does not allow duplicates and keeps its elements in ascending order. 2. Your program requires a data structure that will store about 20 elements, and these elements will always be inserted into the middle of the data structure. Duplicate elements must be allowed. Which type of collection would you use for this situation and why? Vector, ArrayList, and LinkedList would all work equally well because there are very few elements in the collection. HashSet and TreeSet would not be appropriate because those collections do not allow duplicates. 3. Your program requires a data structure that will store 10,000 or more elements, and these elements will always be inserted into random locations within the data structure. Duplicate elements must be allowed. Which type of collection would you use for this situation and why? LinkedList would work best in this situation because of the large number of elements and because the elements are not guaranteed to be added to the end of the collection. Vector and ArrayList would be constantly shifting elements around in order to accommodate new elements. LinkedList does not require element shifting and would, therefore, produce better performance.

Using Collections
All of the collections mentioned so far implement the Collection interface. This is important to you, the programmer, because it means that all the different types of collections are used in the same manner. While some collections have their own unique functionality, they all share common methods for storing and retrieving data.

Creating a Collection
To create a collection, simply declare it and then initialize it. For example, to create a linked list you would use the following code:
LinkedList myList; myList = new LinkedList();

Lesson 2: Flow Control and Data Structures

83

Another option is to declare the collection to be of type Collection. The advantage to doing this is that you can store any type of collection in a variable declared as Collection and you also change the type of collection you are using at any time, without needing to modify your existing code. For example:
Collection myCollection; myCollection = new LinkedList();

The above code declares a Collection variable and then assigns a linked list to it. You also could have assigned an array list to the Collection variable:
Collection myCollection; myCollection = new ArrayList();

The disadvantage of declaring a collection to be of type Collection is that you lose the ability to use any collection-specic functionality. You will be restricted to using the functionality that is common to all collections.

Storing Data in the Collection


You can store any type of object in a collection. This does not include primitive datatypes. If you want to store primitive datatypes in a collection, you will need to use a wrapper object. Every primitive datatype has a corresponding wrapper class that allows you to store a primitive datatype as an object. The following table lists the primitive datatypes and each ones corresponding wrapper class:
The wrapper classes for primitive datatypes can be found in the java.lang package.

Primitive Datatype
boolean byte char double float int long short

Wrapper Class
Boolean Byte Character Double Float Integer Long Short

You can store data in a collection by using the collections add() method. For example, to add the string hello to a collection, you would use the following code:
myCollection.add( "hello" );
Notice that adding data to a collection does not involve using square brackets ( [] ) as it did with arrays. Do not use array syntax when working with collections.

To add a primitive datatype to a collection, you can also use the add() method, but you will need to use a wrapper class in order to convert the primitive datatype to an object. For example:
// this is a primitive datatype int x = 10; // wrap the primitive type in a wrapper object Integer wrappedInt = new Integer( x ); // add the wrapper object to the collection myCollection.add( wrappedInt );

Different types of objects can be stored in a collection at the same time. For example, you can store strings together with integers, oats, or any other object type.
84 Java 2 Programming for Developers

Lists provide additional methods for storing data in specic locations within them. For example, to store a value in the third element of a list, you would use the following code:
List myList = new LinkedList(); ... String someValue = "Java"; myList.add( 2, someValue );
Just like arrays, lists are also zero-based. The third element is actually at position 2.

Retrieving Data from the Collection


When you retrieve data from a collection, it is returned to you as an object of type Object, regardless of its type at the time it was placed in the collection. This is one of the few disadvantages to using collections, and is due to the fact that you can store anything you want in them. Collections need a way to generalize their contents, and they do this by storing everything as objects. You can solve this problem by casting the retrieved object to whatever type you wish. Data is retrieved from a collection with the help of an iterator. An iterator is an object that enumerates the elements of a collection and returns them to you one at a time. You obtain an Iterator object by using the collections iterator() method. For example:
Iterator myIterator = myCollection.iterator();
Storing data in specic locations is not allowed when using sets. Even though sets and lists are both collections, positional access is only possible when using a list.

Once you have obtained a reference to an Iterator object, you can begin retrieving the data from the collection. This is typically done within a loop and involves using two methods of the iterator, hasNext() and next(). The hasNext() method returns true if there are more elements left to be iterated through. The next() method returns the next object in the collection. Its a good idea to always use the hasNext() method before using the next() method. The following code illustrates how to retrieve all the elements of a collection by iterating over its elements:
Collection myCollection = new HashSet(); ... Iterator myIterator = myCollection.iterator(); while ( myIterator.hasNext() ) { Object currentObject = myIterator.next(); // process the current object ... }

When casting an object from one type to another, always remember to use the instanceof operator rst. This will help you to identify what type you should cast the object to and will help you to avoid exceptions getting thrown.

iterator: An object that enumerates the elements of a collection and returns them to you one at a time.

The order in which elements are returned to you using an iterator will depend on the type of collection you are using. For example, the HashSet class does not guarantee the order of elements that are returned, while the TreeSet class will always return elements in ascending order. Vector, ArrayList, and LinkedList will return elements in the order in which they are stored within the collection. Lists provide additional methods for retrieving data from specic locations within them. To retrieve a specic element of a list without the overhead of using an iterator, you can use the get() method. The get() method takes one parameterthe index of the element you wish to retrieve. The following code retrieves the fth element of a list:
Lesson 2: Flow Control and Data Structures 85

// get the fifth element (position 4) Object theFifth = myList.get( 4 );

Other Collection Functionality


The following table lists some of the other methods available from a collection: Method
clear() contains( someObject )

Description
Removes all the elements from the collection. Examines the collection to see if it contains someObject. This method returns true if someObject is found in the collection. Examines the collection to see if it is empty. This method returns true if the collection is empty. Removes someObject from the collection. Returns the number of elements in the collection.

isEmpty() remove( someObject ); size()

TASK 2B-4:
Working with Collections
Objective: To create a collection, add elements to it, and iterate over the elements. You will also see how different types of collections store their elements. 1. 2. Open CollectionsDemo.java. Observe the rst line of code:
import java.util.*;

This import statement includes the collection classes of the java.util package in your program. Youll learn more about packages and the import statement in the next lesson. 3. Within the main() method, declare a Collection variable named myCollection. Initialize a new HashSet and assign it to the variable you just declared:
import java.util.*; public class CollectionsDemo { public static void main( String[] args ) { Collection myCollection; myCollection = new HashSet(); } }

86

Java 2 Programming for Developers

4.

Add the following string elements to the collection: J, A, V, A, I, S, C, O, O, L.


import java.util.*; public class CollectionsDemo { public static void main( String[] args ) { Collection myCollection; myCollection = new HashSet(); myCollection.add( "J" ); myCollection.add( "A" ); myCollection.add( "V" ); myCollection.add( "A" ); myCollection.add( "I" ); myCollection.add( "S" ); myCollection.add( "C" ); myCollection.add( "O" ); myCollection.add( "O" ); myCollection.add( "L" ); } }

5.

On the next line, obtain an iterator from the collection and store it in a variable called myIterator:
Iterator myIterator = myCollection.iterator();

6.

Next, loop through the elements of the collection using the iterator. Print each element out to the screen:
while ( myIterator.hasNext() ) { System.out.print( myIterator.next() ); }

7.

Compile and run the program. Your output should look like the following, although your letters might be in a different order.

Notice that, because you are using a HashSet, the elements are not stored in the order in which you added them to the collection. Also, even though you added two As and two Os, only one A and one O show up in the collection. This is because HashSet does not allow duplicates.

Lesson 2: Flow Control and Data Structures

87

8.

Modify your program so that it uses a TreeSet rather than a HashSet. To do this, simply nd new HashSet() in your code and replace it with new TreeSet():
Collection myCollection; myCollection = new TreeSet();

9.

Compile and run the program. Your output should be similar to the following. Again, your letters may be in a different order.

Notice this time that, because you are using a TreeSet, the elements have been sorted in ascending order. There is still only one A and one O present in the collection because, just like HashSet, TreeSet does not allow duplicates. 10. Modify your program so that it uses a list. You may choose from either a Vector, ArrayList, or LinkedList. 11. Compile and run the program. Compare your output to the following:

Notice that, because you are using a list in your program, the elements have been stored in the same order in which you added them to the collection and duplicates are present.

88

Java 2 Programming for Developers

The Collections Class


Recall that when working with arrays, you could use the Arrays class to perform common tasks such as searching and sorting arrays. Java provides a similar class for working with collectionsthe Collections class. The Collections class contains many static methods that allow you to manipulate or obtain information from collections. The following table lists some of these methods: Method
binarySearch( list, object);

Description
Searches for the specied object in the specied list. The list must be sorted prior to using this method. If the object is found, this method returns the index location of the object, or a negative number if object is not found. Copies all the elements of the source list into the destination list. The destination list must be large enough to hold all the elements of the source list. Sets every element of the specied list to the specied object. Returns the maximum element from the specied collection. The collection must have at least one element and all elements must be comparable to each other. Returns the minimum element from the specied collection. The collection must have at least one element and all elements must be comparable to each other. Returns a new list, which contains n copies of the specied object. Reverses the order of the elements contained within the specied list. Randomizes the order of the elements contained within the specied list. Returns a new set that contains a single copy of the specied object. Arranges the elements of the specied list into ascending order. The elements of the list must be comparable to each other.

For a complete list of methods for the Collections class, refer to the J2SE API documentation.

copy( destination, source );

fill( list, object ); max( collection );

Be sure to use the methods that are appropriate for the collection you are working with. Some of these methods can manipulate all collections. Others will only manipulate a specic type of collection, such as a list.

min( collection );

nCopies( n, object ); reverse( list ); shuffle( list ); singleton( object ); sort( list );

Remember that, since all these methods are static, you dont need a Collections object to use them. For example, to randomize the elements of a list, you would use the following code:
List myList; ... // randomize the list Collections.shuffle( myList );

Lesson 2: Flow Control and Data Structures

89

TASK 2B-5:
Manipulating a List
Objective: To use the Collections class to reverse, shuffle, and then sort the elements of a list. 1. Open ListSorter.java. This program creates a list and adds several elements to it. It then prints out the contents of the list four separate times. The rst time, the elements are displayed in the order in which they were added. The second time, the elements are printed in reverse order. The third time, the elements are shuffled, and the nal time, the elements are sorted. You will write the code that reverses, shuffles, and then sorts the list. In the main() method, nd the comment that states:
// reverse the list

2.

Immediately after this line, insert the following code:


Collections.reverse(myList);

This line of code reverses the order of the elements in the list. 3. Further down in the main() method, nd the comment that states:
// shuffle the list

Immediately after this line, insert the following code:


Collections.shuffle(myList);

This line of code randomizes the order of the elements in the list. 4. Find the comment that states:
// sort the list

Immediately after this line, insert the following code:


Collections.sort(myList);

90

Java 2 Programming for Developers

This line of code sorts the elements of the list into ascending order. 5. Compile and run the program. Compare your output to the following graphic:
Your shufed output will probably look different from the one displayed, as the shuffle() method is random.

Summary
In this lesson, you used control structures to control the ow of Java programs and you used Javas collections to store and manipulate data. Control structures and collections are an integral part of any Java application.

Lesson Review
2A If you had the choice between using a nested if statement and a switch statement with seven cases or conditions, which alternative would you choose? Why?
The switch statement is preferred because if you use the nested if, you will have to use six nested levels of if statements. What would happen if you put a continue statement into a loop without making it conditional? The code following the continue statement would never be executed.

2B How do collections differ from arrays?


Answers may include: Collections are resizable; arrays are not. A single collection can contain objects of all different types; arrays must contain objects that are all of the same type. Collections are object-oriented and can dene many methods, while arrays dene no methods.
Lesson 2: Flow Control and Data Structures 91

Primitive types are allowed in arrays; they are not allowed in collections.

Under what circumstances would you use a tree set? You would use a tree set if your program required a data structure that ordered its elements in ascending order and did not allow duplicates. What kind of tasks can you perform using the Collections class? Answers will vary, but may include: Search for an element within a list. Copy a lists elements into another list. Obtain the minimum and maximum element within a collection. Reverse the order of the elements within a list. Randomize the order of the elements within a list. Sort the elements of a list into ascending order.

92

Java 2 Programming for Developers

Object-oriented Programming
Overview
One of the most commonly discussed features of the Java programming language is its object orientation. In this lesson, youll explore the various aspects of Java that enable programmers to develop object-oriented applications with Java. You will start by creating and employing methods, and will then move on to the true object-oriented topics such as inheritance, polymorphism, overloading, and overriding.

LESSON

3
Data Files Motor.java TestMotor.java HelloMsg.java PrintMsg.java Employee.java StartEmployee.class StartEmployee.java Rect.java Overrides.java Rect2.java StartRect2.java Lesson Time 8 hours

Objectives
To develop applications that use Javas object-oriented features, you will: 3A Create and implement methods. Java methods are similar to functions in C and C++ and procedures in other programming languages. They enable programmers to create reusable blocks of code. 3B Dene, declare, and use a method. This topic denes what a method is, introduces you to the reasons for wanting to use a method, and shows you how to declare (make) and invoke a method. 3C Dene and use overloaded methods. You can declare multiple methods with the same name in a Java program. You will see how Java uniquely distinguishes between multiple methods and what requirements programmers need to adhere to. 3D Explore, discuss, and implement the facets of constructors. Java uses constructors to initialize variables when an object is instantiated. You will learn how to correctly utilize default constructors, as well as to implement both normal and overloaded constructors. 3E To explore the concept of inner classes. Inner classes enable you to specify behavior that cannot be accessed by any class other than the class that encloses the inner class. You have a variety of inner classes: static inner classes, member inner classes, local inner classes, and anonymous inner classes.

Lesson 3: Object-oriented Programming

93

Topic 3A
Java Methods
A method is a section of code that behaves like an independent program, and that is executed by invoking the method name. In Java, it is only within methods that you can write executable statements; accordingly, methods in Java represent processes or behaviors. Notably, you have the option to pass values into the method as shown in Figure 3-1; these values are called input values, arguments, or parameters. Optionally, methods can return a single valuecalled the return valuewhen the method body has nished.
method: A section of code that behaves like an independent program and that an be invoked using the method name. In Java, you can write executable statements only within methods. Accordingly, methods represent processes or behavior.

Javas methods are similar to functions or procedures in other languages. Methods take on additional meaning in the context of object orientation (OO).

Figure 3-1: The method.


The Method

Figure 3-2 shows the diagrammatic representation of a method that calculates the area of a rectangular room. The name of the method is AORR. The method AORR needs the length and width of the room in order to calculate the area. You can accomplish this by passing length and width into the method AORR as arguments. The method outputs the area as a returned value.

The Area of Rectangular Room (AORR) Method

Figure 3-2: The Area of Rectangular Room (AORR) method.

Declaring a Method
To declare a method, use the syntax:

94

Java 2 Programming for Developers

return_type method_name (parameter_list) { ... ... // body of method (Java statements) ... ... }

An annotated version of this syntax is provided in Figure 3-3:


Method Declaration

Figure 3-3: Method declaration. The return_type is the datatype of the value that is returned by the function. The return_type can be either any one of the eight primitive datatypes or the name of a class. The parameter list is a comma-separated sequence of datatype and variable name pairs; one sequence is required for each parameter. The Java code that species what this method will perform is written into the body of the method between the opening brace at the end of line 1 and the closing brace at the beginning of line 7. If the return_type is void, it indicates that the function will not return a value. The following code denes a method named AORR that requires two input parameters or arguments (here, length and widthboth integers). It computes and returns the area.
int AORR (int length, int width) { return length * width; }

return_type: Species the datatype of the returned value.

The annotated version of the code is provided in Figure 3-4 below:

Lesson 3: Object-oriented Programming

95

Figure 3-4: The AORR method declaration. When you pass in a variable containing a primitive value as a method argument, it is passed in by value. This means that the method copies the value of the argument and stores it into an internal variable of the method. If you should modify this internal variable, the variable that you passed in will not be affected in any way. A variable that contains an object really contains a reference to the object. When you pass in a variable that contains an object reference as an argument into a method, the object reference is copied into the corresponding internal variable of the method. So in effect, the internal variable is also pointing to, or referencing, the same object. In this case, you are passing in the object variable by reference. Any modications to the internal variable will accordingly modify the object that it points to. Since the object variable that you passed in also points to the same object, you have changed the values of the original object variable.

Invoking a Method
You can use the following syntax to use or invoke a method in the program:
method_name(argument1, argument2, .....)

For example, you can invoke the method AORR to calculate the area of a room 20 feet long and 14 feet wide with the following statement:
area = AORR(20, 14);

You can invoke the same method to compute the area of another rectangle of different dimensions (in this case, length = 32, width = 27) by using the following code: area = AORR(32, 27); Additionally, you can use dot notation to invoke methods that are members of instances of other classes. For example, if the AORR method from the previous example were part of an object (an instance of a class) named square, you could invoke the method with the following code:
area = square.AORR(32, 27);

96

Java 2 Programming for Developers

Benefits of Using Methods


As you have seen, a method promotes reusability. You dene it once and invoke it everywhere else. You can invoke it with different input values for the arguments. A method improves productivity. Instead of repeating the code everywhere you need it, you just invoke it. A method improves quality by making the code more modular. A method improves quality by making the code more consistent. The method will always process the arguments and return the value in the same way. A method improves quality by minimizing the impact of making changes. Changes only have to be made once, in the method denition. Otherwise, you would have to repeat the change everywhere you repeat the code. Whenever you are required to make the same change at multiple locations, chances are good that you may accidentally make different changes at different locations or you may accidentally miss making the changes at some locations.

Using Dot Notation


After you have created an instance of a class, you can use the following syntax to refer to a method for that instance as shown in Figure 3-5. instance.method(parameter_list);

Figure 3-5: The annotated code that is used to refer to a method using syntax. A period, or dot, separates the instance from the method. This system of specifying the method is called the dot notation. Lets revisit the Car class and dene three variables (or instances) of the Car datatype called myJag, hisCar, and herCar by using the following Java statement:
Car myJag = new Car (); Car hisCar = new Car(); Car herCar = new Car();
dot notation: A type of code notation that uses periods to separate identiers. In the example java.awt.Graphics, the period identies the full reference for the Graphics class: that the Graphics class is contained within the awt package, which is contained within the java package. In myJag.moveIt(), the period indicates that you are invoking the moveIt method of the myJag instance.

Once you dene these instances, you can invoke the classs moveIt() or stopIt() methods of either instance with the following statements:

Lesson 3: Object-oriented Programming

97

You do not have to invoke every method of every instance as represented by the code. You invoke just the methods of the appropriate instances at any given point in the Java program.

myJag.moveIt(); myJag.stopIt(); hisCar.moveIt(); herCar.moveIt(); hisCar.stopIt(); herCar.stopIt();

TASK 3A-1:
Working with Methods
Objective: To create and call methods. 1. 2. Open Motor.java. The le contains the outline of a class called Motor. The class has a single member variable, speed. In the indicated region near the end of the class, add a public method called setSpeed() that returns void and takes a single int argument called newSpeed. The method should set the value speed to the value of newSpeed.
// Add methods here public void setSpeed(int newSpeed){ speed = newSpeed; }

An instance of this class can use this method to change the speed of the motor object. This type of method is often called a setter method. 3. Add a public method called getSpeed() that takes no arguments and returns speed, an int.
public int getSpeed(){ return speed; }

An instance of this class can use this method to get the speed of the motor. This type of method is often called a getter method. Together, getters and setters are known as accessor methods. 4. 5. Save Motor.java and open TestMotor.java. TestMotor is a class that instantiates a Motor object called m. In the indicated region, add a call to ms setSpeed() method that sets the speed to 30.
// Set the Speed m.setSpeed(30);

6.

In the indicated region, add a call to the getSpeed() method to display the motors speed.
// Display the Speed System.out.println("The Motor's Speed Is: " + m.getSpeed());

98

Java 2 Programming for Developers

7.

Save, compile, and test the application. The application starts in the main method and creates a new instance of the Motor class. Then it calls Motors methods to set and display the speed variable.

8.

Do you think this application could have been created from a single source le? Can you think of some advantages to using the two source les? This example could have been developed using a single source le that contains the Motor class denition and a main method that creates an instance of the class and calls its methods. However, in object-oriented programming, programmers try to develop classes that represent the properties and functionality of real-world objects. Having one class that represents a motor and a separate class that instantiates the motor object and calls its methods is good object-oriented practice.

Lesson 3: Object-oriented Programming

99

Suggested Time: 15 minutes

Apply Your Knowledge 3-1


Creating Methods
Objective: To practice writing Java methods. 1. Write the Java statement to declare a method, named COC, that calculates the circumference of a circle. COC requires the radius (integer argument or parameter) and it returns the circumference of the circle. The circumference will be a oating point value. You do not have to specify the body of the method. If you wish to specify the body of the method, the formula for computing the circumference of the circle is 2*Pi*radius, where Pi is a constant 3.142.
float COC (int radius) {

2.

Write the Java statement to declare a method, named myTax, that calculates an individuals income tax based on their income and tax bracket. You do not have to specify the body of the method.
int myTax (int income, double taxBracket) {

Topic 3B
Classes, Packages, and Interfaces
The Java Application Programming Interface, or API, includes many classes that represent external objects and contain methods that dene common behaviors for the objects. In addition, Java, like other object-oriented programming languages, allows you to create your own class les.

Classes and Objects


A class is the basic building block of the Java programming language. Classes are abstract representations, often of real-world objects, that encapsulate common properties and behaviors. An object is an instance of a class. While a class is abstract, an object or instance is concrete. An object or instance must be created before it can be used in the program. You create an instance (instantiation) by using the Java keyword new. The class is the basic or fundamental programming unit in Java and is declared by the following syntax:
class class_name { // Java statements }

100

Java 2 Programming for Developers

The annotated version of this code is presented in Figure 3-6.


The Class Declaration

Figure 3-6: The class declaration. You declare a class by using the class keyword in Java. To refer to the class in the program, you need to give it a name. For example, to declare a class called Car, you need to write the following code:
class Car {

The annotated version of this code is presented in the Figure 3-7.

Figure 3-7: The Car class declaration.

Lesson 3: Object-oriented Programming

101

The Java code that denes the specic characteristics of a class is written between the opening and closing curly braces. You will write Java code here to dene the characteristics of the class that consists of methods and properties. The methods and properties of a class are called class members. A property is a variable that is declared within a class denition. The more complete syntax to specify a class is:
class class_name { datatype instanceVariable1; datatype instanceVariable2; datatype instanceVariable3;

return_type methodName1 (parameter_list) { } return_type methodName2 (parameter_list) { } return_type methodName3 (parameter_list) { } }

The annotated version of this code is presented in Figure 3-8.

Figure 3-8: The class characteristics declaration. You create a new instance (or instantiate) by using the Java keyword new as shown in Figure 3-9. Lets consider three instances of the Car class: myJag, hisCar, and herCar.
Instances of the Car Class

102

Java 2 Programming for Developers

Figure 3-9: Instances of the Car class. If you want to create an instance of the Car class called myJag, use the following Java statement:
Car myJag = new Car();

The annotated version of this code is shown in Figure 3-10.

Figure 3-10: Instances of the Car classDeclaration. You evaluate the right-hand side of the assignment operator rst; you are creating a new instance of the class called Car. You assign or store it into the variable called myJag on the left that is of datatype Car so it can hold the instance of the Car class that is being assigned to it. In other words, you are creating an instance of the Car class and naming it myJag. In the rest of this lesson, you will encounter examples of the Car class. Lets assume that the Car class has ve properties: make, model, colorName, color, and numberOfDoors; and two methods: moveIt and stopIt, as illustrated in Figure 3-11.

Lesson 3: Object-oriented Programming

103

Figure 3-11: Car classProperties and methods.

TASK 3B-1:
Understanding Classes and Instances
1. Give two examples of a class and an instance of that class. Answers will vary. 2.
These properties and methods will assist you in the next two topics, when you are asked to dene and declare properties and methods.

What are some differences between a class and an instance? Answers will vary, but may include: The class is an abstract of the world of objects or instances with a common set of characteristics, while the instance is an actual object that has the same set of characteristics that are dened by the class. A class is the specication of the characteristics; the instance is the object with the characteristics. You dene classes with Java code, you create instances by instantiating the class.

3.

Consider the class called Car. What are some properties (information) and some methods (action or behavior) of Car? Answers will vary, but may include: Some properties are: model, make, numberOfDoors, color, and year. Some methods are: moveIt, stopIt, turnRight, and turnLeft.

104

Java 2 Programming for Developers

Inheritance
Javas extends keyword enables you to declare a class that inherits all of the properties and methods of another class. For example, given the following Car class:
class Car { String color; int numCylinders; }

. . .you could declare an object, ChevyCar that automatically includes the Car properties with the following class declaration:
class ChevyCar extends car { String chevyCarModelName; }

In programmer parlance, you could say that the ChevyCar class is a subclass of its superclass, Car. The relationship between the two classes may also be described as a parent-child relationship. You could also say that a ChevyCar is a Car that has a chevyCarModelName. Unlike some programming languages, Java classes can have only one parent classor class from which they inherit methods and elds. The feature, called single inheritance makes Java code more reliable.

Implementing Interfaces
An interface is a collection or set of abstract, or unimplemented, methods. Syntactically, interfaces are declared similarly to the way you declare classes. One difference between classes and interfaces is that interfaces cannot contain instance variables. They can, however, contain class variables. A second difference is that while you can declare the methods, you cannot ll in the methods body. Interfaces apply the concept of abstraction to a greater degree. You dene interfaces with no details about how they are implemented. A third difference is that a class can only inherit characteristics from classes in the parent system of the hierarchy, but it can inherit characteristics from interfaces that are in a different hierarchy. In other words, the class hierarchy was a single-parent inheritance system, but interfaces allow inheritance across the hierarchy, so interfaces remove the limitations of a single-parent system. For example, to do animations, you use threads. When you need to use threads, you use methods that are inherited from the Runnable interface. Since interfaces are collections of abstract classes, you do not specify the implementation or the instance variables. You only dene the methods shells with the return type and the parameters. The method implementation between the curly braces should not be included. In fact, the curly braces are eliminated also. Here is the general denition of an interface:
access_modifier interface interfaceName { returnType1 methodName1 (argument list); returnType2 methodName2 (argument list); returnType3 methodName3 (argument list); dataType variableName = value; }
interface: A collection or set of abstract methods.

Lesson 3: Object-oriented Programming

105

For every abstract method that you wish to include in the interface, add its return type, name, and argument list. The details of how you would implement this method is not specied. Variables that you dene within the interface are implicitly nal and static. In other words, these variables are read-only type variables. They cannot be altered by the classes that implement the interface. For example, to declare an interface called MyShapes that calculates the areas of different shapes, use the following code:
public interface MyShapes { double rectangle(double length, double width); double circle (double radius); double polygon(int numSides, double side); double myPI = 3.1419; }

One advantage of using interfaces is that classes can implement multiple interfaces. Programmers often use this feature to simulate multiple inheritance. To declare a class that implements an interface, use the following syntax:
ClassName implements InterfaceName { //body of the class }

Because an interface represents a contract between the client code and the class implementing the interface, when you extend an interface in a class, the class must provide method bodies for each of the method stubs in the interface denition.

Packages
Java source les are typically grouped into packages. Source les that are in the same package, or that import a package, have access to the objects and methods in that package. You can use a package statement to specify which package a source le belongs to. Package statements must occur on the rst line of the source code le and have the following syntax:
package <top_package>[.<sub_package>];

package: A collection of related classes.

For example, if you were creating a shipping application that had a group of les which dened the reporting capabilities of the application, you would include a source code le in the reports package with the following package statement:
package shipping.reports;

The path of the package hierarchy is specied using dot notation. Java also enables you to import packages into your source les. This means that your source code le can reference the objects and methods contained in an external packagethis is especially useful for including Javas API packages in your les. The syntax for importing a package is:
import <package_name>[.<sub_pkg_name>].<class_name>;. . .or import <package_name>[.<sub_pkg_name>].*;

106

Java 2 Programming for Developers

The second method enables your le to reference any class within the package. For example, you can include the java.util package in your source code with the following code:
import java.util.*;

Using the import statement to import an entire package rather than a specic class does not result in larger compiled les. When you compile source code that imports a package, the Java compiler identies and includes only those classes actually used in the source code. The Java Language Specication requires that the optional package and import statements (in that order) be included on the rst line of source code les.

Project Development
Developers often work on several projects at the same time. Therefore, it is important to create a logical directory and work structure to help keep track of your project les. Figure 3-12 shows a conventional Java development directory structure.

Figure 3-12: A sample development directory layout. In this example, the HRProj project is stored in the JavaProjects directory (as would be any other current projects). Within the HRProj directory, there are directories for the projects classes, docs, and source les. Inside of the class and src directories are folders that represent the Employee.domain, Employee.gui, and Employee.reporting packages. When the source les are compiled, they are compiled into the appropriate class les package and directory.

Lesson 3: Object-oriented Programming

107

TASK 3B-2:
Working with Java Packages
Objective: To compile les into packages and import packages into source les. 1. In Windows Explorer, create a directory structure that looks like the following:

2.

From the C:\077954 folder, move the HelloMsg.java source code le into the C:\JavaProjects\CurrentProj\src\Hello directory. Later in this activity youll compile this le into a package named Hello. From the C:\077954 folder, move PrintMsg.java source code le into the C:\JavaProjects\CurrentProj\src directory. Later in this activity, youll import the Hello package into this class le. In your text editor, open HelloMsg.java. The le contains a class with a single method, printGreeting() that prints a message to the console.
public class HelloMsg { public void printGreeting() { // Print the greeting to the screen System.out.println("Hello World!"); } }

3.

4.

5.

Add a package statement that includes this class le in a package named Hello.
package Hello; public class HelloMsg { public void printGreeting() { // Print the greeting to the screen System.out.println("Hello World!"); } }

6.

Save the le. In your text editor, open PrintMsg.java. The le contains a class with a main method that creates an instance of HelloMsg and calls its printGreeting() method.
public class PrintMsg { public static void main (String [] args) { HelloMsg myHello = new HelloMsg(); myHello.printGreeting(); } }

108

Java 2 Programming for Developers

7.

Add an import statement that will allow the class to access the HelloMsg class, which is located in the Hello package.
import Hello.*; public class PrintMsg { public static void main (String [] args) { HelloMsg myHello = new HelloMsg(); myHello.printGreeting(); } }

8.

In the MS-DOS console window, navigate to the C:\JavaProjects\ CurrentProj\src directory and compile the HelloMsg.java le into the class directory by typing: javac d ../class Hello/*.java.

9.

Compile the PrintMsg.java le into the class directory by typing javac d ../class *.java.

Lesson 3: Object-oriented Programming

109

10. Navigate to the class directory and run the PrintMsg.class program.

The PrintMsg class loads the Hello package, creates an instance of the HelloMsg class, and calls its printMessage() method. 11. What would happen if you removed the import Hello.*; statement from the PrintMsg class? The PrintMsg program would not compile because the compiler would not be able to locate the HelloMsg class referenced in the code.

Access Modifiers
Java class declarations can optionally include access modiers and an extends clause or an implements clause. Interface, eld variable, and method declarations may include access modiers. Access modiers control how other classes access the details of an objects or variables implementation. The following table illustrates the Java access modiers and their uses: Modier
public

Denition
Classes, interfaces, eld variables, and methods that are declared public can be accessed by any Java program without restrictions. Note that a programs main() method is declared public so that it can be accessed by any Java runtime environment. Variables, methods, constructors, and inner classes may be declared protected. Protected access indicates that an object can be accessed by members of the package in which it resides as well as subclasses of classes that are in the same package even if the subclasses reside in different packages. Variables, methods, constructors, and inner classes may be declared private. The private declaration indicates that the variable, method, or inner class can be used only by the class that declares the variable, method, or inner class. The private declaration is often used on eld variables of fully encapsulated classes to protect the variables from being modied by external classes and methods.

protected

private

110

Java 2 Programming for Developers

Modier
default (no access modier)

Denition
When a class, interface, eld variable, method, constructor, or inner class declaration does not include an access modier, it is given default (or friendly) access. Default access means that only classes that are in the same package as a given class, interface, variable, method, constructor, or inner class may access the object with default access.

Java programmers use access modiers to design encapsulated classes. Encapsulation makes applications easier to modify (because individual classes are unaware of the means by which data is manipulated in other classes) and extend. A fully encapsulated class has private eld variables that are manipulated through accessor methods. In the following simple example, the Car class has two elds: speed and gear. The elds are declared private so that they cannot be directly accessed by other classes. In order to set Cars elds, external classes must call Cars accessor methods. Also note that because the Car class has no access modier (it has default access), it can only be accessed by classes in the same package.
class Car { // Private Field Variables private int speed; private int gear; // Accessor methods used to set fields public void setSpeed(int x){ speed = x; } public void shiftUp() { gear = gear + 1; } public void shiftDown() { gear = gear - 1; } }
encapsulated classes: Classes that contain all of the elds and methods that enable the class to function. The elds in encapsulated classes are manipulated only by methods of the class.

Other Modifiers
The Java Language Specication also provides several other declaration modiers. These modiers are described in the following table: Modier
nal

Description
A nal variable is similar to a const variable in C++ or C#; once it is assigned a value, the value cannot be changed. Classes that are declared nal cannot be subclassed. A method that is declared nal cannot be overridden.

Lesson 3: Object-oriented Programming

111

Modier
abstract

Description
Classes and methods may be declared abstract. When a class is declared abstract it means that an instance of the class cannot be created (subclasses of an abstract class can be instantiated). Methods that are declared abstract do not contain method bodiesthe implementation of these methods is left to subclasses which override the abstract method. A class that contains abstract methods must also be declared abstract. Classes that inherit abstract methods must provide implementations of those methods. Methods and variables that are declared static belong to the class rather than instances of the class. For example, a class may contain a static variable that is incremented each time the class is instantiated. This variable is not part of the instances of the classit belongs to the class itself. Static methods, such as the main method, can be invoked before an instance of the class exists. The native modier can be applied to methods. This modier indicates that the method will implement code which exists outside of the JVM. The transient modier can be applied only to variables. Transient prevents variables from being stored as part of an objects persistent state. This prevents the transient variable (which often contains sensitive data) from being serialized.

static

native

transient

TASK 3B-3:
Access Modifiers
Objective: To demonstrate your knowledge of Javas access modiers. 1. Identify the illegal declaration. a. String str; b. public nal class MyClass { } c. static class MyClass extends AnotherClass { } d. protected int i; e. public static void main (String [] args) { } 2. Identify the true statement. a. Transient variables may not be serialized. b. Transient variables are always static. c. Transient methods must be overridden in subclasses. d. Transient classes may not be serialized. e. Transient methods cannot be overridden.

112

Java 2 Programming for Developers

3.

What change to the following code would make the class fully encapsulated?
class SpeedMeter { int speed; public void setSpeed(int x){ speed = x; } public int getSpeed() { return speed; } }

a. Declare the class public. b. Import the speedMeter package. c. Declare the speed eld to be private. d. Make the setSpeed and getSpeed methods private. 4. Which access modier provides the highest level of protection? a. private b. default (no modier) c. protected d. public 5. Which modier is equivalent to the C++ or C# const modier? a. transient b. native c. volatile d. nal e. synchronized

Abstraction
Classes allow you to develop software quickly by hiding the details of how the developer of the class actually coded or implemented it. It makes the class appear as a component or building block that you can plug in or assemble. When you use a building block, you do not worry about the manufacturing process or about who the suppliers of the raw material were. You just use it. Once a class is built, you do not have to know how it was built and what the code is in order to use it. This concept of hiding details is called abstraction. Your responsibility is to discover the methods (the method name, the purpose, the parameters with datatypes, and the return type) and the properties (the name and the datatype) of the class. Armed with just this information, you can use the class with no need whatsoever to look at the code that the developer of the class used within the body of the methods. You encounter abstraction in every aspect of your life. Abstraction is used to deal with complexity without getting lost in it. When you call customer service at a company that made your toaster that is now broken, you do not concern yourself about who they consult to determine their response, what clothes they are wearLesson 3: Object-oriented Programming 113

abstraction: The concept of hiding the details of the implementation by focusing exclusively on the denition of the communications interface.

ing, what kind of desks they sit at, what the color of the carpet is, and so on. You are only concerned about the communications interface between you and the customer service representative, so that your toaster gets xed. Most signicantly, you are not concerned about the specics of the process that the other person goes through to resolve the problem. When you go to an automobile dealer to purchase a car, you ask for a car. You do not ask for the car part by part. When you ask for a car, you get all the parts that have been installed to produce an operational car. The word car hides the details about the thousands of parts and the process that was used to assemble those parts. Classes in Java are also based on abstraction. Developers are only concerned with the denition or contract that species the characteristics (methods and properties). You do not have to concern yourself with the implementation and how the class implements these characteristics (behaviors and properties).

Keywords: this and super


The this keyword enables you to access local variables from within a local method. Consider the following class:
public class Employee { private int empNum = 0; private int salary = 0; public AnEmployee(int empNum, int salary){ this.empNum = empNum; this.salary = salary; } }

When a class calls the AnEmployee method, it passes the int variable empNum and salary into the method. The method uses the this keyword to set the value of the local empNum and salary variables to the value of the parameters passed into the method. The super keyword is used in a class to refer to its superclass (or parent class). In addition, super can be used to refer to a parent classs constructor.

114

Java 2 Programming for Developers

TASK 3B-4:
Using Inheritance
Objective: To sub-class an existing class to make use of its properties and methods. 1. In your text editor, open C:\077954\Employee.java. The le contains an encapsulated class the represents a very simple employee object.
class Employee { //Employee Class Fields private String name; private int salary;
This class does not contain a constructor. Youll learn about constructors in the next section.

// Employee Class Accessor Methods public void setName(String name){ this.name = name; } public void setSalary(int salary){ this.salary = salary; } public String getData(String name){ return "Name: "+ this.name + "\n" + "Salary: " + this.salary; } }

The employee object has two private elds, name and salary and accessor methods to set the eld values and display the contents of the elds. You may also notice that the accessor methods use the this keyword to indicate that the code sets the value of the elds contained in each individual instance of the class. 2. In another text editor window, open C:\077954\StartEmployee.java. The StartEmployee class contains a main methodthe starting point of the application. The main method creates a new instance of the Employee class and calls several of its methods using parameters entered at the command line.
class StartEmployee { // Entry Point for the Application public static void main(String args[]){ String name = args[0]; int salary = Integer.parseInt(args[1]); Employee emp = new Employee(); emp.setName(name); emp.setSalary(salary); System.out.println(emp.getData(name)); } }

Lesson 3: Object-oriented Programming

115

You may also notice that both the StartEmployee and Employee class declarations are not preceded by an access modier. This means that both classes have default access and are included in the default package. 3. 4. Start a new, blank source code le. Youll create a Manager class that inherits all of the properties and methods of the Employee class. To declare a class that extends the Employee class, type:
class Manager extends Employee { }

5.

To add an additional eld to the Manager class, type:


class Manager extends Employee { private String dept; }

6.

Next, add an accessor method for the dept eld.


class Manager extends Employee { private String dept; public void setDept(String dept) { this.dept = dept; } }

7.

Finally, create a method that displays the managers data. Youll use the super keyword to access Employees getData method.
class Manager extends Employee { private String dept; public void setDept(String dept) { this.dept = debt; } public String getData(String name){ return super.getData(name) + "\nDepartment: " + dept; } }

Save the class as Manager.java. 8. Switch back to the StartEmployee.java source code le. Change the class name to StartManager and save the le as StartManager.java. Youll use the new le as an entry point to the application that sets the managers data. In the main method, add a statement that gets the third element of the args[] array and assigns it to a String called dept. This eld represents the managers department.
public static void main(String args[]){ String name = args[0]; int salary = Integer.parseInt(args[1]); String dept = args[2];

9.

116

Java 2 Programming for Developers

10. Change the new Employee declaration so that it creates a new Manager object called man and change the emp method calls so that they are calls to the man objects methods.
Manager man = new Manager(); man.setName(name); man.setSalary(salary);

11. Add a new statement that sets mans dept eld.


man.setDept(dept);

12. Modify the println method call so that it displays the man data.
System.out.println(man.getData(name));

13. Save the StartManager.java le. Switch to the Command Prompt window. 14. The StartEmployee program has been compiled for you. Test the StartEmployee application by typing:
C:\077954>java StartEmployee Jones 32000

The StartEmployee class initializes the Employee class and calls its methods.

15. Next, compile and test the StartManager application by typing:


C:\077954>javac StartManager.java C:\077954>java StartManager Smith 52000 Accounting

The StartManager class initializes the Manager class and calls its methods. Because the Manager class is a subclass of Employee, it loads the Employee

Lesson 3: Object-oriented Programming

117

class and uses its properties and methods.

Polymorphism
Like other object-oriented languages, Java allows you to refer to an object with a variable that belongs to a parent class. For example, the following code is a legal declaration because the Manager class is a subclass of employee:
Employee employee = new Manager();

Given this declaration, the employee variable can only access the portions of the Manager class that are derived from the Employee class. Essentially, this code indicates that employeevariable of type Employee actually refers to a Manager object.

Topic 3C
Overloading and Overriding
Every method has a signature. The signature for a method is comprised of the name of the method, the number of arguments, and the datatype of the arguments. The signature of each and every method must be unique within a Java class.
signature of a method: The name of the method, the number of arguments, and the datatype of the arguments.

118

Java 2 Programming for Developers

Method Overloading
For most methods, the uniqueness of method signatures is accomplished by using different method names. However, you can declare multiple methods with the same name within a class and ensure the uniqueness of signatures by declaring a different number of arguments or by declaring a unique sequence of argument datatypes for those methods that share a common name. The use of methods with the same name is referred to as method overloading. When you invoke an overloaded method, the Java compiler determines which one of the overloaded methods it should use based on the number and sequence of arguments that you are passing in.
method overloading: Declaring multiple methods with the same name and ensuring uniqueness of signature by declaring a different number of arguments or by declaring a unique sequence of argument datatypes.

TASK 3C-1:
Declaring and Using Overloaded Methods
1. Open Notepad and create a class called Rectangle.
class Rectangle } {

2.

Add a method called area. This method responds to invocations with no arguments.
class Rectangle {

void area() { System.out.println("Method 1: I need more information to calculate the area!"); } }

3.

Add a second method also called area. This method overloads the rst area method. It responds to invocations with a single argument of type double. This method is intended for specifying a square.
class Rectangle {

void area() { System.out.println("Method 1: I need more information to calculate the area!"); } void area(double side) { double x = side * side; System.out.println("Method 2: A square with an area of " + x); } }

4.

Add a third method called area. This method overloads the area method. It responds to invocations with
Lesson 3: Object-oriented Programming 119

two arguments, both of type double. This method is intended for specifying a rectangle.
class Rectangle {

void area() { System.out.println("Method 1: I need more information to calculate the area!"); } void area(double side) { double x = side * side; System.out.println("Method 2: A square with an area of " + x); } void area(double height, double width) { double x = height * width; if (height == width) System.out.println("Method 3: A square with an area of " + x); else System.out.println("Method 3: A rectangle with an area of " + x); } }

5. 6.

Save the le as Rectangle.java. In Notepad, open a new le and create a class called OverloadMethods.
class OverloadMethods { public static void main(String[] args) { } }

7.

Add the following invocations of the overloaded method called area.


class OverloadMethods { public static void main(String[] args) { Rectangle r = new Rectangle(); System.out.println("\nStep 1: Invoking r.area()..."); r.area(); System.out.println("\nStep 2: Invoking r.area(10)..."); r.area(10); System.out.println("\nStep 3: Invoking r.area(10.0, 6.0)..."); r.area(10.0, 6.0); } }

120

Java 2 Programming for Developers

8.

Save the le as OverloadMethods.java. Compile and run the class le.

9.

Observe Step 1 of the output. You invoked area with no arguments. As expected, method 1 was invoked. Recall that method 1 was designed for method invocations with no arguments.

10. Observe Step 2 of the output. You invoked area with one argument of datatype integer. Of the four area methods, only method (2) was designed with one argument. Accordingly, method 2 was invoked. Recall that method 2 was designed for method invocations with one argument of datatype double, to determine the area of a square. Even though you invoked it with an integer (10), the Java compiler converted the integer to a double (10.0). 11. Observe Step 3 of the output. You invoked area with two arguments, both of datatype double. The third method was designed for two arguments. If these two numbers were equal, the rst branch of the if/else structure would have been executed.

Overriding Methods
You can override a parent class method by declaring a method in a subclass with the same name and signature as a method in the parent class. Consider the following parent class:
class Animal { public void eat() { // code that gets an animal to eat } }
overriding methods: Declaring a method with the same name and signature as the parent classs method, thereby hiding the parent classs method.

A Mammal class that extends Animal (inherits its properties and methods) might logically override the Animal class eat() implementation with an eating method that is specic to mammals. Heres the code for the Mammal class whose eat() method overrides the parent classs eat() method.
Lesson 3: Object-oriented Programming 121

class Mammal extends Animal { public void eat() { // code that gets a Mammal to eat } }

Inheritance gives your classes access to all the methods and properties of the parent classesall the way to the top-level class. When you refer to a method name, the runtime engine rst looks for the method within that class, then goes up one level and searches for that method name, then goes up another level, and so on. Once it nds a method, it stops searching and executes the method. By overriding a method that exists in a parent class, the search for that method is limited to that class and the parent classs method is never seen. This is also described as method hiding. There may be situations in which you want to use a parent class methodeven though it may have been overridden in a subclass. To accomplish this, you can use the super keyword. For example, in the Mammal class described above, you could create a Mammal object that uses the Animal classs eat() method with the following code:
//Create a Mammal Mammal dog = new Mammal; //Within the dog context, get //the dog to eat like an Animal super.eat();

TASK 3C-2:
Overriding a Method
Objective: To create a subclass that overrides a parent class method. Setup: Task 3C-1 has been completed. 1. If necessary, open the Rectangle.java source code le. You created this le in the previous activity. Observe the classs second area method.
class Rectangle {

void area() { System.out.println("Method 1: I need more information to calculate the area!"); } void area(double side) { double x = side * side; System.out.println("Method 2: A square with an area of " + x); }

122

Java 2 Programming for Developers

void area(double height, double width) { double x = height * width; if (height == width) System.out.println("Method 3: A square with an area of " + x); else System.out.println("Method 3: A rectangle with an area of " + x); } }

Youll create a subclass of Rectangle that overrides the second area method to calculate the area of a circle. 2. In a new, blank text le, declare a class, called Circle, that extends Rectangle.
class Circle extends Rectangle { }

3.

Override the single parameter area method so that it uses an approximate value of Pi (3.14) to calculate the area of a circle. Youll pass the circles radius to the method.
class Circle extends Rectangle { void area(double radius){ double x = radius * 3.14; System.out.println("Circle's Area: " + x); } }
Later in this course, youll learn how to use the java. math reference for Pi.

Lesson 3: Object-oriented Programming

123

4.

Save the le as Circle.java. Open C:\077954\Overrides.java and observe its contents. The le contains the entry point for an application that calculates the area of a circle. The application accomplishes this by getting a value from the command line, converting it to a double, and constructing a new circle object and calling the circles single-parameter area method. Although Circle inherits its methods from Rectangle, Circle overrides the single-parameter area method to calculate the area of a circle rather than a square.
class Overrides{ public static void main(String [] args){ double circumference = Double.parseDouble(args[0]); Circle c = new Circle(); c.area(circumference); } }

5.

Close the le. Switch to the Command Prompt window, compile, and test the application with a value of 4.2.

Topic 3D
Constructors
Constructors are groups of Java statements that enable initialization of object states when the object is instantiated using the keyword new. In other words, constructors enable automatic initialization of objects when they are instantiated.
constructor: A group of Java statements that enables initialization of the object state when the object is instantiated using the keyword new.

You specify constructors much like you do methods and, like you did for methods, you can specify zero, one, or more arguments. Constructors without arguments are called no-arg constructors. You must name constructors the same name as the class that they initialize. However, keep in mind that constructors are not methodsthey cannot return values, and you do not specify the return type in the declaration (not even the return type void). For example, lets consider the class Rectangle. Lets say you want to specify a constructor for this class that initializes the height to 5.0 and the width to 10.0 when you do not specify the size. The code is:

124

Java 2 Programming for Developers

class Rectangle { double height, width; Rectangle () { height = 5.0; width = 10.0; } }

You can instantiate an object of the Rectangle class using the following code:
Rectangle r = new Rectangle();

The keyword new species that you are creating a new object. After the Rectangle object is created, the constructor is invoked, which sets the instance variable length to 20 and the instance variable width to 10. Constructors cannot be abstract, static, or nal. Since instantiation of an object results in invoking the constructor, it cannot be abstract. Since it initializes objects, it cannot be static. Since you cannot inherit constructors, there will never ever be a need to make the constructor nal.

TASK 3D-1:
Specify a Constructor
Objective: To create a constructor for an existing class. Setup: Task 3C-2 has been completed. 1. In your text editor, open Employee.java. You created the Employee class in an earlier activity. Before the accessor methods, add a constructor that instantiates Employees elds.
class Employee{ //Employee Class Fields private String name; private int salary; Employee(String name, int salary){ this.name = name; this.salary = salary; }

In this case, the constructor does the same thing as the accessor methods. However, by using a constructor you create the object and initialize its elds in a single step. 2. 3. Save and close the le. Open StartEmployee.java. Modify the code that creates the new Employee object so that it passes the name and salary variables to the constructor.
Employee emp = new Employee(name, salary);

Because you added a constructor to the Employee class, the JVM will use
Lesson 3: Object-oriented Programming 125

your constructor to initialize the class elds rather than the default constructor. 4. Delete the calls to the setName and setSalary methods. The remaining code should look like this:
class StartEmployee { //Entry Point for the Application public static void main (String args[]) { String name = args[0]; int salary = Integer.parseInt(args[1]); Employee emp = new Employee(name, salary); System.out.println(emp.getData(name)); } }

5.

Save and compile the le. Run the application with two parameters: Johnson and 76000. Your output should look like the following graphic:

6.

In your text editor, open Manager.java and add a constructor that instantiates Managers elds.
class Manager extends Employee { private String dept; Manager(String name, int salary, String dept){ super(name, salary); this.dept = dept; }

The manager constructor uses the super keyword to call its parent classs (Employee) constructor. Save and close the le. 7. Open StartManager.java and modify the code that creates the new Manager object so that it passes the name, salary, and dept variables to the constructor.
Manager man = new Manager(name, salary, dept);

126

Java 2 Programming for Developers

8.

Delete the calls to the setter methods.


Manager man = new Manager(name, salary, dept); man.setName(name); man.setSalary(salary); man.setDept(dept);

9.

Save, compile, and run the program with three parameters: Jones, 78000, and Accounting. Your output should look like the following graphic:

Default Constructor
As youve seen, if you do not explicitly specify a constructor within a class, Java will create a default no-arg constructor. Once you specify a constructor, Java will not create a default no-arg constructor for you. If you also want a no-arg constructor when you specify a constructor with arguments, you must explicitly specify both constructors. The default constructor has the same access modier as the class that it initializes. For example, the default constructor is public, if the class is public. Lets consider the following class. In this case, you are not specifying a constructor. Java creates a default constructor for you.
class Rectangle { double height, width; }

You can instantiate an object of the Rectangle class using the following code:
Rectangle r = new Rectangle();

The keyword new species that you are creating a new object. After the Rectangle object is created, the default constructor is invoked, which sets both the instance variables height and width to 0.0.

Lesson 3: Object-oriented Programming

127

TASK 3D-2:
Using the Default Constructor
1. In your text editor, open Rect.java. The le contains a class that represents a rectangle. The class has two elds, height and width, a main method, and an additional method that returns the area of the rectangle.
class Rect { double height, width; public static void main(String [] args){ System.out.println("Height: " + rect.height + "Width: " + rect.width); } double area(){ return height * width; } }

2.

On the rst line of the main method, add a line that instantiates a new instance of the Rect class.
public static void main(String [] args) { Rect rect = new Rect(); System.out.println("Height: " + rect.height + "Width: " + rect.width);

In this class, the main method that instantiates a new instance of the class is included in the class rather than in a separate class, as youve seen before. Because the Rect class does not have a constructor, when the JVM constructs the class it will instantiate the class variables to their default values. 3. Save, compile, and execute the le. The default values of the elds are displayed.

128

Java 2 Programming for Developers

Overloading Constructors
You can overload constructors just like you overloaded methods. The signature of a constructor is the number of arguments and the sequence of argument datatypes. You can specify as many constructors as you need within a class, as long as each constructor has a unique signature. For example, lets consider the class Rectangle that you reviewed in the last topic. Lets say you want to specify a second constructor for this class that enables you to specify the initial length and the width for the object you are creating.
class Rectangle { double height, width; Rectangle () { height = 5.0; width = 10.0; } Rectangle (int x, int y) { length = x; width = y; } }

overloading constructors: Specifying many constructors in one class with different signatures.

You can instantiate an object of the Rectangle class using the following code:
Rectangle r = new Rectangle();

The no-arg constructor is invoked, which sets the instance variable height to 5.0 and the instance variable width to 10.0. You can instantiate an object of the Rectangle class and specify the initial values using the following code:
Rectangle r = new Rectangle(30, 25);

The constructor with two integer arguments is invoked, which sets the instance variable length to 30 and the instance variable width to 25.

Lesson 3: Object-oriented Programming

129

TASK 3D-3:
Using Overloaded Constructors
1. In your text editor, open Rect2.java. The class encapsulates a simple rectangle object.
class Rect2 { double height, width; Rect2(){ height = 5.0; width = 10.0; } double area(){ return height * width; } }

2.

Add a second constructor that takes one argument of datatype double. The names of the constructors are the same as the class, so you will have two constructors that are overloaded.
class Rect2 { double height, width; Rect2(){ height = 5.0; width = 10.0; } Rect2(double side) height = side; width = side; } {

double area(){ return height * width; } }

3.

Add a third constructor to this class. This constructor takes two arguments, both of datatype double.
class Rect2 { double height, width; Rect2(){ height = 5.0; width = 10.0; } Rect2(double side) height = side; width = side; {

130

Java 2 Programming for Developers

} Rect2(double ht, double wi) { height = ht; width = wi; } double area(){ return height * width; } }

4.

Save Rect2.java. Open StartRect2.java. This le contains the main method that will call Rect2s constructors. Add a call to the constructor that has no parameters. Use the rectangles area method to display the rectangles area.
class StartRect2 { public static void main(String [] args) { Rect2 r1 = new Rect2(); System.out.println("r1 has a height of " + r1.height + ", a width of " + r1.width + ", and an area of " + r1.area()); } }

5.

Add a call to the constructor that uses a single parameter. Print out a status message.
class StartRect2 { public static void main(String [] args) { Rect2 r1 = new Rect2(); System.out.println("r1 has a height of " + r1.height + ", a width of " + r1.width + ", and an area of " + r1.area()); Rect2 r2 = new Rect2(10.0); System.out.println("r2 has a height of " + r2.height + ", a width of " + r2.width + ", and an area of " + r2.area()); } }

Lesson 3: Object-oriented Programming

131

6.

Finally, add a call to the constructor that takes two parameters.


class StartRect2 { public static void main(String [] args) { Rect2 r1 = new Rect2(); System.out.println("r1 has a height of " + r1.height + ", a width of " + r1.width + ", and an area of " + r1.area()); Rect2 r2 = new Rect2(10.0); System.out.println("r2 has a height of " + r2.height + ", a width of " + r2.width + ", and an area of " + r2.area()); Rect2 r3 = new Rect2(10.0, 6.0); System.out.println("r3 has a height of " + r3.height + ", a width of " + r3.width + ", and an area of " + r3.area()); } }

7.

Save, compile, and execute the code. The application uses all three of Rect2s constructors to create rectangle objects.

Topic 3E
Inner Classes
An inner class is a class that is declared within the specication of another class. In other words, an inner class is dened within the opening and closing curly braces of another class denition.
inner class: A class that is declared within the specication of another class. In other words, it is dened within the opening and closing curly braces of another class denition.

Inner classes offer a number of benets: The enclosing class provides a boundary for the namespace, so that the overall namespace is freed up to use the name of the inner class for other classes. You can limit the scope for using the methods of the inner class to just the enclosing class.

132

Java 2 Programming for Developers

You dene behavior for the enclosing class, within the context of the enclosing class. Static inner classesInner classes dened with the keyword modier static. Static inner classes have access to the static members of the enclosing class, even to those that are private. They do not have implicit reference to members of the instances of the enclosing class. Member inner classesInner classes that are declared without the keyword modier static. Inner classes can access all the members of the enclosing class, even if they are protected or private. Local inner classesInner classes that are specied within a method denition of the enclosing class. The local inner class cannot be declared as static, public, protected, or private. Local inner classes can access local variables that are specied as nal. Anonymous inner classesLocal inner classes that do not have a class name. You would use this class when you need to use it just once and not again. Since this class does not have a name, you cannot specify constructors either. Anonymous inner classes can access local variables that are specied as nal.

You can dene four types of inner classes:

TASK 3E-1:
Using Inner Classes
1. Open a new le in your text editor and dene the enclosing class OutClass. Save the le as InnerClasses.java.
class OutClass {

2.

Dene a property outX for OutClass.


class OutClass { String outX = "'This is outX'"; }

Lesson 3: Object-oriented Programming

133

3.

Dene a method showOutVars for OutClass.


class OutClass { String outX = "'This is outX'"; void outShowVars() { InClass ic = new InClass(); System.out.println("\nInside outShowVars... " + "outX contains " + outX); System.out.println("Inside outShowVars... " + "inX contains " + ic.inX); ic.inShowVars(); } }

4.

Dene a class InClass within the class OutClass.


class OutClass { String outX = "'This is outX'"; void outShowVars() { InClass ic = new InClass(); System.out.println("\nInside outShowVars... " + "outX contains " + outX); System.out.println("Inside outShowVars... " + "inX contains " + ic.inX); ic.inShowVars(); } class InClass {

} }

5.

Dene a property inX within the class InClass.


class OutClass { String outX = "'This is outX'"; void outShowVars() { InClass ic = new InClass(); System.out.println("\nInside outShowVars... " + "outX contains " + outX); System.out.println("Inside outShowVars... " + "inX contains " + ic.inX); ic.inShowVars(); } class InClass { String inX = "'This is inX'"; } }

134

Java 2 Programming for Developers

6.

Dene a method inShowVars within the class InClass.


class OutClass { String outX = "'This is outX'"; void outShowVars() { InClass ic = new InClass(); System.out.println("\nInside outShowVars... " + "outX contains " + outX); System.out.println("Inside outShowVars... " + "inX contains " + ic.inX); ic.inShowVars(); } class InClass { String inX = "'This is inX'"; void inShowVars() { System.out.println("\nInside inShowVars... " + "outX contains " + outX); System.out.println("Inside inShowVars... " + "inX contains " + inX); } } }

7.

Dene a class InnerClasses to test the classes you built by invoking outClass.
class InnerClasses { public static void main(String[] args) {

} } class OutClass { String outX = "'This is outX'"; void outShowVars() { InClass ic = new InClass(); System.out.println("\nInside outShowVars... " + "outX contains " + outX); System.out.println("Inside outShowVars... " + "inX contains " + ic.inX); ic.inShowVars(); } class InClass { String inX = "'This is inX'";

Lesson 3: Object-oriented Programming

135

void inShowVars() { System.out.println("\nInside inShowVars... " + "outX contains " + outX); System.out.println("Inside inShowVars... " + "inX contains " + inX); } } }

8.

Instantiate OutClass and invoke its outShowVars method.


class InnerClasses { public static void main(String[] args) OutClass oc = new OutClass(); oc.outShowVars(); } } class OutClass { String outX = "'This is outX'"; void outShowVars() { InClass ic = new InClass(); System.out.println("\nInside outShowVars... " + "outX contains " + outX); System.out.println("Inside outShowVars... " + "inX contains " + ic.inX); ic.inShowVars(); } class InClass { String inX = "'This is inX'"; void inShowVars() { System.out.println("\nInside inShowVars... " + "outX contains " + outX); System.out.println("Inside inShowVars... " + "inX contains " + inX); } } } {

136

Java 2 Programming for Developers

9.

Save, compile, and run InnerClasses.

10. Observe the output. You can access both outX and inX from within the OutClass method outShowVars(). You can access both outX and inX from within the InClass method inShowVars(). 11. Delete the reference to the instance ic when you print ic.inX. The characters to be deleted are grayed-out in the following code:
class InnerClasses { public static void main(String[] args) OutClass oc = new OutClass(); oc.outShowVars(); } } class OutClass { String outX = "'This is outX'"; void outShowVars() { InClass ic = new InClass(); System.out.println("\nInside outShowVars... " + "outX contains " + outX); System.out.println("Inside outShowVars... " + "inX contains " + ic.inX); ic.inShowVars(); } class InClass { String inX = "'This is inX'"; void inShowVars() { System.out.println("\nInside inShowVars... " + "outX contains " + outX); System.out.println("Inside inShowVars... " + "inX contains " + inX); } } } {

Lesson 3: Object-oriented Programming

137

12. Save and compile the code.

13. Observe the error. OutClass outShowVars() method does not have implicit access to InClasss inX property. You must refer to the instance ic when you access inX as follows:
ic.inX

Summary
In this lesson, you explored the object-oriented principles that make Java such a powerful and adaptable programming language. You declared and instantiated classes using Javas access modiers and other modier keywords. You used method overriding and overloading. You also wrote constructors and used Javas default constructors. Finally, you explored Javas inner classes.

Lesson Review
3A List three benets of using methods to build software.
Any three of the following are correct: reusability, productivity, modularity, and minimizing the impact of making changes to the code. Discuss the differences between objects and primitive values that are passed into methods. Because objects are passed by reference into methods, changes to the object that occur within the method will not be reected to the object outside of the method. Because primitive variables are passed by value as method arguments, changes that are made to the variable within the method will be reected in the variables value outside of the method.
138 Java 2 Programming for Developers

3B Discuss some of the advantages of developing encapsulated classes.


Answers will vary, but should include: Encapsulated classes make application modication much easier. Encapsulated classes provide a conceptual framework for designing classes. Encapsulated classes may be easier to develop because they are often modeled after real-world objects. Encapsulated classes protect class variables from being unintentionally manipulated by other classes.

Discuss the importance of inheritance in Java programming. Answers will vary, but should include a discussion of developing prototype parent classes, the time-savings resulting from extending existing classes, and the advantages of code reuse.

3C What is the signature of a method?


A signature of a method is comprised of the method name, the number of arguments, and the sequence of argument datatypes. Java requires you to have methods with unique signatures within a class. What does it mean to overload a method? Overloading a method is the use of methods with the same names but with uniqueness of signature. In other words, even though they have the same name, they can be distinguished either by having a different number of arguments or a different sequence of argument datatypes.

3D What is a constructor?
A constructor is a programming tool that enables Java to initialize instance property values when creating new instances.

3E Describe some of the key benets of inner classes.


Inner classes provide a boundary for the namespace of the inner class, so that the overall namespace is freed up to use the name of the inner class for other classes, limit the scope for using the methods of the inner class to just the enclosing class, and enable you to dene behavior for the enclosing class within the context of the enclosing class.

Lesson 3: Object-oriented Programming

139

140

Java 2 Programming for Developers

Exception Handling and Garbage Collection


Overview
Exceptions are Java mechanisms that allow programmers to anticipate and handle errors in their programs. Even the most well-conceived programs have the potential to cause an error. In this lesson, you will learn what exceptions are and how they relate to your Java programs. You will also learn how to handle errors by writing exception handlers. Finally, you will examine garbage collection, the process by which Java automatically clears memory space.

LESSON

4
Data Files Exception.java ExceptionDemo.java Lesson Time 1 hour, 30 minutes

Objectives
To learn about the exception handling mechanism in Java, you will: 4A Dene and discuss the meaning of exceptions in Java. Before you can begin to handle exceptions, you need to learn what exceptions are and how they relate to the Java programming language. 4B Write exception handlers. Writing efficient exception handlers will increase the reliability of your programs. A typical size program will usually involve writing several exception handlers. They may seem cumbersome at rst, but after a while you will begin to realize their value. 4C Explore the garbage collection system in Java. Java has a sophisticated garbage collection system that frees memory taken by objects once they are no longer being referenced. Since garbage collection is automatic, you do not have to worry about memory management.

Lesson 4: Exception Handling and Garbage Collection

141

Topic 4A
Overview of Exceptions
The lifecycle of a program is usually straightforward. The program starts, does some computations, and then exits. When program execution goes according to plan, everyone is happy. But what if something goes wrong? How does the program behave? Here are a few possibilities: The program could shut down abnormally. The program could display an error message. The program could recover from the error and proceed without any noticeable effects on the users experience.

Depending on the situation, any of the above possibilities may be appropriate when an error occurs. Unfortunately, writing extra code to handle errors can be both time consuming and annoying. Where in your program are errors possible? How will you be notied of the error? When an error occurs, what kind of an error is it? How should you handle the error? Java answers all of these questions with a mechanism called exceptions.

What are Exceptions?


Exceptions are events that are triggered because something abnormal has happened during program execution. People sometimes associate exceptions with fatal errors. While this is sometimes true, exceptions usually result from minor errors that can be recovered from with one or two lines of additional code. Regardless of whether the error is fatal or not, when an exception occurs, the following conditions are true: Something abnormal has occurred. Normal execution cannot continue until the exception is handled. Exceptions are represented by objects that are instances of the Exception class (or a subclass of the Exception class). These exception objects contain information about what went wrong in the system. When an error occurs, one of these exception objects is created and thrown.

exception: An event that is triggered because something abnormal happens during execution of a program. When such an event occurs, program execution is immediately halted and control is passed to an exception handler.

fatal error: An error from which recovery is not possible.

Throwing Exceptions
The process of triggering an exception in Java is called throwing an exception. An exception can be thrown at any time from within a method by using the keyword throw. The following code illustrates this:
// create an Exception object Exception e = new Exception(); // throw the exception throw e;

142

Java 2 Programming for Developers

When an exception is thrown, normal execution is immediately halted and control is diverted, as shown in Figure 4-1.
Normal Program Execution Being Interrupted by an Exception

Figure 4-1: Normal program execution being interrupted by an exception getting thrown. Now that an exception has been thrown, there needs to be a way to catch it.

Catching Exceptions with Exception Handlers


Just as exceptions can be thrown, they can also be caught. Catching exceptions is the job of exception handlers. An exception handler is not an object, but rather a special block of code whose purpose is to catch an exception, deal with it, and attempt to return the program to normal execution. How the exception handler does this is up to the programmer and will depend on the situation. Exception handlers are dened using try, catch, and finally blocks.

The try Block


Code that has a potential for throwing exceptions should be placed within a try block:
try { // place code that might throw // an exception here }

exception handler: A block of code whose purpose is to catch an exception, deal with it, and return the program to normal execution.

try, catch, nally: Blocks of code used to dene an exception handler.

When the JVM encounters a try block it will execute the code contained within the block until the code throws an exception. If the code does not throw an exception it will be executed normally.

The catch Block


Every try block needs at least one catch block immediately following it. Within a catch block, you place code that will handle an exception, if one gets thrown. If no exception gets thrown, the code in the catch block will not get executed. The following code illustrates a catch block:

You can think of the try block as trying to execute some code to see if it throws an exception.

Lesson 4: Exception Handling and Garbage Collection

143

catch ( Exception ex ) { // place code to handle // exception here }

A catch block is special in that it takes a parameter, almost in the same way that a method takes a parameter. This parameter species the type of exception that the catch block is willing to catch. Within the catch block, you can obtain information about the exception by accessing the exception object that gets passed into the catch block. In the code example above, the catch block species that it is willing to accept any exception object that is an instance of the Exception class. Since almost all exceptions extend the Exception class, this catch block will catch almost any exception. A catch block can also declare that it only wants to catch a specic type of exception. For example, the following catch block will only catch I/O exceptions.
I/O stands for input/output and is most commonly associated with reading and writing les.

catch ( IOException ex ) { // place code to handle // IO exceptions here }

You can also place multiple catch blocks after a try block. This is useful, if the code in the try block has a potential for throwing several different types of exceptions:
catch ( FileNotFoundException ex ) { ... } catch ( EOFException ex ) { ... } catch ( PrinterException ex ) { ... }

EOF exceptions are End Of File exceptions.

When an exception is thrown, the catch blocks are examined (from top to bottom) to see which one was declared to be able to handle the specic type of exception that got thrown. The rst catch block that meets the criteria gets executed. The remaining catch blocks are ignored, even if they could also handle the exception.

The finally Block


Optionally, exception handlers may include a finally block immediately after the last catch block. Any code placed within the finally block will get executed no matter what, whether an exception gets thrown or not. This block is used for cleanup purposes, such as closing any open les or other resources you may have had open prior to the exception getting thrown. The syntax of a finally block is shown below:
finally { // place code here that you // need executed regardless // of whether an exception is // thrown or not }

A Complete Exception Handler


The following code segment illustrates a exception handler. It combines a try block with several catch blocks and a finally block:
144 Java 2 Programming for Developers

try { ... } catch ( ... } catch ( ... } catch ( ... } finally ... }

FileNotFoundException ex ) {

EOFException ex ) {

PrinterException ex ) {

Figure 4-2 illustrates the exception handlers control ow.


control ow: The order in which statements, or blocks of statements, are executed within a program.

Control Flow of an Exception Handler

Figure 4-2: Control ow of an exception handler. If an exception occurs within a try block, code from only one catch block will be executed, and then code from the finally block will be executed. If no exceptions get thrown, then the catch blocks are ignored and the code in the finally block will be executed.

Exception Handling: A Requirement in Java


Youve just seen how exception handlers catch exceptions and attempt to handle them. This mechanism helps to avoid, or at least recover from, potential errors in your programs. Because of this, exception handling is required in the Java programming language. This requirement is enforced by the Java compiler.
Lesson 4: Exception Handling and Garbage Collection 145

Typically, a method is dened like this:


public void someMethod() { ... }

However, if anywhere within the method, an exception has a potential of being thrown, that method must do one of two things: Include an exception handler to catch the exception. The method needs to declare that itself has a potential for throwing an exception.

If the method does neither, the compiler will refuse to compile the code. When you try to compile, you will see an error message like the one shown in Figure 4-3.

Figure 4-3: The Java compiler refusing to compile a program because an exception is not being caught.

Including an Exception Handler


As mentioned before, there are two ways to x a compilation error similar to the one shown in Figure 4-3. The rst is to include an exception handler within the method. This involves wrapping the exception-throwing lines of code in try and catch blocks:
public void someMethod() { try { // place exception-throwing code here } catch ( Exception e ) { // handle the exception } }

The Java compiler will tell you which line(s) of code might throw an exception.

This is the most general exception handler, as it will catch all types of exceptions.

146

Java 2 Programming for Developers

Declaring that a Method Might Throw an Exception


The other way to avoid a compilation error similar to the one shown in Figure 4-3 is to have the method declare that it might throw an exception. This is done using the keyword throws and is placed in the method declaration:
public void someMethod() throws Exception { ... }

throw and throws are two different keywords in Java. Dont get them confused!

The method can also declare the specic type of exception that it will throw, for example, an IOException:
public void someMethod() throws IOException { ... }

The advantage to using the throws keyword is that the compiler will now compile your code without requiring you to write an exception handler. The disadvantage is that any other method which calls someMethod() will be forced to catch the exception that someMethod() chose not to catch or declare that it, too, might throw an exception.

TASK 4A-1:
Following the Control Flow of an Exception Handler
1. Observe the following code:
//Method a public void a(int x) { try { b( x ); System.out.println( } catch ( IOException e System.out.println( } catch ( Exception e ) System.out.println( } finally { System.out.println( } }

While the Java compiler will allow you to use the throws keyword, it is not a good idea to use it every time the compiler informs you that an exception might be thrown. This is almost equivalent to using to having no exception handling at all.

"1" ); ) { "2" ); { "3" );

"4" );

//Method b public void b(int x) throws IOException { if ( x == 0 ) { IOException error = new IOException(); throw error; } System.out.println( "5" ); }

Lesson 4: Exception Handling and Garbage Collection

147

2.

What would the output be from executing the following method call?
a(1);

The output would be:


5 1 4

3.

What would the output be from executing the following code?


a( 0 );

The output would be:


2 4

Runtime Exceptions
There is a special category of exceptions called runtime exceptions. Runtime exceptions are typically thrown by the Java Virtual Machine when something in the Java runtime goes wrong. This can include: Dividing by 0 during an arithmetic operation. Accessing a null object reference. Casting an object to a type which it is not an instance of. Creating an array with a negative size or accessing an element of an array whose index is larger than the array itself.

runtime exception: A special type of exception that is not checked by the compiler to see if it might be thrown within a method.

Normally, exceptions represent unexpected errors in a program that cannot be avoided. Runtime exceptions, on the other hand, can easily be avoided. For example, accessing a null object reference can be avoided by simply testing the reference to see if it is null before accessing it. An illegal casting operation can be avoided by using the instanceof operator. Dividing by zero can also be easily avoided, as can illegally accessing an array. Runtime exceptions can occur at any time within a program. They are not unexpected errors but, rather, avoidable errors that could be prevented through methods other than exception handling. Because of this, the Java compiler does not require you to catch runtime exceptions or to declare that a method throws them. Doing so would require putting almost all of your code in a try block. The purpose of exception handling is to handle unexpected, unavoidable errors.

Even though the Java compiler does not require that you catch runtime exceptions, you can still catch them just like you would any other type of exception.

Uncaught Exceptions
There are two situations in which an exception would never get caught. The rst is if it were a runtime exception, since the Java compiler does not require that they be caught. The second situation is where, instead of catching an exception, a method simply declares that it throws that exception. If every method in your program does this, no exceptions will ever get caught. An uncaught exception simply keeps aborting method after method, looking for an exception handler. Eventually, the exception will end up making its way to the Java runtime. At this point, there are two possibilities:

148

Java 2 Programming for Developers

If you are running a command-line program, the program will most likely terminate. If you are running a program with a graphical user interface (GUI), your program may still keep running, but there may be serious side effects present in the program.

Obviously, you want to avoid these possibilities. The best way to ensure doing this is to avoid runtime exceptions and properly handle all other exceptions with exception handlers.

TASK 4A-2:
Runtime Exceptions
1. In your text editor, open the le Exception.java and observe its contents.
public class Exception { public static void main(String[] args) { String[] names = {"Jack","Tina","Marge"}; System.out.println(names[3]); } }

2.

What is wrong with the code? The code references names[3] when the array only contains three elements.

3.

Compile and execute the code. When you execute the code, the JVM produces an ArrayIndexOutOfBounds exception.

Lesson 4: Exception Handling and Garbage Collection

149

4.

Return to the source code. To print the last name in the array, get the arrays length, subtract one (because arrays are zero-based), and print out that element of the array.
public class Exception { public static void main(String[] args) { String[] names = {"Jack","Tina","Marge"}; int i = names.length; i-=1; System.out.println(names[i]); } }

5.

Recompile and execute the code.

Topic 4B
Writing Exception Handlers
There are generally four steps involved when writing an exception handler: 1. Identifying exception-throwing code. 2. 3. 4. Placing code in a try block. Writing one or more catch blocks. Including an optional finally block.

Identifying Exception-throwing Code


The rst step involved in writing an exception handler is to identify potential exception-throwing code. The easiest way to do this is by having the compiler inform you of any exceptions that need to be caught. Remember that the compiler does this for all exceptions, except for runtime exceptions. To identify where runtime exceptions might be thrown, you may want to consult the Java API documentation for the method you are trying to invoke. Keep in mind that runtime exceptions can generally be thrown at any time. You dont need to be too concerned with them, but you should remember that they do exist.

150

Java 2 Programming for Developers

Once you have identied a section of code that may throw an exception, you have two choices. If you dont want to catch any exceptions at this point in your program, you can declare that the method youre writing may throw an exception. This is done by using the throws keyword in the method declaration. You could also choose to handle the exception, in which case, its time to write an exception handler.

Keep in mind that the longer you choose not to handle an exception, the more of a negative effect the exception will have on your program.

Placing Code in a try Block


Once you have identied the code which might throw an exception, you need to place that code inside a try block. Here are a couple pointers: Dont place unnecessary code in the try block. When an exception is thrown, any remaining code left in the try block will not get executed. You should try to place all non-exception-throwing code outside of the exception handler if possible. If you declare any local variables within the try block, those variables will not be accessible from outside the try block. The best thing to do in this case would be to declare the variable outside the try block and then initialize or set its value from inside the try block. This way, you can still access them from outside.

Writing the catch Block


With the exception-throwing code now wrapped in a try block, its time to write a catch block in order to catch any exceptions that get thrown. As the writer of the catch block, you can decide how to best handle the exception. Some possibilities are: Handle the exception silently and continue. The ideal exception handler will handle exceptions in such a way that the user will never know an error has occurred. Re-throw the exception. You may decide that you dont want to handle the exception yourself, so you throw the exception again. This is called re-throwing. When you re-throw an exception, the method containing the exception handler must declare that it might throw an exception.
catch ( Exception e ) { // re-throw the exception throw e; }
re-throwing: The process of catching an exception and immediately throwing it again.

Display an error message to the user. This should only be done if the user has an interest in the error. For example, if the user tries to open a le that doesnt exist, then they would probably appreciate an error message. However, if a null pointer exception occurs, a user of your program would most likely not understand the signicance of the error. Terminate the program. In some cases, the error that caused the exception is serious enough that the program should no longer be allowed to execute. An example of this would be if you wrote a program that required a constant network connection and that connection suddenly was broken.

Here are a couple pointers to remember when writing catch blocks:

Lesson 4: Exception Handling and Garbage Collection

151

A catch block should handle an exception, not create new ones. The code in a catch block should be as stable as possible. A catch block should handle an exception, and nothing more. You should not place large chunks of code within a catch block, if that code has nothing to do with handling the exception.

The Exception Object


When a catch block is executed, an exception object is passed in to it. This exception object contains information about what went wrong. This information is accessed via the methods of the Exception class. Some of these methods include: Method
stack trace: Shows you where an exception originated, as well as all the methods that rethrew the exception or passed it on without catching it.

Description
Returns the error message generated by the method which threw the exception. The error message can either be displayed to the user or used to debug your program. Prints a stack trace to the console window. A stack trace will show you where the exception originated, as well as all the methods that re-threw the exception or passed it on without catching it. This is very useful when trying to debug your program. Returns both the particular class name of the exception (IOException, RuntimeException, or others), and the error message.

getMessage()

printStackTrace()

toString()

To call these methods, simply reference the exception object that gets passed into the catch block:
catch ( Exception e ) { // print a stack trace e.printStackTrace(); }

Including a finally Block


As a last step in writing an exception handler, you could include a finally block. This is an optional step and the goal is to factor out duplicate code that appears in both the try block and all the catch blocks. Consider the following code:

152

Java 2 Programming for Developers

try { ... someFile.close(); System.out.println( } catch ( IOException e ... someFile.close(); System.out.println( } catch ( Exception e ) ... someFile.close(); System.out.println( }

"All done!" ); ) {

"All done!" ); {

"All done!" );

In the code sample above, there is duplicate code in each block. By using a finally block, this duplicate code can be factored out:
try { ... } catch ( IOException e ) { ... } catch ( Exception e ) { ... } finally { someFile.close(); System.out.println( "All done!" ); }

By using a finally block, your code can be more efficient and maintainable.

TASK 4B-1:
Writing an Exception Handler
Objective: To create a program that handles exceptions. 1. Open ExceptionDemo.java. This le contains two methods, main() and openFile().

Lesson 4: Exception Handling and Garbage Collection

153

2.

Compile the program. Youll notice that the program will not compile and you receive an error message similar to the following:

You receive this error message because the method openFile() declares that it might throw an exception. At this point, you have two choices: you can declare that the main() method throws an exception, or you can write an exception handler to catch the exception. Both options will allow this code to compile. For this task, you will write the exception handler. 3. Wrap the code in the main() method within a try block. For readability, be sure to indent the code within the try block:
public static void main( String[] args ) { try { openFile(); System.out.println( "All done!" ); } }

4.

Compile the program. A different error message is displayed informing you that you forgot the catch block after the try block:

154

Java 2 Programming for Developers

5.

Insert a catch block immediately after the try block. The catch block should catch an IOException. Inside the catch block, print a stack trace using the printStackTrace() method and display a user-friendly message to the user:
public static void main( String[] args ) { try { openFile(); System.out.println( "All done!" ); } catch( IOException e ) { e.printStackTrace(); System.out.println( "Sorry, I could not open the file!" ); } }

The stack trace is meant for you, the developer. The friendly message is meant for the user. 6. Add a finally block to your code just after the catch block. Move theAll done! message from the try block, into the finally block. This way, the message will be displayed whether an exception gets thrown or not.
public static void main( String[] args ) { try { openFile(); System.out.println( "All done!" ); } catch( IOException e ) { e.printStackTrace(); System.out.println( "Sorry, I could not open the file!" ); } finally { System.out.println( "All done!" ); } }

7. 8.

Compile the program. This time, you shouldnt have any more errors. Run the program and observe the results. The openFile() method throws an exception at random. If no exception gets thrown, you will see the message All done! as the program goes through the openFile() method and an additional All done! when the program executes the finally block. If an exception does get thrown, you will see the stack trace and an error message. Run the program a couple more times and watch it behave differently based on whether an exception gets thrown.

Lesson 4: Exception Handling and Garbage Collection

155

Output without an exception:

Output with an exception:

Topic 4C
Garbage Collection
In Java, you create an object or instance by using the keyword new, but you have no way to specically get rid of an object to free up the memory. Fortunately, Java manages memory for you. Java considers objects that are not referenced as garbage. Javas garbage collection process locates and reclaims memory taken by these objects. Essentially, an object becomes eligible for garbage collection when you no longer reference it. For example, lets say you assigned an object reference to a variable within a method. When that method is done, that variable is gone and, therefore, the object reference is gone. At that point, the object becomes eligible for garbage collection.

156

Java 2 Programming for Developers

Another example is when you assign a null to a variable that contained an object reference. That object reference is lost, and that object becomes eligible for garbage collection. Java uses a two-phase process to perform garbage collection. In the rst phase, it locates and tags objects that are no longer referenced and not going to be referenced. During the second phase, Java actually de-allocates the objects and reclaims memory. Java does not guarantee that it will perform garbage collection at all. It only performs garbage collection if it needs more memory at any point in time, or if it decides to ensure that it will not run out of memory. You may have a program that may not even come close to running out of memory, so Java may never perform garbage collection. Java performs garbage collection only if needed to improve performance, since garbage collection is a very processor- and timeintensive process.

TASK 4C-1:
Performing Garbage Collection
1. In your text editor, open a new le and create a class named Garbage.
class Garbage { public static void main(String[] args) {

} }

2.

Import the java.util.* package and create a Date object and store the reference in a variable.
import java.util.*; class Garbage { public static void main(String[] args) Date d1 = new Date(); } } {

3.

Use the object variable.


import java.util.*;

class Garbage { public static void main(String[] args) Date d1 = new Date(); System.out.println(d1); } } {

Lesson 4: Exception Handling and Garbage Collection

157

4.

Lose the object reference by assigning a null.


import java.util.*;

class Garbage { public static void main(String[] args) Date d1 = new Date(); System.out.println(d1); d1 = null; } } {

Since you assigned a null to d1, the object reference is lost. Assuming no other variable contains a reference to d1, the object d1 is now eligible for garbage collection. While the variable d1 is eligible for garbage collection, the garbage collection process will probably not be performed because this is a small program and Java does need any more memory. 5. 6. Save and compile. Run Garbage.

Summary
In this lesson, you used Javas try, catch, and finally keywords to detect and handle exceptions. You wrote exception handling code that gracefully handles exceptions and enables the program to continue processing. Finally, you explored Javas garbage collection behavior.

158

Java 2 Programming for Developers

Lesson Review
4A What is an exception?
An exception is an event that is triggered because something abnormal or unexpected happens during program execution. How is an exception handler dened? An exception handler is dened by using try, catch, and finally blocks. What is special about a runtime exception? A runtime exception results from something going wrong in the Java runtime. The Java compiler does not require you to catch runtime exceptions.

What happens if an exception in your program is never caught? The program will either terminate or suffer potentially serious side effects.

4B What are the steps involved in writing an exception handler? 1. Identify exception-throwing code. 2. Place code in a try block. 3. Write one or more catch blocks. 4. Optionally, include a finally block.
What can you do with an exception object? Answers may include: You can obtain the error message generated by the method which threw the exception. You can print a stack trace, which helps you debug your program.

4C Describe what involvement a developer can have in Javas garbage collection system.
The only involvement a developer can have is to make an object eligible for garbage collection. Ultimately, Java determines when garbage collection will take place, and what memory will be freed up.

Lesson 4: Exception Handling and Garbage Collection

159

160

Java 2 Programming for Developers

The java.lang Package


Overview
Essential to every Java program, the java.lang package is the only package automatically included when you compile a Java program. It provides the language denition and classes, such as the Math and String classes, that are fundamental to programming in Java. In this lesson, you will explore this package as well as the Math and String classes in greater detail.

LESSON

5
Data Files none Lesson Time 2 hours

Objectives
In the process of exploring the java.lang package, you will: 5A List the classes and interfaces of the java.lang package. The java.lang package has classes and interfaces that are essential to Java programming. The java.lang package is automatically included when you compile a Java program. You will survey the classes and interfaces that are contained in the java.lang package. 5B Use methods and properties of the String class. You will encounter strings regularly in your programming experience. The methods in the String class enables you to manipulate strings. For example, you can determine the number of characters in the string, you can extract characters from the string, and you can search for the existence of a substring. 5C Explore and use the methods of the Math class. Most business applications require some amount of mathematical operations. The Math class provides you with constants such as Pi to calculate the area of a circle. It also gives you methods to perform mathematical functions such as computing the sine of an angle (from trigonometry).

Lesson 5: The java.lang Package

161

Topic 5A
Classes and Interfaces
The java.lang package contains the following classes: Class
Boolean Byte Character Class ClassLoader Compiler Double Float InheritableThreadLocal Integer Long Math Number Object Package Process Runtime RuntimePermission SecurityManager Short String StringBuffer System Thread ThreadGroup ThreadLocal Throwable Void

Subclass of
Object Number Object Object Object Object Number Number

Description
Wrapper for the boolean primitive. Wrapper for the byte primitive. Wrapper for the char primitive. Refers to classes as objects. Supports custom class loading. Supports Just In Time (JIT) compiling to improve performance. Wrapper for the double primitive. Wrapper for the oat primitive. Extends ThreadLocal to enable inheriting thread values. Wrapper for the int primitive. Wrapper for the long primitive. Mathematical constants (such as Pi) and functions. Base class for wrappers of numeric primitives. The highest class. Version information. Control external processes. Access to Java Runtime Environment (JRE). Control access to Java Runtime Environment (JRE). Implements security policies. Wrapper for the short primitive. Wrapper for strings. Buffer for String objects. Access to operating system resources. Creates objects that can run as separate threads, implements the Runnable interface. Collection of Thread objects. Variables that are local to a Thread instance. Base class for Java errors and exceptions. The void primitive.

Number Number Object Object None Object Object Object Object Number Object Object Object Object Object Object Object Object

The java.lang package contains the following interfaces: Interface


Cloneable Comparable Runnable

Description
Class can be cloned by the Object class clone() method. Provides the compareTo() method. The class can run as a separate thread.

162

Java 2 Programming for Developers

TASK 5A-1:
Classes and Interfaces of the java.lang Package
1. 2. 3. Launch your browser and navigate to http://java.sun.com/j2se/1.4/docs/ api/index.html. The home page of the J2SE API specication is displayed. From the Java 2 Platform Packages table in the main browser frame, click on the java.lang link. The Package java.lang page is displayed. Explore the contents of the java.lang package. All of the interfaces, classes, errors, and exceptions are shown. Click on several of the classes and explore their contents. Match the classes/interfaces on the left to their descriptions on the right. e i j h g a b c d f Math Runnable System Integer Class Character Package Object Thread Runtime a. Wrapper for the char primitive. b. Version information about package. c. Highest class in Java hierarchy. d. Creates objects that run as separate threads. e. Mathematical functions and constants. f. Access to JRE. g. Refers to classes as objects. h. Wrapper for the int primitive. i. Class can run as a separate thread. j. Access to operating system resources.

4.

Wrapper Classes
Previously, you took a brief look at wrapper classes and how they enable programs to place an object wrapper around primitive datatypes so they can be stored in collections. The wrapper classes Boolean, Byte, Character, Double, Float, Integer, Long, Short, and String, which are included in the java.lang package, provide additional functionality that is not available to primitive types. You can use the following syntax (where intValue contains an integer value) to wrap an int with the Integer wrapper class (other wrapper classes use similar syntax):
Integer myInteger = new Integer(intValue);

With the intValue wrapped in an Integer, you can perform all of the methods included in the Integer class denition. You can use the following syntax to unwrap the myInteger object (again, other wrapper classes use similar syntax):
int myInt = Integer.intValue(myInteger);

Lesson 5: The java.lang Package

163

Topic 5B
The String Class
The String class is probably the most frequently used class in the Java Class Library. Every string variable and string constant that you create is automatically an object of the String class. By implementing strings as objects, Java provides a suite of properties and methods that enhance your ability to manipulate strings. Each string object that is created is immutable, which means it cannot be altered. In other words, String objects are read-only objects. Java forces the immutability constraint on string objects to enhance performance. Fixed-length string objects can be operated upon much more efficiently than variable length string objects. However, this is not a limitation to the developer, since you can still perform a whole a rich variety of string operations and you can create new string objects as opposed to changing the old object. Lets consider the following code that stores the string Jack into a variable person.
String person = "Jack";

Class type variables (as opposed to primitive datatype), store an reference to the object containing the literal value. And since String is a class, Java creates a string object that contains the literal Jack. Then, Java stores the reference to that object into the variable person. Lets assume you add the following code later on in the program:
person = "Jill";

Java does not change the contents of the rst object. It creates a new object that contains the literal Jill and stores a reference to that object into the variable person. Now, you have two objects, the rst contains Jack, the second contains Jill. The variable person contains an object reference that points to the second object. After the rst statement, you would get the value Jack if you used the following code:
System.out.println(person);

After the second statement, you would get the value Jill if you used the same code.
System.out.println(person);

So while it appears as if you had a variable person that contained one string rst and a second string later, in reality, Java has two separate objects that you can reference through one variable. If you really want just one object that you can alter, Java provides the StringBuffer class. You can also perform most String manipulations with the StringBuffer class. However, the StringBuffer is not as efficient as the String class, from a performance perspective. The methods of the String class are:

164

Java 2 Programming for Developers

Method
charAt endsWith indexOf

Return Type
char boolean int

Parameter List
int location_index String string_to_match String sub_string

Description
Extracts a single character. Determines if the string ends with string_to_match. Determines location of rst occurrence of substring. You get a 1 if it does not exist. Determines location of last occurrence of substring. You get a 1 if it does not exist. Number of characters in the string. Replaces an existing character with another. Determines if the string starts with string_to_match. Returns the substring from the starting index up to, but not including, the ending index. Converts the string to lowercase. Converts the string to uppercase. Removes leading and trailing spaces.

lastIndexOf

int

String sub_string

length replace startsWith substring

int String boolean String

None char originalChar, char replacementChar String string_to_match int startIndex, int endIndex None None None

toLowerCase toUpperCase trim

String String String

TASK 5B-1:
String Methods
Objective: To create an application where you will initialize string variables, compile your code, and test it. 1. Set up an empty application.
class StringIt { public static void main (String args[]) {

} }

2.

Add code to initialize a string variable.


class StringIt { public static void main (String args[]) { String tongueTwister = "She sells sea shells on the sea shore"; } }

Lesson 5: The java.lang Package

165

3.

Add code to display the length.


class StringIt { public static void main (String args[]) { String tongueTwister = "She sells sea shells on the sea shore"; System.out.println( "The number of characters in the tongue twister is " + tongueTwister.length()); } }

4.

Add code to display the character at index 11 (the 12th character).


class StringIt { public static void main (String args[]) { String tongueTwister = "She sells sea shells on the sea shore"; System.out.println( "The number of characters in the tongue twister is " + tongueTwister.length()); System.out.println( "The character at index 11 (12th char) is " + tongueTwister.charAt(11)); } }

5.

Add code to test if it starts with She.


class StringIt { public static void main (String args[]) { String tongueTwister = "She sells sea shells on the sea shore"; System.out.println( "The number of characters in the tongue twister is " + tongueTwister.length()); System.out.println( "The character at index 11 (12th char) is " + tongueTwister.charAt(11)); System.out.println( "The tongue twister starts with a \"She\". " + tongueTwister.startsWith("She")); } }

166

Java 2 Programming for Developers

6.

Add code to test if the string starts with Sea.


class StringIt { public static void main (String args[]) { String tongueTwister = "She sells sea shells on the sea shore"; System.out.println( "The number of characters in the tongue twister is " + tongueTwister.length()); System.out.println( "The character at index 11 (12th char) is " + tongueTwister.charAt(11)); System.out.println( "The tongue twister starts with a \"She\". " + tongueTwister.startsWith("She")); System.out.println( "The tongue twister starts with a \"Sea\". " + tongueTwister.startsWith("Sea")); } }

7.

Add code to determine the location of sea within the string.


class StringIt { public static void main (String args[]) { String tongueTwister = "She sells sea shells on the sea shore"; System.out.println( "The number of characters in the tongue twister is " + tongueTwister.length()); System.out.println( "The character at index 11 (12th char) is " + tongueTwister.charAt(11)); System.out.println( "The tongue twister starts with a \"She\". " + tongueTwister.startsWith("She")); System.out.println( "The tongue twister starts with a \"Sea\". " + tongueTwister.startsWith("Sea")); System.out.println( "The string \"sea\" is located at index " + tongueTwister.indexOf("sea")); } }

Lesson 5: The java.lang Package

167

8.

Add code to get the substring from index 12 to 18.


class StringIt { public static void main (String args[]) { String tongueTwister = "She sells sea shells on the sea shore"; System.out.println( "The number of characters in the tongue twister is " + tongueTwister.length()); System.out.println( "The character at index 11 (12th char) is " + tongueTwister.charAt(11)); System.out.println( "The tongue twister starts with a \"She\". " + tongueTwister.startsWith("She")); System.out.println( "The tongue twister starts with a \"Sea\". " + tongueTwister.startsWith("Sea")); System.out.println( "The string \"sea\" is located at index " + tongueTwister.indexOf("sea")); System.out.println( "The substring between index 12 and 18 is " + tongueTwister.substring(12, 18)); } }

9.

Save the le as StringIt.java. Compile the application.

10. Run the application. 11. Examine the output.

168

Java 2 Programming for Developers

Topic 5C
The Math Class
The Math class consists of two static constants and a number of methods to perform trigonometric and regular mathematical calculations. The angles within the trigonometric methods are specied in radians as opposed to degrees. The values returned for the trigonometric methods are, for the most part, of datatype double. The methods of the Math class are static, they are class methods. You do not have to create an instance to use the method. Besides, because the Math class is declared nal, you cannot extend or instantiate the Math class. The Math class contains the following methods that allows you to perform complex mathematical operations: Method
abs acos asin atan ceil cos oor pow random round sin sqrt tan

Return Type
int/long/oat/ double double double double double double double double double int/long double double double

Parameters
int/long/oat/double numVal double angle double angle double angle double numVal double angle double numVal double x, double y None oat/double numVal double angle double numValue double angle

Description
The absolute value. The angle whose cosine is specied. The angle whose sine is specied. The angle whose tangent is specied. The smallest whole number greater than or equal to numVal. The cosine of the angle specied in radians. The largest whole number less than or equal to numVal. x raised to the power of y. A random number between 0 and 1. The nearest whole number. The sine of the angle specied in radians. Returns the square root. The tangent of the angle specied in radians.

The Math class also gives you two constants: 1. E, the base of the natural logarithm. 2. Pi, the ratio of the circumference of a circle to its diameter. Lets look a little closer at some of the methods: The abs method returns the absolute valuethe positive value, regardless of the sign of the argument. The abs method returns an int if the argument is int, a long if the argument is long, a oat if the argument is oat, and a double if the argument is double. The ceil method returns the nearest whole number (as a double) that is greater than or equal to the argument. The floor method returns the nearest whole number (as a double) that is less than or equal to the argument.

Lesson 5: The java.lang Package

169

The max method compares the two arguments provided and returns a value that is equal to the greater of the two arguments. The datatype of the returned value corresponds to that of the arguments. The min method compares the two arguments provided and returns a value that is equal to the smaller of the two arguments. The datatype of the returned value corresponds to that of the arguments. The random method returns a random value (as a double) that is greater than or equal to 0.0 and less than 1.0. The random function can be used to simulate the roll of a dice in a board game. The round method returns the nearest integer to the argument as int or a long depending on whether the argument is oat or double, respectively. The sin, cos, and tan methods returns the sine, the cosine, and the tangent, respectively, of the argument (which is the angle specied in radians). The sqrt method returns the square root (as a double) of the argument specied as a double. The sqrt method does not return a complex number (real + imaginary) if the argument is a negative number, it returns a NaN (Not a Number). The toRadians method converts an angle specied in degrees into radians. The toDegrees method converts an angle specied in radians into degrees.

TASK 5C-1:
Using the Math Class
1. In your text editor, set up an empty application and name the class MathTest.
class MathTest { public static void main (String args[]) {

} }

2.

Add code to display the power of a number.


class MathTest { public static void main (String args[]) { double numVal1 = 12.5; double numVal2 = 3.5; System.out.println(numVal1 + " raised to the power of " + numVal2 + " is " + Math.pow(numVal1, numVal2)); } }

170

Java 2 Programming for Developers

3.

Add code to display the square root of a number.


class MathTest { public static void main (String args[]) {

double numVal1 = 12.5; double numVal2 = 3.5; System.out.println(numVal1 + " raised to the power of " + numVal2 + " is " + Math.pow(numVal1, numVal2)); System.out.println("The square root of " + numVal1 + " is " + Math.sqrt(numVal1)); } }

4.

Add code to display the oor of a number.


class MathTest { public static void main (String args[]) {

double numVal1 = 12.5; double numVal2 = 3.5; System.out.println(numVal1 + " raised to the power of " + numVal2 + " is " + Math.pow(numVal1, numVal2)); System.out.println("The square root of " + numVal1 + " is " + Math.sqrt(numVal1)); System.out.println("The floor of " + numVal1 + " is " + Math.floor(numVal1)); } }

5.

Add code to display the ceiling of a number.


class MathTest { public static void main (String args[]) { double numVal1 = 12.5; double numVal2 = 3.5; System.out.println(numVal1 + " raised to the power of " + numVal2 + " is " + Math.pow(numVal1, numVal2)); System.out.println("The square root of " + numVal1 + " is " + Math.sqrt(numVal1)); System.out.println("The floor of " + numVal1 + " is " + Math.floor(numVal1)); System.out.println("The ceiling of " + numVal1 + " is " + Math.ceil(numVal1)); } }

Lesson 5: The java.lang Package

171

6.

Add code to display the rounded value of a number.


class MathTest { public static void main (String args[]) { double numVal1 = 12.5; double numVal2 = 3.5; System.out.println(numVal1 + " raised to the power of " + numVal2 + " is " + Math.pow(numVal1, numVal2)); System.out.println("The square root of " + numVal1 + " is " + Math.sqrt(numVal1)); System.out.println("The floor of " + numVal1 + " is " + Math.floor(numVal1)); System.out.println("The ceiling of " + numVal1 + " is " + Math.ceil(numVal1)); System.out.println("The round of " + numVal1 + " is " + Math.round(numVal1)); } }

7.

Add code to display the absolute value of a number.


class MathTest { public static void main (String args[]) { double numVal1 = 12.5; double numVal2 = 3.5; System.out.println(numVal1 + " raised to the power of " + numVal2 + " is " + Math.pow(numVal1, numVal2)); System.out.println("The square root of " + numVal1 + " is " + Math.sqrt(numVal1)); System.out.println("The floor of " + numVal1 + " is " + Math.floor(numVal1)); System.out.println("The ceiling of " + numVal1 + " is " + Math.ceil(numVal1)); System.out.println("The round of " + numVal1 + " is " + Math.round(numVal1)); System.out.println("The abs of " + -numVal1 + " is " + Math.abs(-numVal1)); } }

8.

Add code to display the maximum of two numbers.


class MathTest { public static void main (String args[]) { double numVal1 = 12.5; double numVal2 = 3.5; System.out.println(numVal1 + " raised to the power of " + numVal2 + " is " + Math.pow(numVal1, numVal2)); System.out.println("The square root of " + numVal1 + " is " + Math.sqrt(numVal1)); System.out.println("The floor of " + numVal1 + " is " + Math.floor(numVal1));

172

Java 2 Programming for Developers

System.out.println("The ceiling of " + numVal1 + " is " + Math.ceil(numVal1)); System.out.println("The round of " + numVal1 + " is " + Math.round(numVal1)); System.out.println("The abs of " + -numVal1 + " is " + Math.abs(-numVal1)); System.out.println("The maximum of " + numVal1 + " and " + numVal2 + " is " + Math.max(numVal1, numVal2)); } }

9.

Add code to display the minimum of two numbers.


class MathTest { public static void main (String args[]) { double numVal1 = 12.5; double numVal2 = 3.5; System.out.println(numVal1 + " raised to the power of " + numVal2 + " is " + Math.pow(numVal1, numVal2)); System.out.println("The square root of " + numVal1 + " is " + Math.sqrt(numVal1)); System.out.println("The floor of " + numVal1 + " is " + Math.floor(numVal1)); System.out.println("The ceiling of " + numVal1 + " is " + Math.ceil(numVal1)); System.out.println("The round of " + numVal1 + " is " + Math.round(numVal1)); System.out.println("The abs of " + -numVal1 + " is " + Math.abs(-numVal1)); System.out.println("The maximum of " + numVal1 + " and " + numVal2 + " is " + Math.max(numVal1, numVal2)); System.out.println("The minimum of " + numVal1 + " and " + numVal2 + " is " + Math.min(numVal1, numVal2)); } }

10. Add code to display a random number between 0 and 1.


class MathTest { public static void main (String args[]) { double numVal1 = 12.5; double numVal2 = 3.5; System.out.println(numVal1 + " raised to the power of " + numVal2 + " is " + Math.pow(numVal1, numVal2)); System.out.println("The square root of " + numVal1 + " is " + Math.sqrt(numVal1)); System.out.println("The floor of " + numVal1 + " is " + Math.floor(numVal1)); System.out.println("The ceiling of " + numVal1 + " is " + Math.ceil(numVal1)); System.out.println("The round of " + numVal1 + " is " + Math.round(numVal1)); System.out.println("The abs of " + -numVal1

Lesson 5: The java.lang Package

173

+ " is " + Math.abs(-numVal1)); System.out.println("The maximum of " + numVal1 + " and " + numVal2 + " is " + Math.max(numVal1, numVal2)); System.out.println("The minimum of " + numVal1 + " and " + numVal2 + " is " + Math.min(numVal1, numVal2)); System.out.println("A random number between " + "0 and 1 is " + Math.random()); } }

11. Add code to display the sine of an angle.


class MathTest { public static void main (String args[]) { double numVal1 = 12.5; double numVal2 = 3.5; System.out.println(numVal1 + " raised to the power of " + numVal2 + " is " + Math.pow(numVal1, numVal2)); System.out.println("The square root of " + numVal1 + " is " + Math.sqrt(numVal1)); System.out.println("The floor of " + numVal1 + " is " + Math.floor(numVal1)); System.out.println("The ceiling of " + numVal1 + " is " + Math.ceil(numVal1)); System.out.println("The round of " + numVal1 + " is " + Math.round(numVal1)); System.out.println("The abs of " + -numVal1 + " is " + Math.abs(-numVal1)); System.out.println("The maximum of " + numVal1 + " and " + numVal2 + " is " + Math.max(numVal1, numVal2)); System.out.println("The minimum of " + numVal1 + " and " + numVal2 + " is " + Math.min(numVal1, numVal2)); System.out.println("A random number between " + "0 and 1 is " + Math.random()); int angle = 60; System.out.println("The sine of " + angle + " degrees is " + Math.sin(Math.toRadians(angle))); } }

12. Add code to display the cosine of an angle.


class MathTest { public static void main (String args[]) { double numVal1 = 12.5; double numVal2 = 3.5; System.out.println(numVal1 + " raised to the power of " + numVal2 + " is " + Math.pow(numVal1, numVal2)); System.out.println("The square root of " + numVal1 + " is " + Math.sqrt(numVal1)); System.out.println("The floor of " + numVal1 + " is " + Math.floor(numVal1)); System.out.println("The ceiling of " + numVal1

174

Java 2 Programming for Developers

+ " is " + Math.ceil(numVal1)); System.out.println("The round of " + numVal1 + " is " + Math.round(numVal1)); System.out.println("The abs of " + -numVal1 + " is " + Math.abs(-numVal1)); System.out.println("The maximum of " + numVal1 + " and " + numVal2 + " is " + Math.max(numVal1, numVal2)); System.out.println("The minimum of " + numVal1 + " and " + numVal2 + " is " + Math.min(numVal1, numVal2)); System.out.println("A random number between " + "0 and 1 is " + Math.random()); int angle = 60; System.out.println("The sine of " + angle + " degrees is " + Math.sin(Math.toRadians(angle))); System.out.println("The cosine of " + angle + " degrees is " + Math.cos(Math.toRadians(angle))); } }

13. Add code to display the tangent of an angle.


class MathTest { public static void main (String args[]) { double numVal1 = 12.5; double numVal2 = 3.5; System.out.println(numVal1 + " raised to the power of " + numVal2 + " is " + Math.pow(numVal1, numVal2)); System.out.println("The square root of " + numVal1 + " is " + Math.sqrt(numVal1)); System.out.println("The floor of " + numVal1 + " is " + Math.floor(numVal1)); System.out.println("The ceiling of " + numVal1 + " is " + Math.ceil(numVal1)); System.out.println("The round of " + numVal1 + " is " + Math.round(numVal1)); System.out.println("The abs of " + -numVal1 + " is " + Math.abs(-numVal1)); System.out.println("The maximum of " + numVal1 + " and " + numVal2 + " is " + Math.max(numVal1, numVal2)); System.out.println("The minimum of " + numVal1 + " and " + numVal2 + " is " + Math.min(numVal1, numVal2)); System.out.println("A random number between " + "0 and 1 is " + Math.random()); int angle = 60; System.out.println("The sine of " + angle + " degrees is " + Math.sin(Math.toRadians(angle))); System.out.println("The cosine of " + angle + " degrees is " + Math.cos(Math.toRadians(angle))); System.out.println("The tangent of " + angle + " degrees is " + Math.tan(Math.toRadians(angle))); } }

14. Save as MathTest.java and compile the program.


Lesson 5: The java.lang Package 175

15. Run MathTest.

16. Examine the output. Did it agree with your anticipated answers? If not, discuss this with your instructor.

Suggested Time: 15 minutes

Apply Your Knowledge 5-1


Creating a Command-line Calculator
Objective: To create a command-line calculator that will take three parameters from the command line. The rst parameter will indicate whether the calculator should perform addition or subtraction. The following two parameters will be the numbers on which the operation is performed. The result of the operation should be displayed to the screen. 1. 2. Create the body of a class called AddNSubtract that contains a main method. In the main method, add code that gets a string from the rst member of the command line args array. Also, add code that gets two integers from the command line array. The code to do this might look something like:
int firstNum = Integer.parseInt(args[1]);

3.

Create an if...else block that calls an adding method if the value of the rst command-line parameter equals add or calls a subtracting method if the value of the command-line parameter equals some other value. Your if block might look something like:
if (addOrSubVar.equals("add"){ addNumbers(firstNum, secondNum); } else { subNumbers(firstNum, secondNum); }

4.

Write the methods that add or subtract the two numbers and print the output to the screen. You might need to declare these methods as static because your main method does not instantiate the AddNSubtract class.

176

Java 2 Programming for Developers

5.

Compile and test your application. Your result should look something like the graphic shown here:

6. 7.

Expand the application so that it multiplies and divides. You may need to use the double data type to store your numbers. How do you think this application could be improved? The application could include some error handling to prevent the ArrayIndexOutOfBoundsException. In order to make the variables and methods non-static, you could also have the applications main method create an instance of the AddNSubtract class.

Summary
In this lesson, you listed the various classes and interfaces in the java.lang package. The java.lang package is automatically included when you compile your source code. You explored the various methods of the String class and built an application that used some of the methods of the String class. You also explored the various methods and constants of the Math class. You also built an application that used some of the methods of the Math class.

Lesson Review
5A Why did Sun Microsystems choose to include the java.lang package automatically when you compile?
The java.lang package is fundamental to the Java language specication.

Lesson 5: The java.lang Package

177

5B What does the term immutability of String objects mean?


String objects cannot be altered. You can create a new object with the altered value, but you cannot alter the original object. Java uses xed length String objects for maximum effciency. Give one example of how you would use the length method of the String class. Answers will vary, but may include: To determine the number of characters in a persons firstname text eld, so you can verify that the database eld is large enough before you attempt to store the firstname into the database. To know when to stop if you are extracting one letter at a time and processing it. For example, in developing a parser, you can get the line and process it character-by-character.

5C Give an example of how you would use the random method of the Math class.
Answers will vary, but may include: To generate random colors in a display. To generate a random number to determine the roll of the dice in a game. To extract random samples for quality control.

178

Java 2 Programming for Developers

Java GUIs
Overview
The java.awt package contains the classes and interfaces that enable developers to create graphical user interfaces (GUIs) for their Java applications. In this lesson, you will use Javas Abstract Window Toolkit (AWT) to create GUIs that interact with users. You will write Java code to create containers and components, menuing systems, and applications that display graphics and respond to user input.

LESSON

6
Data Files CustEntry.java MenuGui.java DrawApp.java DrawApp2.java Lesson Time 2 hours, 30 minutes

Objectives
To create Java GUIs, you will: 6A Develop a stand-alone Java application that uses containers and components. Containers and components are the basic building blocks of a Java-based GUI application. As the name implies, containers hold components and other containers. Components, on the other hand, are the GUI widgets such as text areas, menus, and buttons that comprise GUI applications. 6B Use layout managers to control the positioning of objects within containers. Java includes several layout manager classes that use different rules to position components within containers. Javas layout managers are: BorderLayout, CardLayout, FlowLayout, GridLayout, and GridBagLayout. 6C Create a menuing system for an application. Most GUIs require some kind of menuing system to help users nd common functions. The java.awt package includes several classes to help you build menuing systems. 6D Use Javas event handlers to respond to user events. Graphical user interfaces must be able to respond to input from users. Javas event delegation model enables you to design programs that detect and respond to events. 6E Create applications that display graphics. The J2SE API contains a range of tools to enable developers to create programs that generate and display graphics.

Lesson 6: Java GUIs

179

Topic 6A
Containers and Components
Javas Abstract Window Toolkit (AWT) is a Java API that you use to build graphical user interfaces (GUIs). AWT is one of the Java Foundation Classes (JFCs) and enables you to: Create GUI components, like buttons and menus. Handle GUI events, such as mouse clicks and keyboard manipulation. Draw graphics and images.

The AWT classes and interfaces are contained in the java.awt package. Every program that creates GUI components must import the java.awt package.

AWT and Platform Independence


As you know by now, Java and AWT are platform-independent. To achieve this, AWT programs create GUI objects by instantiating components and containers that are represented in an applications native operating system by peer components, also called heavyweight components. Platform independence means that your AWT applications dont need to know how to instruct each operating system to create its environment. In fact, for most applications, a GUI Java program can be written once and run on any supported operating system.

peer components: Similar objects on different operating systems. Also known as heavyweight components. For instance, the Java AWT text eld component has a Windows peer component which is also known as a texteld.

Containers
There are quite a few compelling reasons to create GUIs with Java. From a programmers perspective, the ability to create platform-independent Java GUIs adds a new and highly-valued job skill to your resume. From a users perspective, GUIs present information in a visual and meaningful way. Javas AWT enables you to create a single GUI that can be displayed on almost any platform. Javas AWT container objects are the basic elements that youll use to develop GUI applications. Without a container to hold GUI components, you wouldnt be able to construct even the most basic GUI application. A container is an AWT component that can contain other components. An AWT container has methods that enable it to add, get, display, count, and remove components. The Container class is a subclass of the Component class. Figure 6-1 illustrates the relationship between the various Java classesdown to the java.awt container classes. In this hierarchy, containers are a subclass of components.

platform independence: A feature of a software application or language that enables it to be run on any operating system.

180

Java 2 Programming for Developers

Figure 6-1: Container classes. The following table contains three examples of AWT containers: Container
Window

Description
The abstract Window class represents a generic window object that is subclassed by the Frame class to create application windows and by the Dialog class to create dialog boxes. You can add GUI components and/or other containers to a Window container. The Panel class creates a rectangular area that can contain components. Panel is subclassed by the Applet class, which is used to automatically construct applets. You can add GUI components and/or other containers to a Panel container. The ScrollPane class is used to create scrollable applications. You can add components and/or other containers to a ScrollPane container.

Panel

ScrollPane

Creating Containers
As you are developing Java GUIs, you can follow this procedure to create containers: 1. Create a Java source code le that imports the java.awt package, as shown below.
import java.awt.*;

2.

Create a public class that extends the Frame class. Frame is a subclass of Window and extends all of Windows methods. Heres an example of code that creates a class that extends Frame.
public class ClassName extends Frame { // Class Definition . . . }

3. 4.

Instantiate a container object, as shown here:


ContainerType containerName = new ContainerType();

Write a main method that calls the classs constructor to create a new instance of the class. The main method will look something like this:
public static void main(String[] args){ // Call to Class Constructor }

Lesson 6: Java GUIs

181

5.

Write a constructor that adds the container to the frame and makes the frame visible. A generic constructor might look something like this:
public myConstructor(){ add(object); setSize(210,130); show(); }

Components
A component is a graphical object that is displayed on-screen. Components may contain other components and can be manipulated by end users. Java instructs an operating system to create components by instantiating members of the Component class, which is a subclass of the Object class. The following table contains a list of components and their descriptions: Component
Button

Description
A GUI component that responds to mouse clicks.

Canvas Check box

A blank, rectangular area of the screen onto which a user can draw. A toggle switch that a user can set to on (checked) or off (unchecked).

Choice

Enables a user to select from a series of choices. Also known as a drop-down list or combo box.

Container Label List

Components that can hold other components or containers. A component that displays text to an end user. A choice with a scrollbar from which users can select more than one item.

Scroll bar TextComponent

A component that enables users to select from a range of values. TextField and TextAreas are TextComponents. TextFields contain a single line of text. TextAreas display multiple lines of text.

Creating Components
You can use the following procedure to add containers to components: 1. Create a container. You can create a panel container with the following syntax:
Panel panelName = new Panel();

182

Java 2 Programming for Developers

2.

Create a new component. You can create a button component with the following syntax:
Button buttonName = new Button("Button Label");

3.

Using the containers add method, add the component to the container. You can add a button to a panel with the following syntax:
panel.add(button);

4.

Using the frames add method, add the container to the frame. In a constructor of a class that extends Frame, you can add a panel to a frame with the following syntax:
add(panel);

TASK 6A-1:
Creating a GUI Application
Objective: To use java.awt to create a simple application that adds numbers. 1. In your text editor, create a new Java source code le called awtCalc.java that imports the java.awt package, contains a public class called awtCalc that extends the Frame class, and declares a new panel container object called panel1.
import java.awt.*; public class awtCalc extends Frame { Panel panel1 = new Panel(); }

2.

Add a main method that instantiates a new instance of the awtCalc class called myCalc.
Panel panel1 = new Panel(); public static void main (String[] args) { awtCalc myCalc = new awtCalc(); } }

3.

Write a constructor that adds panel1 to the frame, sets the size to 210 x 130 pixels, and shows the frame.
public static void main(String[] args){ awtCalc myCalc = new awtCalc(); } public awtCalc(){ add(panel1); setSize(210,130); show(); } }

Lesson 6: Java GUIs

183

4.

Save, compile, and execute the application. At this point, the application displays an empty container.

5.

Click on the windows Close button. You will notice that the window does not close. This is because your application does not include code to activate the windows buttons. Later in this lesson, youll learn how to create GUI applications that respond to events. To close the window, switch to the DOS window and press [Ctrl]C. The window closes.

6.

Next, youll add components to your applications panel container. In the awtCalc.java source code le, add declarations for the following objects: A label called label1 that states Enter two numbers:. A button called button1 that is labeled Add. A text eld called textField1 that is four characters wide. A text eld called textField2 that is four characters wide.

import java.awt.*; public class awtCalc extends Frame { Panel panel1 = new Panel(); Label label1 = new Label("Enter two numbers:"); Button button1 = new Button("Add"); TextField textField1 = new TextField(3); TextField textField2 = new TextField(3);

7.

In the constructor, add code that places the label, texteld, and button objects in panel1.
public awtCalc(){ panel1.add(label1); panel1.add(textField1); panel1.add(textField2); panel1.add(button1);

8.

Remove the setSize method and replace it with a call to the pack method so that the window size is set to the preferred size of the total of all of its components.
add(panel1); pack();

184

Java 2 Programming for Developers

9.

Save, compile, and execute the application. The application window is displayed.

10. Close the application window.

Applets
Applets are Java applications that are designed to be embedded in a Web page. Unlike application windows, applets do not need to have menubars and other window componentsfeatures that are contained in the Frame class. In fact, all an applet really needs is a rectangular piece of real estate in which it can run. The Panel class provides the screen area in which an applet can run. The Applet class is a subclass of Panel. Applet objects do not require a main method and constructor because they are automatically constructed by the browser in which they are displayed. The code from the previous activity could be rewritten as an applet. The code that creates the applet could look something like this:
import java.applet.*; import java.awt.*; public class awtCalc extends Applet { public void init(){ setSize(410,130); } }

applet: A Java application that is intended to be embedded in a Web page. The AWT Applet class is a subclass of Panel and is automatically constructed by the browser.

In this very simple example, you dont need to create a panel container because an applet is already displayed within a panel. Figure 6-2 shows what this empty applet would look like if you embedded it in an HTML le and displayed it in your browser.

Figure 6-2: An empty applet.

Lesson 6: Java GUIs

185

Topic 6B
Layout Managers
Up until now, you have had very little control over where components were placed within containers. In fact, you needed to create several containers to control where components were placed in your window. Obviously, if you were working with an application that had a dozen window components, this process would be tedious and time-consuming. Layout managers let you automate the positioning of components within containers, making the job of positioning components much easier. A layout manager is a class that uses a sequence of rules to position components within a container. Layout manager classes implement the AWT LayoutManager interface and use rules that enable components to be exibly positioned, depending on the window size and operating system. Layout Managers Layout Manager
BorderLayout

Layout Rules
Lays out components along the North, South, East, and West borders of a container and in the center of the container. BorderLayout is the default layout for Window, Frame, and Dialog objects. Lays out components as if they were in a deck of cards, displaying only a single layer at a time. Contains methods to switch between cards. Lays out the components in a left-to-right, top-to-bottom fashion. FlowLayout is the default layout for Panel and Applet objects. Lays out the components in a series of regions, all of which are the same size. You can specify the number of grid rows and columns in the GridLayout constructor. Lays out the components in a series of grid regions. However, unlike GridLayout, some components can occupy more than one grid cell. Uses the GridBagConstraints class to determine the positioning and resizing parameters of a component.

CardLayout

FlowLayout

GridLayout

GridBagLayout

186

Java 2 Programming for Developers

TASK 6B-1:
Layout Manager Review
Objective: To demonstrate your knowledge of layout managers. 1. Match the layout manager class with the description of the method that it uses to lay out a container. c a BorderLayout FlowLayout a. b. Lays out the components in a left-toright, top-to-bottom fashion. Lays out the components in a series of regions, all of which are the same size. Lays out components along the North, South, East, and West borders and in the center of a container. Lays out the components in a series of grid regions. Some components can occupy more than one grid cell. Lays out components as if they were in a deck of cards, displaying only a single component at a time.

CardLayout

c.

GridBagLayout

d.

GridLayout

e.

2.

True or False? AWT uses layout managers to ensure a GUIs platform independence. True, layout managers use rules to logically position components in windows of various sizes.

3.

True or False? The BorderLayout is the default layout manager for all Panel objects. False, BorderLayout is the default layout manager for Windows, Frames, and Dialogs.

Assigning a Layout Manager


You can follow these steps to assign a layout manager to a container: 1. Create the container that you want to hold your components. You could also use the default Frame or Panel that is created by your application. 2. 3. 4. Create the components that you want to place in the container. Create a new instance of a layout manager and use your containers setLayout method to assign the layout manager to the container. Add your components to the layout manager in the same way you add components to containers.

The following example shows the syntax used to assign a layout manager to a container. In this example, you create panel1 and assign a new layout manager to it. Then, you insert label1 into the panel.

Lesson 6: Java GUIs

187

public class Layout extends Frame { Panel panel1 = new Panel(); Label label1 = new Label("Hello There"); public static void main(String[] args){ Layout myLayout = new Layout(); } public Layout(){ panel1.setLayout(new LayoutType()); panel1.add(label1); add(panel1); show(); } }

TASK 6B-2:
Using the Border Layout Manager
Objective: To use the border layout manager to position components within a container. 1. In the awtCalc.java source code le, create two new panels called panel2 and panel3 and create a new label called label2 that states, The sum of the numbers is:.
Panel Panel Panel Label Label panel1= new Panel(); panel2 = new Panel(); panel3 = new Panel(); label1 = new Label("Enter two numbers:"); label2 = new Label("The sum of the numbers is:");

2.

Modify the constructor so that: The frames layout manager is BorderLayout. textField1, textField2, and button1 are added to panel2. label2 is added to panel3.
setLayout(new BorderLayout()); panel1.add(label1); panel2.add(textField1); panel2.add(textField2); panel2.add(button1); panel3.add(label2); pack();

3.

Add panel1 to the top of the BorderLayout layout manager, panel2 to the middle region, and panel3 to the bottom region.
panel3.add(label2); add("North", panel1); add("Center", panel2); add("South", panel3); pack();

188

Java 2 Programming for Developers

4.

Save, compile, and execute the application. The output should look something like the following image.

5.

Close the application.

GridBagLayout Layout Manager


You have successfully created a simple window using Java AWT, and used a layout manager to position components within the window. Up until now, the windows that youve designed have relatively simple layouts. In this section, youll use the GridBagLayout layout manager to construct a more complex layout. As a Java AWT developer, theres no doubt that one of the tasks youll be assigned is to create forms. By using the GridBagLayout layout manager, youll have more control over the layout of your form components and youll be able to create more visually appealing form and panel layouts. Without the GridBagLayout layout manager, you would be unable to develop professionalquality forms and layouts. The GridBagLayout layout manager class dynamically positions components within a grid, without mandating that each component ll only a single grid cell (as in the GridLayout). Each component placed in an instance of a GridBagLayout is associated with a set of constraints which indicates how each component is positioned in its grid cell or cells. GridBagLayout is especially useful because it ensures that your applications are platform-independent by guaranteeing that variations in component size and window size do not change the relative position of components.

GridBagConstraints Class
The GridBagLayout class denes the constraining values that are applied to objects laid out by the GridBagLayout layout manager. The following table contains the primary GridBagConstraints eld variables. These values control the positioning of a component in the GridBagLayout layout manager. GridBagConstraint
GridBagConstraint.BOTH GridBagConstraint.CENTER or NORTH, NORTHEAST, NORTHWEST, SOUTH, SOUTHEAST, SOUTHWEST, EAST, WEST GridBagContraint.ll GridBagConstraint.gridheight

Effect on Layout
Allows a component to resize both vertically and horizontally. Positions a component in the specied region of its display area. Allows a component to grow in order to ll its display area. Determines the number of grid rows that a component will ll.

Lesson 6: Java GUIs

189

GridBagConstraint
GridBagConstraint.gridwidth GridBagConstraints.HORIZONTAL GridBagConstraint.VERTICAL

Effect on Layout
Determines the number of columns that a component will ll. Allows a component to resize horizontally. Allows a component to resize vertically.

Procedure for Using GridBagLayout


You can use GridBagLayout to lay out the contents of a window by following these steps: 1. 2. 3. 4. 5. 6. Create the components that you want to lay out with GridBagLayout. Create instances of GridBagLayout and GridBagConstraints. Assign the instance of GridBagLayout as a containers layout manager. Set the GridBagConstraint properties for the rst component that you want to add. Add the component. Change the GridBagConstraint properties as needed and insert the rest of your components.

The following code positions components in a GridBagLayout. First, the code creates instances of GridBagLayout and GridBagConstraints and sets the layout to the instance of GridBagLayout. Next, the code sets the GridBagConstraints properties (fill and gridheight) and inserts a component. Finally, the code changes the constraints, as needed, and inserts more components.
public GridBagExample() { // Create an instance of GridBagLayout and GridBagConstraints GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); // Set the layout setLayout(gridbag); // Fill the fields horizontally and vertically c.fill = GridBagConstraints.BOTH; // Make the next component span two rows c.gridheight = 2; // Add the component add(Button1, c); // Reset the gridheight and add more components c.gridheight = 1; add(Button2, c); add(Button3, c); // Make the next components span the rest of the columns c.gridwidth = GridBagConstraints.REMAINDER; add(Button4, c);

190

Java 2 Programming for Developers

add(Button5, c); // Make the next component the next-to-last in the row c.gridwidth = GridBagConstraints.RELATIVE; add(Button6, c); c.gridwidth = GridBagConstraints.REMAINDER; add(Button7, c); pack(); show(); }

Figure 6-3 shows the output of the code.

Figure 6-3: Buttons laid out with the GridBagLayout.

TASK 6B-3:
Using a GridBagLayout
Objective: To use the GridBagLayout layout manager to position components within a container. 1. 2. From the C:\077954 folder, open the CustEntry.java source code le. Take a look at the source code. Given your knowledge of Java and AWT, what does this code do? What is missing? The code creates a list of objects but doesnt add them to any container. The objects need to be added to a container before the code will do anything. 3. In the custEntry() constructor, declare a new instance of a GridBagLayout called gbl and a new instance of GridBagConstraints called gbc. Assign gbl as the containers layout manager.
public CustEntry(){ super("New Customer Entry Form"); addWindowListener(new WindowEventHandler()); label1.setFont(new Font("Times-Roman", Font.BOLD + Font.ITALIC, 16)); GridBagLayout gbl = new GridBagLayout(); GridBagConstraints gbc = new GridBagConstraints(); setLayout(gbl);

Lesson 6: Java GUIs

191

4.

Add a block of code that sets the gridwidth of gbc so that the component spans all columns and that adds label1 to the gbc container.
public CustEntry(){ super("New Customer Entry Form"); addWindowListener(new WindowEventHandler()); label1.setFont(new Font("Times-Roman", Font.BOLD + Font.ITALIC, 16)); GridBagLayout gbl = new GridBagLayout(); GridBagConstraints gbc = new GridBagConstraints(); setLayout(gbl); gbc.gridwidth = GridBagConstraints.REMAINDER; add(label1, gbc);

5.

Add a block of code which achieves the following: Sets the fill eld value of gbc so that components can resize horizontally. Sets the gridwidth value so that each of the following components spans a single cell. Sets the insets values so there is 1 pixel of padding on each components top, 10 pixels on the left, 1 pixel on the bottom, and 1 pixel on the right. Adds the name label to the gbc container.

public CustEntry(){ super("New Customer Entry Form"); addWindowListener(new WindowEventHandler()); label1.setFont(new Font("Times-Roman", Font.BOLD + Font.ITALIC, 16)); GridBagLayout gbl = new GridBagLayout(); GridBagConstraints gbc = new GridBagConstraints(); setLayout(gbl); gbc.gridwidth = GridBagConstraints.REMAINDER; add(label1, gbc); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridwidth = 1; gbc.insets = new Insets(1,10,1,1); add(name, gbc);

6.

Next, add code that resets the gridwidth value to REMAINDER and adds the nameField text eld to the gbc layout.
public CustEntry(){ super("New Customer Entry Form"); addWindowListener(new WindowEventHandler()); label1.setFont(new Font("Times-Roman", Font.BOLD + Font.ITALIC, 16)); GridBagLayout gbl = new GridBagLayout(); GridBagConstraints gbc = new GridBagConstraints(); setLayout(gbl);

192

Java 2 Programming for Developers

gbc.gridwidth = GridBagConstraints.REMAINDER; add(label1, gbc); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridwidth = 1; gbc.insets = new Insets(1,10,1,1); add(name, gbc); gbc.gridwidth = GridBagConstraints.REMAINDER; add(nameField, gbc);

7.

Next, add code that: Resets the gridwidth so that subsequent components ll a single grid cell. Inserts the address label. Resets the gridwidth so that components ll the leftover grid cells. Inserts the addressField text eld.

public CustEntry(){ super("New Customer Entry Form"); addWindowListener(new WindowEventHandler()); label1.setFont(new Font("Times-Roman", Font.BOLD + Font.ITALIC, 16)); GridBagLayout gbl = new GridBagLayout(); GridBagConstraints gbc = new GridBagConstraints(); setLayout(gbl); gbc.gridwidth = GridBagConstraints.REMAINDER; add(label1, gbc); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridwidth = 1; gbc.insets = new Insets(1,10,1,1); add(name, gbc); gbc.gridwidth = GridBagConstraints.REMAINDER; add(nameField, gbc); gbc.gridwidth = 1; add(address, gbc); gbc.gridwidth = GridBagConstraints.REMAINDER; add(addressField, gbc);

Lesson 6: Java GUIs

193

8.

Finally, change the gridwidth parameter back to 1 and insert the city, cityField, state, and stateField components.
public CustEntry(){ super("New Customer Entry Form"); addWindowListener(new WindowEventHandler()); label1.setFont(new Font("Times-Roman", Font.BOLD + Font.ITALIC, 16)); GridBagLayout gbl = new GridBagLayout(); GridBagConstraints gbc = new GridBagConstraints(); setLayout(gbl); gbc.gridwidth = GridBagConstraints.REMAINDER; add(label1, gbc); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridwidth = 1; gbc.insets = new Insets(1,10,1,1); add(name, gbc); gbc.gridwidth = GridBagConstraints.REMAINDER; add(nameField, gbc); gbc.gridwidth = 1; add(address, gbc); gbc.gridwidth = GridBagConstraints.REMAINDER; add(addressField, gbc); gbc.gridwidth = 1; add(city, gbc); add(cityField, gbc); add(state, gbc); add(stateField, gbc); pack(); show(); }

9.

Save, compile, and test the application.

194

Java 2 Programming for Developers

Topic 6C
Menus
Now that you have assembled some of the components for a simple graphical interface, youre probably wondering how to add other GUI components, like menus and menu items, to your applications. In this topic, youll create a menuing system that adds menus, menu items, and cascading menus to your application. As a programmer and application developer, you probably understand the importance of a menuing system in a graphics application. Menus provide the users of your applications with a convenient and familiar means to accomplish common tasks like opening and saving les or cutting, copying, and pasting. A menu component is any AWT object that is used to create menus. Menu components extend the abstract MenuComponent class. Figure 6-4 shows some examples of the most commonly used menu components.

Figure 6-4: Menu components. The following table lists the menu component classes. Class
Menubar

Description
The Menubar class is used to create a windows menubar. A menubar contains menus and is attached to a frame by using the frames setMenuBar() method. The Menu class represents the menus that are deployed from a frames menubar. Menus generally contain menu items and/or other menus. The MenuItem class represents a simple, labeled menu item that is contained in a menu. A CheckboxMenuItem is a subclass of MenuItem and represents a labeled menu with a toggle check box. CheckboxMenuItems are contained in menus.

Menu

MenuItem CheckboxMenuItem

Adding Menus
You can add a menubar and menus to an application by following these steps: 1. Declare a new menubar object. For simplicitys sake, many developers call their menubars mb or myMB.
Lesson 6: Java GUIs 195

2. 3. 4.

Declare the menus that you want to include in your application. Use the menubars add method to add the menu objects to the menubar. Use your frame objects setMenuBar method to add your menubar to the frame.

TASK 6C-1:
Creating a Menu
Objective: To use the menu component classes to build a menuing system. 1. 2. From the C:\077954 folder, open MenuGui.java. Youll add a menuing system to this application. Add a declaration for a new MenuBar object called myMB.
public class MenuGUI Label label1 = new Label label2 = new Label label3 = new Label label4 = new extends Frame { Label("Customer Name:"); Label(" Customer No.:"); Label("Select a Product:"); Label("Enter a Quantity:");

//Declare a New MenuBar Object Here MenuBar myMB = new MenuBar();

3.

In the indicated region of the constructor, type:


public menuBar() { super("Customer Order Entry"); addWindowListener(new WindowEventHandler()); buildChoice(); buildCheckboxGrp(); //Call the buildMenuBar Method Here buildMenuBar(); setMenuBar(myMB);

This code creates a call to the buildMenuBar() method, which adds the menubar components to the menubar (youll create this method in the next step) and calls the menubars setMenuBar() method (this method is dened in the java.awt MenuBar class) which adds the myMB menubar to the layout. 4. Add a method called buildMenuBar that creates the following objects and adds them to myMB: A Menu called fileMenu that says File. A Menu called editMenu that says Edit.

196

Java 2 Programming for Developers

A Menu called helpMenu that says Help.

// Add buildMenuBar Method Here void buildMenuBar(){ Menu fileMenu = new Menu("File"); Menu editMenu = new Menu("Edit"); Menu helpMenu = new Menu("Help"); myMB.add(fileMenu); myMB.add(editMenu); myMB.add(helpMenu); }

5.

At this point, your application has three menus without any menu items. To add menu items to the menus, rst initialize the following menu items: openFileMenu saveasFileMenu cutEditMenu copyEditMenu pasteEditMenu aboutHelpMenu

// Add buildMenuBar Method Here void buildMenuBar(){ Menu fileMenu = new Menu("File"); MenuItem openFileMenu = new MenuItem("Open a File"); MenuItem saveasFileMenu = new MenuItem("Save As File"); Menu editMenu = new Menu("Edit"); MenuItem cutEditMenu = new MenuItem("Cut"); MenuItem copyEditMenu = new MenuItem("Copy"); MenuItem pasteEditMenu = new MenuItem("Paste"); Menu helpMenu = new Menu("Help"); MenuItem aboutHelpMenu = new MenuItem("About");

6.

Finally, add the menu items to the menus.


// Add buildMenuBar Method Here void buildMenuBar(){ Menu fileMenu = new Menu("File"); MenuItem openFileMenu = new MenuItem("Open a File"); MenuItem saveasFileMenu = new MenuItem("Save As"); fileMenu.add(openFileMenu); fileMenu.add(saveasFileMenu); Menu editMenu = new Menu("Edit"); MenuItem cutEditMenu = new MenuItem("Cut"); MenuItem copyEditMenu = new MenuItem("Copy"); MenuItem pasteEditMenu = new MenuItem("Paste"); editMenu.add(cutEditMenu); editMenu.add(copyEditMenu); editMenu.add(pasteEditMenu); Menu helpMenu = new Menu("Help"); MenuItem aboutHelpMenu = new MenuItem("About"); helpMenu.add(aboutHelpMenu); myMB.add(fileMenu); myMB.add(editMenu); myMB.add(helpMenu); }

Lesson 6: Java GUIs

197

7.

Save, compile, and execute the application. Click on the File menu. The File menu items are displayed.

8.

Select one of the menu items. Notice that the applications menu items dont trigger any actions. Youll learn how to handle events in the next section.

Topic 6D
Handling Events
Now that youve mastered component layout, youre ready to start using events in your programs. The rst way that youll use events is to use an action event handler to respond to a click of a button in your application. Responding to action events is an essential skill for any Java GUI programmer. Using action events enables you to write programs with buttons that trigger actions and perform such basic operations as closing a window. Theres no doubt that when you employ these skills in your application development, not only will you be able to develop a broader range of application types, but your programs will be more user-friendly and easier to operate.

Javas Event Delegation Model


The event delegation model is composed of three parts: components, events, and listeners. As you can see in Figure 6-5, components such as buttons or labels dispatch event objects, which are handled by listeners. Listeners are registered with components, so that when an event occurs, the appropriate method in the listeners interface is called. The Listener class (often an inner class), which is registered with a component, implements one of AWTs listener interfaces and contains one or more methods that may be red, depending on the nature of the action. When the registered component receives an action from a user, an instance of an event class is created. This class is used by the listener class to handle the action.

event: An occurrence in the runtime system. Events occur when a user interacts with the system by pressing a button, clicking the screen, or performing other actions.

listener: An object that is notied by a registered source when an event, such as a button press, occurs. A listener object implements an eventlistener interface that corresponds to the component to which it is assigned.

198

Java 2 Programming for Developers

Figure 6-5: Javas event delegation model. Figure 6-6 shows the types of events that can be dispatched by components.

Figure 6-6: Event categories.

Event Listener Interfaces


Event listener interfaces are interfaces that extend the top-level java.util.EventListener interface. The event listener interfaces contain methods that enable the listeners to handle specic types of events from components. Event listeners are registered with components, such as buttons and text elds, that receive user actions. Event Listener Interface
ActionListener AWTEventListener AdjustmentListener ComponentListener

Event Types Handled


Implemented by objects, such as buttons, that handle ActionEvents. An interface handles events dispatched to objects that are Components or MenuComponents. An interface that receives AdjustmentEvents sent by adjustable objects like scrollbars. An interface that receives ComponentEvents that indicate changes in a components visibility, size, or position. An interface that receives ContainerEvents triggered by changes in a containers contents.

ContainerListener

Lesson 6: Java GUIs

199

Event Listener Interface


FocusListener

Event Types Handled


An interface that receives FocusEvents triggered when a component gains or loses the keyboard focus. An interface that receives InputMethodEvents that contain information about text that is composed by an input method. An interface that receives ItemEvents that indicate when an item was selected or deselected. An interface that receives KeyEvents that are triggered when the keyboard is manipulated. An interface that receives MouseEvents that are triggered when the mouse button is manipulated. An interface that receives MouseEvents that are triggered when the mouse is moved. An interface that receives TextEvents that indicate that an objects text has changed. An interface that handles WindowEvents.

InputMethodListener

ItemListener KeyListener MouseListener MouseMotionListener TextListener WindowListener

Event Adapter Classes


Java interfaces require you to write denitions for all of their methods. When you use a event listener interface like ActionListener, which contains only one method, this requirement is easy to accommodate. However, if you want to use the MouseListener interface, you need to dene the mouseClicked, mouseEntered, mouseExited, mousePressed, and mouseReleased methods. To save you this hassle, the java.awt.event package contains event adapter classes that automatically include implementations of the interface methods. The most commonly used event adapter classes are the MouseAdapter, the MouseMotionAdapter, and the WindowAdapter.

event adapter class: An abstract class that receives mouse events and contains empty method stubs that save a programmer from needing to dene each method in an interface implementation.

Event Listener Assignment


Getting your applications to respond to action events is a simple process. To get a component to respond to an event: 1. Use the components listener registration method to assign an appropriate event listener interface to a component. A listener registration method like addActionListener() takes a new instance of the event handling class as a parameter. 2. Create a class that implements the appropriate event listener interface or extends the appropriate event adapter class for your component. Heres an example of a action handling class called ButtonHandler:
class ButtonHandler implement ActionListener(){ }

3.

Override the class methods that will be called when the event object is passed to the class. Heres an example of a method that overrides the ButtonHandlers actionPerformed method.
public void actionPerformed(ActionEvent e) { \\ When an event occurs, do this code . . . }

200

Java 2 Programming for Developers

TASK 6D-1:
Responding to an Action Event
Objective: To use event listeners to detect events and event handlers to handle events. 1. 2. In your text editor, open awtCalc.java. Youll add an event listener and event handler to the application. At the top of the le, add a statement to import the java.awt.event.* package.
import java.awt.*; import java.awt.event.*;

The java.awt.event package includes the classes that enable your applications to respond to user events. 3. Create a new label object called label3. Youll display the sum of the two numbers entered in the text elds in this label.
Label label1 = new Label("Enter two numbers:"); Label label2 = new Label("The sum of the numbers is: "); Label label3 = new Label("");

4.

In the constructor, add label3 to panel3.


panel1.add(label1); panel2.add(textField1); panel2.add(textField2); panel2.add(button1); panel3.add(label2); panel3.add(label3);

5.

Insert a WindowListener that creates a new instance of a class called WindowEventHandler. WindowListeners detect window events like minimize, restore, and close.
public awtCalc() { addWindowListener(new WindowEventHandler());

This code adds a WindowListener that will implement the WindowEventHandler class to close the window when a user clicks the Close button. Youll create the WindowEventHandler class later in this activity. 6. On the following line, add an ActionListener to button1 that creates a new instance of a class called ButtonHandler.
button1.addActionListener(new ButtonHandler());

This code adds an ActionListener to button1. Youll create a class called ButtonHandler that is triggered when the button is clicked.

Lesson 6: Java GUIs

201

7.

At the end of the source code le, before the closing bracket, add an inner class called WindowEventHandler that extends the WindowAdapter event adapter class and contains a method called windowClosing that exits the program.
class WindowEventHandler extends WindowAdapter{ public void windowClosing(WindowEvent e) { System.exit(0); } }

8.

At the end of the le, before the closing bracket, add a class called ButtonHandler that, when button1 is pressed, gets the values in the text elds, converts them to integers, adds them together, converts the result to a string, and sets the value of label3 to the result. The ButtonHandler class should implement the ActionListener interface.
class ButtonHandler implements ActionListener{ public void actionPerformed(ActionEvent ev){ String val1 = textField1.getText(); String val2 = textField2.getText(); int val3 = new Integer(val1).intValue(); int val4 = new Integer(val2).intValue(); int result = val3+val4; String strResult = String.valueOf(result); label3.setText(strResult); } }

The actionPerformed method of your ButtonHandler class overrides the ActionListener interfaces actionPerformed method. 9. Compile and test the application by entering numbers into the text elds and clicking the Add button. The result is displayed in label3.

10. Click the windows close button to exit the application.

202

Java 2 Programming for Developers

Apply Your Knowledge 6-1


Responding to Mouse Events
Objective: To modify the application created in the previous activity so that the calculation is triggered by a mouse event rather than a button action event. Setup: In the previous activity, you created an application that used a button handler to implement the ActionListener interface. In this activity, youll change the applications button to a label and use the MouseListener interface and the MouseAdapter class to respond to a users clicks on the label. 1. 2. 3. Change the button1 member declaration so that it creates a label called label4 that contains the text, Add Em Up. In the awtCalc constructor, change the method call that adds button1 to panel2 so that it adds label4 to panel2. Change the instruction that assigns a button listener to button1 so that it assigns a mouse listener to label4. The addMouseListener() method should create a new instance of a class called MouseHandler. Rename the ButtonHandler class to MouseHandler. Modify the class so that it implements the MouseListener interface. Add empty implementations of the MouseInterfaces mouseClicked, mousePressed, mouseReleased, mouseEntered, mouseExited, and mouseDragged methods that are passed a MouseEvent called ev. Move the implementation of the actionPerformed method into the mouseClicked method so that when a user clicks the label, the numbers in the text elds are added and the sum is displayed. Delete the actionPerformed method body. To the body of the mouseClicked method, add a line that prints the ev MouseEvent object to the console. You can use the components of this object when you develop applications that use MouseEvents. The code should look like:
System.out.println(ev);

Suggested Time: 15 minutes

4.

5.

6.

7. 8.

Compile and test the application. Return to the source code le. Change the MouseHandler class so that it extends the MouseAdapter class rather than the MouseListener interface. What is the advantage of using the MouseAdapter class rather than the MouseListener interface? The MouseAdapter class provides default implementations of the MouseListener methods. This means that you dont have to include your own implementation of each MouseListener interface method.

9.

10. Compile and test the application.


Lesson 6: Java GUIs

203

Topic 6E
Java Graphics
Every AWT component has its own java.AWT.Graphics object that it uses to paint itself to the screen or to perform other graphical operations that are associated with the component. Although you can paint lines and shapes in any component, AWT has provided the Canvas class specically for painting. You can use the methods of the Graphics class to paint objects into a Canvas object (or any other component) by overriding the objects paint method. Graphics class methods are methods that enable you to create and display graphics objects. The following table contains some of the most commonly used Graphics class methods. Graphics Method
drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) drawImage(Image img, int x, int y, ImageObserver observer) drawLine(int x1, int y1, int x2, int y2) drawOval(int x, int y, int width, int height) drawRect(int x, int y, int width, int height) drawString(String str, int x, int y) llArc(int x, int y, int width, int height, int startAngle, int arcAngle) llRect(int x, int y, int width, int height)

Description
Draws an arc around the outline of the specied rectangle. Draws an image beginning at the x,y origin. Draws a line between the two points. Draws an oval. Draws a rectangle beginning at the specied x,y point. Draws a string of characters, beginning at the specied point. Fills the indicated arc. Fills the specied rectangle.

The Color Class


The Color class is used to represent colors in the RGB colorspace. The most commonly used Color constructor takes three parameters, which represent the red, green, and blue color values. In addition, you can set a colors alpha, or transparency, value as a fourth parameter. Alpha values are oats that vary between 0.0 (which makes the color entirely transparent) and 1.0 (which makes the color nontransparent). You can also use Javas static color variables to dene colors by specifying a variable name, rather than the RGB value. For instance, the color gray is referenced with the static color variable Color.gray, rather than with the RGB value Color(150,150,150);. If you dont have to be precise about which colors you use, these classes can save you a signicant amount of time.

RGB: Color dened by its red, green, and blue components. RGB is typically used for dening colors displayed on-screen, since those are the colors used in monitors.

Painting Shapes to a Screen


You can draw graphics objects to the screen by following these steps: 1. Create an instance of the object in which you want the graphics to appear. If youre creating a drawing tool, youll probably use an instance of the Canvas class.

204

Java 2 Programming for Developers

2. 3.

Override the components paint method. Generally, this means that youll create a subclass of Canvas or Panel that overrides the paint method. In your paint method, call the graphics methods that draw the graphics objects. For instance, given a Graphics class g, you could draw a line with the following code:
g.drawLine(10,10,100,100);

TASK 6E-1:
Painting Shapes to a Screen
Objective: To create a Java application that paints shapes to a computer screen. 1. 2. From the C:\077954 directory, open drawApp.java. The le contains the skeleton of an application that draws shapes in a window. In the indicated region of the source code le, inside the MyCanvas inner class, add a paint method that receives a Graphics object called g as a parameter. Set gs color to black.
class MyCanvas extends Canvas { // Add paint method here public void paint(Graphics g) { g.setColor(Color.black);}

Notice that the MyCanvas class is a subclass of the Java APIs Canvas class. As a result, all of the methods and elds of the Canvas class are available in the MyCanvas class. In addition, your MyCanvas class overrides the Canvas classs paint method. 3. In the paint method, add code to draw a line and an oval with the following coordinates: The ovals origin should be at (30, 30) and its dimensions should be 30 x 40. The lines origin should be at (40, 30) and its terminus should be at (260, 160).
g.setColor(Color.black); g.drawOval(30,30,30,40); g.drawLine(40,30,260,160);

4.

Change the graphics color to blue and draw a lled rectangle whose origins are at (110, 35) and whose dimensions are 55 x 110.
g.drawLine(40,30,260,160); g.setColor(Color.blue); g.fillRect(110,35,55,110);
The JVM processes the commands in the paint method sequentially.

Lesson 6: Java GUIs

205

5.

Next, change the color to red and draw an unlled rectangle that starts at (100, 30) and whose dimensions are 50 x 100. Draw a string of text that says, Hello There, whose origins are at (200, 180).
g.fillRect(110,35,55,110); g.setColor(Color.red); g.drawRect(100,30,50,100); g.drawString("Hello There", 200,180);

6.

Save and test your application. Your application window should look like the following image:

Suggested Time: 15 minutes

Apply Your Knowledge 6-2


Painting Shapes in Response to User Events
In this activity, youll create an application that draws shapes and lines when a user clicks a button. When youre nished, your application should look like the following graphic:

1. 2. 3. 4.

From the C:\077954 directory, open drawApp2.java. Declare three new buttons called button1, button2, and button3, that are labeled Draw Line, Draw Rectangle, and Draw Oval, respectively. Add the buttons to the panel called panel. To each of the buttons, add an ActionHandler that uses a class called ButtonHandler. Add panel to the top of the window. For the button1 action handler, the declaration will look like this:
button1.addActionListener(new ButtonHandler());

206

Java 2 Programming for Developers

5.

In the ButtonHandler class, get events action command and assigns it to a String variable called s. Add the framework for an if...else control structure that determines whether s equalsDraw Line, Draw Rectangle, or Draw Oval. Youll ll in the method bodies in the next step. Your button handler class will look something like this:
class ButtonHandler implements ActionListener { public void actionPerformed(ActionEvent event) { String s = event.getActionCommand(); if(s.equals("Draw Rectangle")){ } else if(s.equals("Draw Line")){ } else if(s.equals("Draw Oval")){ } }

6.

Add code to each if...else control structure so that: If a user clicks Draw Rectangle, a rectangle with an origin at (50,80) and dimensions of 120 x 100 is drawn. If a user clicks Draw Line, a line with an origin at (200,50) and an end at (400,600) is drawn. If a user clicks Draw Oval, a 150 x 100 oval with an origin at (150,50) is drawn.

Your code for drawing a rectangle will look something like this:
if(s.equals("Draw Rectangle")){ Graphics g = getGraphics(); g.drawRect(50,80,120,100); }

7.

Save, compile, and test your application.

Summary
In this lesson, you used the java.awt package to create graphical user interfaces. You wrote Java code to create containers and components, menuing systems, and applications that display graphics and respond to user input.

Lesson 6: Java GUIs

207

Lesson Review
6A Describe the differences between Java applets and stand-alone applications.
A Java applet is displayed in a browserwhile a stand-alone application is displayed by a computers native operating system. Javas stand-alone applications use the Frame class to create a space in which the application is displayed. Java applets use the Applet class, which creates a Panel object in a browser window. List and describe the steps required to create an application that displays components within a container. 1. 2. 3. 4. 5. Create a class that imports the java.awt.* package and extends the Frame class. Construct the containers and components that you will include in your application. Write a main method that instantiates the class and calls the Frames show() method. Use the Frames add() method to add the container to the frame. Use the containers add() method to add components to the container.

6B How does the gridBagLayout layout manager position window components? When would you want to use gridBagLayout?
The gridBagLayout layout manager uses the constraints specied in the gridBagConstraints class to position components along grid cells. Typically, youll use gridBagLayout to position components in containers that can vary in size between operating systems.

6C What are the advantages of using a menuing system? Can you think of any disadvantages?
Answers will vary, but menuing systems are advantageous because they group commands into easily navigated and widely used menu components. Menuing systems may not be necessary for very simple applications.

6D In what types of applications will you want to use event handling?


Answers will vary, but any application that receives and responds to keyboard and/or mouse input will need to use event handling. Discuss the differences between a TextListener and an ActionListener. How are they alike? How do they differ? The ActionListener interface responds to button clicks while the TextListener interface handles changes in text elds. Although they receive events from different types of sources, both interfaces handle events in the same general way.

6E What class would you use to enable an application to draw into components? Discuss when you would use the various methods of this class.
The Graphics class enables you to draw into objects. Each of the class methods creates a specic type of graphical object.
208 Java 2 Programming for Developers

The java.io Package


Overview
Input and output, better known as I/O, allow us to bring data into our programs and to store data outside of our programs. Without this ability, program functionality would be limited. Java provides I/O through the java.io package. In this lesson, you will explore the java.io package and the services that it provides.

LESSON

7
Data Files FileInfo.java Reader.java TextEditor.java Address.java Lesson Time 1 hour, 30 minutes

Objectives
To effectively use I/O in the Java programming language, you will: 7A Explore and discuss the java.io package. The java.io package can seem overwhelming at rst. With all those classes, you may not know where to begin. You will explore this package and learn how many of the components work together to provide input and output (I/O) in Java. 7B Use the java.io package to read data from les into your program. Sometimes in other programming languages, reading les is not something programmers look forward to. The complicated system calls, cryptic variables, and messages complicate the process. Fortunately, Java handles all these details and provides us with an easy-to-understand, objectoriented approach to le I/O. 7C Use the java.io package to write les to your hard drive. Writing les is very similar to reading les. The only difference is that information ows in a different direction. You will write les to your hard drive using the classes available from the java.io package. 7D Use object serialization to read and write objects. In Java, you are not limited to I/O using bytes and characters. You can also read and write objects. You will learn about object serialization and how it is used to read and write objects.

Lesson 7: The java.io Package

209

Topic 7A
Overview of the java.io Package
Sometimes the data we require is not available within our program. It may be contained within a le on our computer, or someone elses computer. Likewise, there may be times when we want to store information outside of our program. Therefore, developers need a way to bring data in and send data out of programs. This is achieved through a process called I/O, which stands for input and output. The classes that compose Javas I/O functionality can be found in the java.io package. At rst glance, this package can seem overwhelming. With more that 50 classes, you may not know where to begin. Fortunately, you dont need to use all of these classes to perform simple I/O. Instead, Java gives you a lot of choices when it comes to reading and writing data. Lets dive right into the java.io package. We will begin with the File class.
I/O: Short for input and output.

The File Class


Java does not provide a Directory class. Since a directory is a special type of le, the File class is used to represent both les and directories. Keep this in mind when working with the File class.

The File class represents a le or directory on your hard drive. Having such a class available to refer to a le or directory is more convenient than using a string. A string can only represent the lename. A File object, on the other hand, cannot only represent the lename, but also provide additional information about the le such as its parent directory, permissions, and size.

Creating a File Object


There are a couple different ways to create a File object in Java. The rst is to create one using a string that species the full path to the le. For example:
// the filename String fileLocation = "C:\somefile.txt";

If you omit the full path to the le and only use a lename, Java automatically assumes you are referring to a le in the directory from which your program was executed.

// the file object File theFile = new File( fileLocation );

You can also create a File object by specifying both the directory and the lename as two separate strings. For example:
// the directory String directory = "C:\"; // the filename String filename = "somefile.txt"; // the file object // this constructor takes two parameters, // one string representing the directory, // the other representing the filename File theFile = new File( directory, filename );

You can also use a File object to represent the directory, and then use a string to create a File object representing a le in that directory. For example:

210

Java 2 Programming for Developers

// the directory String directory = "C:\"; // the file object representing the directory File theDirectory = new File( directory ); // the filename String filename = "somefile.txt"; // the file object representing the file // this constructor takes two parameters, // a file object and a string File theFile = new File( theDirectory, filename );

Using the File Object


Once you have created a File object, you can then obtain information about the le that it represents. The File class has many methods that allow you to do this. The following table lists some of these methods: Method
canRead() canWrite() createNewFile()

Description
Returns true if the le exists and if the les contents can be read by your program. Returns true if the le exists and if the le can be written to by your program. If the le does not exist, this method will create the le. The newly created le will be empty. This method returns true if the le is successfully created. Deletes the le. If the File object represents a directory, that directory must be empty in order for the directory to be deleted. This method returns true if the le is successfully deleted. This method will cause the le to be deleted as soon as your program exits. Returns true if the le exists. Returns the absolute path to this le. The absolute path contains the full path (beginning with a drive letter) on Windows platforms. Returns the lename of the le. Returns the path of the parent directory in which the le is located. If the le does not have a parent directory, this method returns null. For example, C:\ does not have a parent directory. Returns the path to this le. The path may be relative or absolute, depending on the path used to create the File object. Returns true if the File object represents a directory. Returns true if the File object represents a le. Returns when the le was last modied. The return value is in the form of a long. Typically, you will convert this long to a Date object. If the le does not exist, 0 is returned.

For a complete list of methods available in the File class, refer to the J2SE API documentation.

delete()

The delete() and deleteOnExit() methods cannot be undone. You should be careful when using the these methods.

deleteOnExit(); exists() getAbsolutePath()

getName() getParent()

The listRoots() method is staticmeaning that you dont need an available File object in order to use it. You can simply call File.listRoots() from anywhere within your program.

getPath()

isDirectory() isFile() lastModified()

Lesson 7: The java.io Package

211

Method
length() list()

Description
Returns the size of the le in bytes. If the le does not exist, 0 is returned. If the File object represents a directory, this method will perform a directory listing of that directory. This method returns an array of strings. Each element of the array represents one lename from the listing. Returns an array of File objects representing your computers local and mapped drives. Creates the directory represented by this File object. Returns true if the directory is successfully created. Creates the directory represented by this File object, including any necessary parent directories. Returns true if the directories are successfully created.

listRoots() mkdir()

mkdirs()

TASK 7A-1:
Working with the File Class
Objective: To use the File class to obtain information about a le. (You will not be modifying any les at this time.) 1. Open FileInfo.java and observe the contents of the le. This program contains two methods: main() and displayFileInfo(). The main() method has been written for you. It will display a le dialog box that will allow the user of the program to select a le. Your job will be to implement the displayFileInfo() method. This method takes one parametera stringwhich will indicate the le chosen by the user. In the displayFileInfo() method, create a le object which represents the le chosen by the user. Call the le object f. Remember that the string passed into the method you are writing contains the lename of the selected le. The code to create the le object is as follows:
public class FileInfo { public static void displayFileInfo( String filename ) { File f = new File( filename ); }

A le dialog box is created by using the FileDialog class. The FileDialog class can be found in the java.awt package.

2.

Now that you have created a le object, you can get information about that le.

212

Java 2 Programming for Developers

3.

Create an if statement that checks to see if the selected le exists by using the exists() method of the File class:
public class FileInfo { public static void displayFileInfo( String filename ) { File f = new File( filename ); if ( f.exists() ) { }

We only want to display information about the le, if the le exists. 4. Within the if statement, display the lename and directory of the selected le by using the getName() and getParent() methods of the File class.
public static void displayFileInfo( String filename ) { File f = new File( filename ); if ( f.exists() ) { System.out.println( "Filename: " + f.getName() ); System.out.println( "Directory: " + f.getParent() ); Steps 4 through 7 should be written within the if statement.

5.

Display the le size of the selected le by using the length() method of the File class:
public static void displayFileInfo( String filename ) { File f = new File( filename ); if ( f.exists() ) { System.out.println( "Filename: " + f.getName() ); System.out.println( "Directory: " + f.getParent() ); System.out.println( "Size: " + f.length() + " bytes" );

6.

Display the date in which the selected le was last modied by using the lastModified() method of the File class. Since the lastModified() method returns the date in the form of a long datatype, you should convert it to a Date object as you display it:
public static void displayFileInfo( String filename ) { File f = new File( filename ); if ( f.exists() ) { System.out.println( "Filename: " + f.getName() ); System.out.println( "Directory: " + f.getParent() ); System.out.println( "File Size: " + f.length() + " bytes" ); System.out.println( "Last Modified: " + new Date( f.lastModified() ) );
You can convert the long to a date by creating a new Date object and by passing the long into the constructor of the Date class.

Lesson 7: The java.io Package

213

7.

Display the le permissions of the selected le by using the canRead() and canWrite() methods of the File class:
public static void displayFileInfo( String filename ) { File f = new File( filename ); if ( f.exists() ) { System.out.println( "Filename: " + f.getName() ); System.out.println( "Directory: " + f.getParent() ); System.out.println( "File Size: " + f.length() + " bytes" ); System.out.println( "Last Modified: " + new Date( f.lastModified() ) ); System.out.println( "Readable: " + f.canRead() ); System.out.println( "Writable: " + f.canWrite() );

8.

Following the if statement, add an else statement to the method that will display a message to the user if the le never existed:
public static void displayFileInfo( String filename ) { File f = new File( filename ); if ( f.exists() ) { System.out.println( "Filename: " + f.getName() ); System.out.println( "Directory: " + f.getParent() ); System.out.println( "File Size: " + f.length() + " bytes" ); System.out.println( "Last Modified: " + new Date( f.lastModified() ) ); System.out.println( "Readable: " + f.canRead() ); System.out.println( "Writable: " + f.canWrite() ); } else { System.out.println( "The selected file does not exist!" ); } }

9.

Compile and run the program. When executed, the program displays a Choose A File dialog box:

214

Java 2 Programming for Developers

10. Select a le and click Open. Information about the le is displayed in the console window. This output should be similar to the following:
You can select any le for this step.

11. Run the program several more times and experiment by choosing different les on your computer. Observe the results for each le you choose. You should also try deliberately typing a lename that does not exist into the Choose A File dialog box to see how the program behaves.

Streams
In Java, information is written to and read from different places through the use of streams. The stream classes make up a huge subset of the java.io package. A stream can be thought of as a pipe of information that is used to move data from one place to another. Information is put into one end of the stream, and emerges at the other end. The java.io package contains many stream classes. Depending on what kind of I/O you need to perform, you will need to decide which stream class to use. Your rst decision is whether you need to use an input stream or an output stream.

stream: Apipe of information used to move data from one place to another.

Input Streams
Input streams are used to read bytes of data into your program. The source of this data could be either a le, a network connection, or even another part of your program. To create a new input stream, you need an available source of data. Depending on the particular source of data you have available, you will use a different input stream class. The following table lists some of the available input stream classes and describes their sources of data: Class
ByteArrayInputStream FileInputStream PipedInputStream

Description
Used to read data whose source is a byte array in memory. Used to read data from a le on your computer. Used to read data from another part of your program, usually from a different thread.

The InputStream class is abstract. Therefore, you will never use this class directly. Instead, you will use one of these subclasses, which extend InputStream.

Lesson 7: The java.io Package

215

Java also provides other input stream classes that are not used to create new input streams but, rather, to extend the functionality of an existing input stream. If you already have an input stream created, you can use one of these classes to make reading data more convenient. The following table lists some of these classes and describes the extended functionality they add to existing input streams: Class
BufferedInputStream

Description
Buffers the data from an input stream, resulting in more efcient reading of data. Also allows you to remember a location within the stream and read data from that location more than once. Contains methods that allow you to read primitive datatypes from an input stream without needing to know the details of how a particular operating system stores these primitive types. Allows you to read objects from an input stream. Allows you to place additional data into the input stream so that it can be read along with original data in the stream. Concatenates two (or more) input streams together. The concatenated input streams logically function as one large input stream.

DataInputStream

ObjectInputStream PushbackInputStream

SequenceInputStream

For example, if you wanted to create a buffered input stream from an already existing input stream, you would use the following code:
// the existing stream InputStream in; ... // the buffered input stream BufferedInputStream bufferedIn = new BufferedInputStream( in );

Output Streams
Output streams are used to write bytes of data to a destination. To create a new output stream, you will need to specify a destination for the data. Depending on where you will be writing your data to, you will use a different output stream class. The following table lists some of the available output stream classes:
The OutputStream class is abstract. Therefore, you will never use this class directly. Instead, you will use one of these subclasses, which extend OutputStream.

Class
ByteArrayOutputStream

Description
Used to write data to a byte array. The array can resize itself to accommodate more data when needed. Used to write data to a le on your computer. Used to write data to another part of your program (usually to a different thread).

FileOutputStream PipedOutputStream

Just as with input streams, Java provides other output stream classes that are used to extend the functionality of an existing output stream. The following table lists some of these classes and describes the extended functionality they add to existing output streams:

216

Java 2 Programming for Developers

Class
BufferedOutputStream DataOutputStream

Description
Buffers data prior to writing to an output stream. This results in more efcient writing of data. Contains methods that allow you to write primitive datatypes to an output stream without needing to know the details of how a particular operating system stores these primitive types. Allows you to write objects to an output stream. Contains methods that allow you to write primitive data types and strings to an output stream and, optionally, terminate data with new line characters.

ObjectOutputStream PrintStream

For example, if you wanted to create a data output stream from an already existing output stream, you would use the following code:
// the existing stream OutputStream out; ... // the data output stream DataOutputStream dataOut = new DataOutputStream( out );

TASK 7A-2:
Identifying Input and Output Streams
1. Match the input stream class with its corresponding functionality. b d a h f BufferedInputStream ByteArrayInputStream DataInputStream FileInputStream ObjectInputStream a. b. c. d. e. Allows you to read primitive datatypes from the input stream. Provides efficient reading of data through the use of buffering. Reads data from another thread within your program. Used to read bytes directly from an array. Allows you to place additional data back into the input stream so that it can be read as if it were part of the original data. Used to read objects from the input stream. Allows you to concatenate two or more input streams together. Reads data from a le on the users computer.

c e g

PipedInputStream PushbackInputStream SequenceInputStream

f. g. h.

Lesson 7: The java.io Package

217

2.

Match the output stream class with its corresponding functionality. f c e b BufferedOutputStream ByteArrayOutputStream DataOutputStream FileOutputStream a. b. c. d. Writes data to another thread in your program. Writes data to a le on the users computer. Used to write bytes directly to an array. Allows you to write primitive datatypes and strings to the output stream as well as terminate your data with new line characters. Allows you to write primitive datatypes to the output stream. Writes its data efficiently through the use of buffering. Used to write objects to the output stream.

g a d

ObjectOutputStream PipedOutputStream PrintStream

e. f. g.

Character Streams
Input and output streams read bytes of data. However, Java provides special versions of streams that read characters instead of bytes. Usually, byte streams are useful for reading binary data such as images, executable les, and others. Character streams, on the other hand, are useful when reading text-based les. There are two types of character streams in Java: readers and writers.

Readers
As their name suggests, readers read data into your program. Unlike input streams that read bytes, readers read characters. To create a new reader, you need an available source of data. Depending on the particular source of data you have available, you will use a different reader class. The following table lists some of the available reader classes and describes their sources of data: Class
CharArrayReader
The Reader class is abstract. Therefore, you will never use this class directly. Instead, you will use one of these subclasses, which extend Reader.

reader: A special type of input stream that reads characters instead of bytes.

Description
Used to read data whose source is a character array in memory. Used to read data from a le on your computer. Used to read data from another part of your program (usually from a different thread). Used to read data whose source is a string in memory.

FileReader PipedReader StringReader

Java also provides other reader classes that are not used to create new readers but, rather, to extend the functionality of an existing reader. If you already have a reader created, you can use one of these classes to make reading data more convenient. The following table lists some of these classes and describes the extended functionality they add to existing readers:

218

Java 2 Programming for Developers

Class
BufferedReader

Description
Buffers the data from a reader, resulting in more efcient reading of data. Also allows you to read lines of data by automatically locating new line characters for you. A specialized version of BufferedReader that allows you to keep track of line numbers. You can ask the reader for its current line number or read specic lines from the reader. Allows you to place additional data into the reader so that it can be read as if it were part of the original data in the reader.

LineNumberReader

PushbackReader

For example, if you wanted to create a line number reader from an already existing reader, you would use the following code:
// the existing reader Reader in; ... // the line number reader LineNumberReader lineNumberIn = new LineNumberReader( in );

Writers
Writers are used to write characters of data to a destination. To create a new writer, you will need to specify a destination for the data. Depending on where you will be writing your data to, you will use a different writer class. The following table lists some of the available writer classes: Class
CharArrayWriter

Description
Used to write data to a character array. The array can resize itself to accommodate more data when needed. Used to write data to a le on your computer. Used to write data to another part of your program (usually to a different thread). Used to write data to a string in memory.

writer: A special type of output stream that writes characters instead of bytes.

FileWriter PipedWriter StringWriter

The Writer class is abstract. Therefore, you will never use this class directly. Instead, you will use one of these subclasses which extend Writer.

Just like with readers, Java also provides other writer classes that are not used to create new writers but, rather, to extend the functionality of an existing writer. If you already have a writer created, you can use one of these classes to make writing data more convenient. The following table lists some of these classes and describes the extended functionality they add to existing writers: Class
BufferedWriter

Description
Buffers data prior to writing to the writer. This results in more efcient writing of data. Also allows you to write strings and platformindependent new line characters to the writer.

Lesson 7: The java.io Package

219

Class
PrintWriter

Description
Contains methods that allow you to write primitive data types and strings to the writer and, optionally, terminate data with new line characters.

For example, if you wanted to create a print writer from an already existing writer, you would use the following code:
// the existing writer Writer out; ... // the print writer PrintWriter printOut = new PrintWriter( out );

Converting Between Bytes and Characters


It was stated earlier that input and output streams read and write bytes. However, it is possible to read characters from and write characters to these streams by using the InputStreamReader and the OutputStreamWriter classes. These classes are used to convert byte streams to character streams. This is sometimes needed because you, as the programmer, may not have a choice as to what type of stream is used. For example, sockets communicate data at the byte level. In order to use characters with sockets, you need a way to convert your data. The InputStreamReader class allows you to read characters from an input stream that normally requires bytes to be read in. This is useful if you want to read textual data from an input stream. To create an input stream reader from an input stream, you would use the following code:
// the input stream InputStream in; ... // the input stream reader InputStreamReader charIn = new InputStreamReader( in );

The OutputStreamWriter class allows you to write characters to an output stream that normally requires bytes to be written to it. This is useful if you want to write textual data to an output stream. To create an output stream writer from an output stream, you would use the following code:
// the output stream OutputStream out; ... // the output stream writer OutputStreamWriter charOut = new OutputStreamWriter( out );

220

Java 2 Programming for Developers

TASK 7A-3:
Identifying Readers and Writers
1. Match the Reader class with its corresponding functionality. d BufferedReader a. Allows you to keep track of line numbers while reading data. Also allows you to read specic lines from the reader. Reads characters directly from an array. Reads characters directly from a string. Reads data efficiently through the use of buffering. Allows you to read characters from a byte stream. Allows you to place additional data back into the reader, so that it can be read as if it were part of the original data. Reads data from another thread within your program. Reads data from a le on the users computer. Allows you to write characters to a byte stream. Writes characters directly to a string. Efficiently writes data to the writer through the use of buffering. Allows you to write primitive datatypes and strings to the writer, as well as terminate your data with new line characters. Writes data to a le on the users computer. Writes data to another thread in your program. Writes characters directly into an array.

b h e a g

CharArrayReader FileReader InputStreamReader LineNumberReader PipedReader

b. c. d. e. f.

f c 2.

PushbackReader StringReader

g. h.

Match the Writer class with its corresponding functionality. c g e a BufferedWriter CharArrayWriter FileWriter OutputStreamWriter a. b. c. d.

f d b 3.

PipedWriter PrintWriter StringWriter

e. f. g.

When is it best to use readers and writers instead of input and output streams? It is best to use readers and writers when reading or writing text-based data.

Lesson 7: The java.io Package

221

Random Access Files


Usually when you read or write to a le, you do so in a sequential manner. You start out at the beginning of the le and continue reading until you reach the end of the le. All of the byte and character streams we have looked at so far read and write data sequentially. Sometimes, however, it is necessary to read and write to random locations within a le. That can be done using the RandomAccessFile class. A random access le is not a stream, nor is it a reader or writer. Instead, it can be thought of like a large array that represents the data in a le. You can read data from the array, or write data to the array. A random access le maintains a pointer to the current location in the array. You can get or set the pointer location at any time. The concept of the pointer is what allows random access to the particular le. The RandomAccessFile class is unique in that it contains methods for both reading and writing data. You can read and write many different types of data using the RandomAccessFile class, including all the primitive types and strings.

random access le: A le I/O technique that allows random, or nonsequential, access to a le. Data can be read from or written to any location in the le at any time.

Using a random access le requires a well-dened le format. You must know how the data in the le will be structured, otherwise you will not be able to locate information properly.

Console Input and Output


Throughout this course youve used the System.out.println() method to display text in the console window. System.out is a PrintStream object that has access to the window in which the current Java application was launched. The println() method converts any object parameter into a string and displays the string to the console followed by a new line character. PrintStream also denes a print() method which does not end with a new line character.

Reading Console Input


The java.lang.System class denes a property called in which references an InputStream object. As you have seen, Java provides mechanisms for handling the incoming stream of bytes. To manipulate input from the console, developers use two objects: InputStreamReaderwhich reads the character bytes and converts them into Unicode characters and BufferedReaderwhich includes a getLine() method to handle code input a single line at a time. The following code segment illustrates the process of capturing standard input.
String s; //A string to hold the input //A System.in reader that converts bytes to characters InputStreamReader ir = new InputStreamReader(System.in); //A reader that can handle input a line at a time BufferedReader in = new BufferedReader(ir); //A try-catch block to handle IOExceptions try { //Capture the input s = in.readLine(); } catch (IOException e){ }

222

Java 2 Programming for Developers

TASK 7A-4:
Reading Input from the Console
Objective: To read and process console input. 1. In your text editor, open C:\077954\Reader.java. The le contains a partially-completed class. Youll add code to the class that will capture and multiply two numbers typed into the console window. In the indicated region, add code that wraps the System.in stream with an InputStreamReader (to convert the bytes into characters) and a BufferedReader (to handle code a line at a time).
import java.io.*; class Reader { public static void main (String args[]) { String s[] = new String [2]; // Array of 2 Strings /* Create an InputStreamReader and a BufferedReader */ InputStreamReader ir = new InputStreamReader(System.in); BufferedReader input = new BufferedReader(ir);

2.

3.

In the indicated region, add code that uses the BufferedReader getLine() method to capture the rst line of input and assign it to the rst element in s (an array of Strings).
import java.io.*; class Reader { public static void main (String args[]) { String s[] = new String [2]; // Array of 2 Strings /* Create an InputStreamReader and a BufferedReader */ InputStreamReader ir = new InputStreamReader(System.in); BufferedReader input = new BufferedReader(ir); System.out.print("Enter a number: "); try { /*Capture the first line of input*/ s[0] = input.readLine();

Observe that the new code is wrapped in a try block. This is because readLine() can throw an IOException. 4. Next, add code to capture the second line of input. The second line of input can be captured after the program prints the Enter another number statement.
try { /*Capture the first line of input*/ s[0] = input.readLine(); System.out.print("Enter another number: "); /*Capture the second line of input*/ s[1] = input.readLine();

Lesson 7: The java.io Package

223

5.

Observe the nested try/catch block.


/*Convert the input Strings to ints and multiply*/ try { System.out.println("The product of "+s[0]+" and " + s[1] + " is: " +(Integer.parseInt(s[0])*Integer.parseInt(s[1]))); } catch (NumberFormatException e) { System.out.println( "There is something wrong with one of your nubmers. Try again."); }

This code converts the strings entered in the console to Integers and displays the product of the two numbers. This code is wrapped in a try/catch block because the conversion of the strings to Integers can result in a NumberFormatException being thrown. 6. Save, compile, and test the program by entering two numbers at the prompts. Your results should look similar to the following graphic.

Topic 7B
Reading Files
The ability to read les allows us to make our programs more useful. The alternative is to have a user enter information into the program by hand. Since this can be a time-consuming process, reading information from a le is much more desirable. Unfortunately, performing le I/O in other programming languages has sometimes been a challenge for programmers because of the following reasons: Poor documentation. Cryptic variables. Complicated, low-level system calls.

Java, on the other hand, eliminates these issues. As you saw in the last topic, Java provides an entire package of classes that allows you to perform I/O. All of these classes are well documented and provide you with an object-oriented approach to I/O.

224

Java 2 Programming for Developers

Steps to Reading a File


Reading a le usually involves the following steps: 1. 2. 3. 4. 5. Open the le. Read some data. Process the data. If there is more data, repeat step 2. Close the le.

The steps above have been graphically represented in Figure 7-1.


Process for Reading a File

Figure 7-1: Process for reading a le.

Opening the File


Before you can begin reading data from a le, the le needs to be opened. You can open a le using either the FileInputStream class or the FileReader class. Recall from the last topic that a le input stream reads bytes from the le and a le reader reads characters from the le. In this course, we will focus primarily on reading text les. For this reason, we will use a le reader as our example.
Lesson 7: The java.io Package 225

There are two options when creating a FileReader object. The rst is to create the reader using a string that contains a lename. For example:
File input streams are created in a similar manner.

String filename = "somefile.txt"; FileReader in = new FileReader( filename );

The other option is to create a le reader using a File object:


File f = new File( "somefile.txt" ); FileReader in = new FileReader( f );

If you attempt to open a le that does not exist using a le input stream or a le reader, a FileNotFoundException will be thrown. The compiler will remind you of this when you try to compile your code.

Once you have created a le reader, you have an option to extend its functionality by converting it to another type of reader. For example, you might want to convert your FileReader to a BufferedReader, so that you can read your le one line at a time. Assuming your le reader was called in, you could convert it to a buffered reader like this:
BufferedReader bufferedIn = new BufferedReader( in );

Reading and Processing Data


Depending on the type of input stream or reader you are using, different methods will be available to you for reading data. If you are using a le reader, you have two ways of reading data. The rst is to read data one character at a time. This is done by using the read() method of the FileReader class. There are actually three read() methods provided by a le reader. Each method takes different parameters. To read a single character from the le, you would use the method that takes no parameters. For example:
// create the file reader FileReader in = new FileReader( "somefile.txt" ); // read one character int tempChar = in.read(); // convert int to char char theChar = (char)tempChar;

The read() methods of the FileInputStream class are similar to those of the FileReader class, with the exception that they read bytes of data rather than characters of data.

The read() method will return the character as an int. Notice, in the code above, that the return value of the read() method is cast (converted) to a char. When the read() method returns -1, it means that there are no more characters in the le. In other words, you have reached the end of the le. Using this information, you can set up a loop that reads all the characters in the le:

226

Java 2 Programming for Developers

// create the file reader FileReader in = new FileReader( "somefile.txt" ); // read all the characters int tempChar; do { //read a character tempChar = in.read(); if ( tempChar >= 0 ) { // convert int to char char theChar = (char)tempChar; // process each character here ... } } while ( tempChar != -1 );

Your other option when reading data from a le reader is to read multiple characters at once. This is also done by using the read() method. The difference is that you pass a character array into the read() method as a parameter and the read() method will ll the array with data from the le. The return value of the read() method will be an int, telling you how many characters were placed into the character array. The following code segment demonstrates how to read multiple characters from a le:
// create the file reader FileReader in = new FileReader( "somefile.txt" ); // create a character array to hold the data char[] buffer = new char[100]; // create an int that keeps track of the // amount of data read in int charCount; // read a chunk of data charCount = in.read( buffer ); // process the data in the buffer ...

Notice that the read() method does not return a character array. Instead, you pass in your own array, and the read() method will ll it with data. You will know exactly how much data was placed in the array by examining the return value of the read() method. The following table describes the possible return values: Return Value
charCount == buffer.length

Meaning
If the return value equals the size of the character array, then it means the character array is completely lled. If the return value is less than the size of the character array, then it means that the character array is only partially lled.

charCount < buffer.length

Lesson 7: The java.io Package

227

Return Value
charCount == 0

Meaning
If the return value is 0, then it means that no data was placed in the character array. (This does not necessarily mean that there is no more data in the le.) If the return value is -1, then it means that there is no more data left in the le and that no data was placed in the character array.

charCount == -1

You can also create a loop that reads the entire le by reading multiple characters at a time:
// create the file reader FileReader in = new FileReader( "somefile.txt" ); // create a character array to hold the data char[] buffer = new char[100]; // create an int that keeps track of the // amount of data read in int charCount; // read in the entire file do { charCount = in.read( buffer ); // process the data in the buffer ... } while ( charCount != -1 );

Closing the File


When you are nished reading in data from a le, you should always close the le. This assures that any locks placed on the le by the operating system will be released. Any system resources used to read in the le will also be released. To close a le, you can call the close() method of the le reader. For example:
The close() method is available from all input streams and readers.

in.close();

TASK 7B-1:
Reading Data from a File
Objective: To implement the open le functionality of a text editor by reading in data from a le. 1.
Notice, in this task, that we have imported the java.io package. This package contains all the classes necessary for performing I/O.

Open TextEditor.java. You may compile and run the program if you wish. This program is a text editor that is missing itsopen le functionality. Your job will be to write this functionality. Locate the openFile() method. This is where you will write your code. The openFile() method takes one parameter, a string, which is the le that the user wants to open.

2.

228

Java 2 Programming for Developers

3.

In the openFile() method, create a new File object called inputFile. Initialize it so that it points to the le that is passed into the method:
public void openFile( String filename ) { File inputFile = new File( filename ); }

4.

Create a new empty string called data, that will eventually hold the entire contents of the le:
public void openFile( String filename ) { File inputFile = new File( filename ); String data = ""; }

5.

Create a character array called buffer, whose size is 1,024 characters. This array will be used to temporarily hold the data as it is read in from the le:
public void openFile( String filename ) { File inputFile = new File( filename ); String data = ""; char[] buffer = new char[1024]; }
1024 is a typical buffer size. If you prefer, you may choose a different buffer size.

6.

Create an integer variable called charCount that will be used to keep track of the number of characters read in from the le:
public void openFile( String filename ) { File inputFile = new File( filename ); String data = ""; char[] buffer = new char[1024]; int charCount; }

7.

Since we are going to be performing le I/O, there is a potential for exceptions to occur. Write a try and catch block that will handle any I/O exceptions that get thrown. The catch block should catch an IOException object and print out an error message. For example:
public void openFile( String filename ) { File inputFile = new File( filename ); String data = ""; char[] buffer = new char[1024]; int charCount; try { } catch ( IOException e System.out.println( inputFile.getName() System.out.println( }

) { "Could not open file: " + ); e.toString() );

Lesson 7: The java.io Package

229

8.

Within the try block, create a FileReader object called in. The reader should be initialized with the inputFile variable:
public void openFile( String filename ) { File inputFile = new File( filename ); String data = ""; char[] buffer = new char[1024]; int charCount; try { FileReader in = new FileReader( inputFile ); }

9.

Create a do-while loop that will continue looping while there is more data to be read:
public void openFile( String filename ) { File inputFile = new File( filename ); String data = ""; char[] buffer = new char[1024]; int charCount; try { FileReader in = new FileReader( inputFile ); do { } while( charCount != -1 );

When charCount equals -1, it means that there is no more data in the le. At this point, the loop will terminate. 10. Within the do-while loop, read in a chunk of data using the read() method of the le reader. Pass the character array called buffer into the read() method. The data will be stored in this buffer. Store the result of the read() method in the charCount variable:
Remember that a return value of -1 from the read() method will signify end of le.

try { FileReader in = new FileReader( inputFile ); do { charCount = in.read( buffer ); } while( charCount != -1 );

230

Java 2 Programming for Developers

11. If any data was read into the buffer, convert the data in the buffer to a string and append it to the data variable. Youll know when data is read in because charCount will be greater than 0. Remember that the buffer may not be completely lled. When you convert it to a string, be sure to use the appropriate String constructor, that allows you to specify a character array, the offset, and the number of characters to read from the buffer. The offset will be 0 and the number of characters is being held in the charCount variable:
try { FileReader in = new FileReader( inputFile ); do { charCount = in.read( buffer ); if ( charCount > 0 ) { String newData = new String( buffer, 0, charCount ); data += newData; } } while ( charCount != -1 );

12. Outside of the do-while loop, close the le reader:


do { charCount = in.read( buffer ); if ( charCount > 0 ) { String newData = new String( buffer, 0, charCount ); data += newData; } } while ( charCount != -1 ); in.close(); }

Remember that closing the le reader will release any system resources used to read the le, thus freeing up memory. 13. Prior to exiting the method, be sure to display the data in the text editor window. The text area in the window is named myTextArea, and the data is being held in the variable you created called data. Use the setText() method of the text area to display the data.
catch ( IOException e ) { System.out.println( "Could not open file: " + inputFile.getName() ); System.out.println( e.toString() ); } myTextArea.setText( data );

Lesson 7: The java.io Package

231

14. Observe your code. At this point, your method should look similar to the following:
public void openFile( String filename ) { File inputFile = new File( filename ); String data = ""; char[] buffer = new char[1024]; int charCount; try { FileReader in = new FileReader( inputFile ); do { charCount = in.read( buffer ); if ( charCount > 0 ) { String newData = new String( buffer, 0, charCount ); data += newData; } } while ( charCount != -1 ); in.close(); } catch ( IOException e ) { System.out.println( "Could not open file: " + inputFile.getName() ); System.out.println( e.toString() ); } myTextArea.setText( data ); }

15. Compile and run the program. The text editor window is displayed.

232

Java 2 Programming for Developers

16. Open a le in the text editor. This can be done by choosing FileOpen. Use the dialog box to choose a text le. Your le will be displayed in the text editor window.

Topic 7C
Writing Files
The ability to write les enables data persistence. This means that data can exist long after our programs have terminated. Some of the reasons we need to store data outside of our programs include: Giving a user the ability to save their work. Backing up data. Exporting data from one system in order to be imported into another system.

The term text le refers to any text-based, non-binary le, which could include a Java source le, HTML le, etc.

On some operating systems, Java text areas have a limit as to how much text they can display. If you open a large le and nothing is displayed, the le may be too large for the text area.

Steps to Writing a File


Writing a le usually involves the following steps: 1. Open the le. 2. 3. 4. Write some data. If there is more data, repeat step 2. Close the le.
Notice that the process for writing a le is very similar to the process for reading a le.

The steps above have been graphically represented in Figure 7-2.

Process for Writing a File

Lesson 7: The java.io Package

233

Figure 7-2: Process for writing a le.

Opening the File for Writing


Before you can begin writing data to a le, the le needs to be opened. Even if the le you are writing to does not yet exist, the le still needs to be opened. You can open a le for writing by using either the FileOutputStream class or the FileWriter class. The difference between the two is that a le input stream writes bytes to a le and a le writer writes characters to a le. In this course, you will focus primarily on writing text les. For this reason, this example will use a le writer.

234

Java 2 Programming for Developers

When you create a le writer, you have a couple choices to make. The FileWriter class provides three different constructors. The following table describes these constructors: Constructor
FileWriter( File file )

Description
Opens the le, indicated by the specied File object, for writing. The target le will be overwritten by any new data you write to it. Opens the le, indicated by the specied String object, for writing. The target le will be overwritten by any new data you write to it. Opens the le, indicated by the specied String object, for writing. If the append parameter is true, any data you write to the le will be appended to the end of the le. If the append parameter is false, the le is overwritten by any new data you write to it.

The FileOutputStream class provides three similar constructors.

FileWriter( String name )

FileWriter( String name, boolean append )

A FileNotFoundException will be thrown if you attempt to open a read-only le with a le writer or a le input stream. The compiler will remind you of this when you try to compile your code.

For example, to create a new le writer, you would use the following code:
File f = new File( "somefile.txt" ); FileWriter out = new FileWriter( f );
Appending data is useful for implementing a log le. Log les are typically added to, not overwritten.

Or, if you prefer not to use a File object, you can simply use a string:
FileWriter out = new FileWriter( "somefile.txt" );

Once you have created a le writer, you have an option to extend its functionality by converting it to another type of reader. For example, you might want to convert your FileWriter object to a PrintWriter object so that you can conveniently write primitive data types to the le. Assuming your le writer was called out, you could convert it to a print writer like this:
PrintWriter printOut = new PrintWriter( out );

Writing Data
When you wanted to read data from a le, you used the read() method of the FileReader class. To write data to a le, you will need to use the write() method of the FileWriter class. There are ve write() methods provided by the FileWriter class. The following table describes these methods: Method
write( char[] buffer ) write( char[] buffer, int offset, int length )

Description
Writes the data from the specied character array to the le. Writes a portion of the specied character array to the le. The offset parameter tells the le writer where in the array the data is located. The length parameter species how much data to use from the buffer starting from the offset location. Writes the specied character to the le. Even though this method takes an int as a parameter, you can safely pass a char to it without receiving any errors. Writes the specied string to the le.

write( int c )

write( String s )

Lesson 7: The java.io Package

235

Method
write( String s, int offset, int length );

Description
Writes a portion of the specied string to the le. The offset parameter tells the le writer where in the string the data is located. The length parameter species how much data to use from the string, starting from the offset location.

When you write data to a le using a le writer, you have three choices: you can write one character at a time, several characters at once using an array or characters, or several characters at once using a String object.

Closing the File


When you nished reading data from a le, you needed to close the le. The same is true when you are writing data to a le. When you have nished writing all your data to the le, you should use the close() method of the le writer to close the le. For example:
The close() method is available from all output streams and writers.

out.close();

Closing the le does two things. First, it commits the changes that you made to the le. If you do not close the le, there is a chance that your le will not be saved. Closing the le will also assure that any system resources used to write to le to disk will also be released.

TASK 7C-1:
Writing Data to a File
Objective: To implement the Save As functionality of a text editor by writing data to a le. You will also use a string reader to read data from a string. Setup: Task 7B-1 has been completed. 1. If necessary, open TextEditor.java. You may compile and run the program if you wish. This program is a text editor that is missing its Save As functionality. Your job will be to write this functionality. Locate the saveFile() method. This is where you will be writing your code. The saveFile() method takes one parameter, a string, which is the le that the user wants to save to. In the saveFile() method, create a new File object called outputFile. Initialize it so that it points to the le that is passed into the method:
File outputFile = new File( filename );

2.

3.

4.

Create a character array called buffer whose size is 1,024 characters. This array will be used to temporarily hold the data as it is written to the le:
char[] buffer = new char[1024];

236

Java 2 Programming for Developers

5.

Create an integer variable called charCount that will be used to keep track of the number of characters written to the le:
int charCount;

6.

Since we are going to be performing le I/O, there is a potential for exceptions to occur. Write a try and catch block that will handle any I/O exceptions that get thrown. The catch block should catch an IOException object and print out an error message. For example:
try { } catch ( IOException e ) { System.out.println( "Could not save file: " + outputFile.getName() ); System.out.println( e.toString() ); }

7.

Within the try block, create a StringReader object called data. The reader will be reading the contents of the text area in the text editor window. The text area is named myTextArea. Use the text areas getText() method to retrieve the text from the text area:
StringReader data = new StringReader( myTextArea.getText() );

8.

Create a FileWriter object called out. The writer should be initialized with the outputFile variable:
FileWriter out = new FileWriter( outputFile );

9.

Create a do-while loop that will continue looping while there is more data to be read from the text area:
do { } while( charCount != -1 );

When charCount equals -1, the loop will terminate because there is no more data in the text area. 10. Within the do-while loop, read a chunk of data using the read() method of the string reader. Pass the character array called buffer into the read() method. The data will be stored in this buffer. Store the result of the read() method in the charCount variable:
charCount = data.read( buffer );

11. If any data was read into the buffer, write the data that is being held in the buffer out to the le. Youll know when data is available in the buffer because charCount will be greater than 0. Remember that the buffer may not be completely lled. When you use the write() method of the le writer, be sure to specify the offset and amount of data in the buffer. The offset will be 0 and the number of characters is being held in the charCount variable:
if ( charCount > 0 ) { out.write( buffer, 0, charCount ); }

Using a le writer, you could write the entire contents of the text area to the le at once. However, it is a better practice to use a string reader and perform the I/O in chunks, especially with larger les.

Lesson 7: The java.io Package

237

12. Outside of the do-while loop, close the string reader and the le writer:
data.close(); out.close();

13. Observe your code. At this point, your method should look similar to the following:
public void saveFile( String filename ) { File outputFile = new File( filename ); char[] buffer = new char[1024]; int charCount; try { StringReader data = new StringReader (myTextArea.getText()); FileWriter out = new FileWriter( outputFile ); do { charCount = data.read( buffer ); if ( charCount > 0 ) { out.write( buffer, 0, charCount ); } } while( charCount != -1 ); data.close(); out.close(); } catch ( IOException e ) { System.out.println( "Could not save file: " + outputFile.getName() ); System.out.println( e.toString() ); } }

14. Compile and run the program. The text editor window is displayed:

15. Type some text into the text editor window.

238

Java 2 Programming for Developers

16. Try saving the le. This can be done by choosing FileSave As. Use the dialog box to specify a lename to save to.

Apply Your Knowledge 7-1


Creating a Copy Program
Objective: To write a copy program using your knowledge of le I/O. Create a copy program that copies a source le to a destination le. You can either create the program from scratch, or use the le CopyMachine.java, located in the C:\077954 folder, as a starting point. This le contains the functionality to display two le dialog boxes to a userone for selecting a source le, and another for selecting a destination le. Note: If you want your copy machine to be able to copy binary les, you may want to use a byte stream rather than a character stream. Once the two les are selected, the program calls the copyFile() method and passes it two strings; one for the source le, the other for the destination le. Your job is to implement the copyFile() method. You may implement your solution using any of the available classes in the java.io package.

If you re-open the le you just saved in Notepad, you may nd that Notepad does not properly display new lines in your le. This is due to Javas text area using a different new line character combination than what Notepad uses. It is not an error in your code.

Suggested Time: 1 Hour

A possible solution to this AYK can be found in the le CopyMachine.java, which is in the Solutions folder.

Apply Your Knowledge 7-2


Creating a Log Program
Create a log program that, when executed, will append the current date and time to a le called log.txt. Your program will not overwrite the le but, rather, append to it. For example, if you run the program ve times, you should see ve date/time stamps in the le. To obtain the current date and time, you can use the Date class located in the java.util package. This program has been started for you in the le Logger.java.

Suggested Time: 30 Minutes

A possible solution to this AYK can be found in the le Logger.java.

Topic 7D
Reading and Writing Objects
Earlier in this lesson, you examined the ObjectInputStream and ObjectOutputStream classes. These classes are used to read objects from and write objects to a stream. The destination of this stream could be either across the network or into a le. This raises some interesting questions. If a network transmits information using bits and bytes, how is it possible to transmit an entire object over the network? Also, if a le system stores information in bytes, how is it possible to store an object in a le? The answer to both of these questions is object serialization.

Lesson 7: The java.io Package

239

Object Serialization
Object serialization is the process of converting an object into a series of bytes. These bytes contain enough information to reconstruct a copy of the object at a later time. The reason for serializing an object is so that the object can be written to and read from a byte stream. Specically, the object can be transmitted across a network, or written to and then restored from a le. How many bytes of data are required to reconstruct an object will depend on the particular object. Consider the following class:
public class Person { public static int MALE = 0; public static int FEMALE = 1; private String name; private int sex; private Date birthdate; public String getName() { return name; } public void setName( String name ) { this.name = name; } // additional methods here ... }

object serialization: The process of converting an object into a series of bytes, which can be used to reconstruct the object at a later time.

Some of the methods of the Person class have been omitted.

The Person class above contains two constants (static variables): MALE and FEMALE. It also contains the name, sex, and birthdate elds (global variables). In addition, the Person class contains several methods used to get and set the values of the three elds. If we wanted to serialize an instance of the Person class, so that it could be reconstructed at a later date, how much information would be needed? To answer this question, consider two instances of the Person class:
Person p1 = new Person(); Person p2 = new Person(); // manipulate both person objects here ...

At any one point in time, what distinguishes p1 from p2? The methods of both objects are identical because the methods are dened in the Person class and each object is an instance of this class. The constant values, MALE and FEMALE, are shared between both objects, meaning they are identical as well. The only differences between the two objects are the eldsname, sex, and birthdate. The values of these elds, or global variables, distinguish one Person object from another. Therefore, when we serialize an object, we only need to be concerned with the data contained within the objects global variables. It is this data that is needed to reconstruct a copy of the original object. An objects methods and static variables are not needed in order to reconstruct an object because that particular data can be obtained from the objects class denition.
240 Java 2 Programming for Developers

Performing Object Serialization


Object serialization can be performed in one of two ways. The rst is to let Java perform the serialization for you. This is called default serialization. In order for an class to be considered serializable, the class must implement the Serializable interface, found in the java.io package. The Serializable interface does not dene any methods. In fact, its denition is completely empty. When you implement the Serializable interface, you are telling Java that you want to allow objects, which are instances of your class, to be serialized. For example, to make the Person class serializable, you would add the following code to the class:
public class Person implements Serializable { ... }
Many classes built in to Java already implement the Serializable interface. These classes include String, Date, Vector, and many others.

default serialization: The built-in mechanism that performs object serialization automatically.

Your class is now serializable, and objects that are instances of your class can be sent across a network or stored in a le. Making this happen is the work of the ObjectOutputStream and ObjectInputStream classes, but well look at that shortly. The only restriction to using default serialization is that all the global variables in your class must, themselves, be serializable. If you attempt to serialize an object that contains non-serializable variables, a NotSerializableException will be thrown.

Customized Object Serialization


Default serialization does have its drawbacks. Since it has to examine the object and decide which data to serialize, default serialization can be slow. It also has a tendency to store more data than is needed. There is also the problem, as was just mentioned, when using default serialization. All the global variables contained within your class must also be serializable. If even one variable is not serializable, you cannot use default serialization. The biggest drawback, however, is the fact that recompiling your program can actually cause default serialization to fail. For example, imagine you serialize an object and write that object out to a le on your hard drive. You then modify your serializable class and recompile your program. Chances are, the serialized object on your hard drive is no longer compatible with your program. This is because the new version of your program serializes the object differently and it cant gure out how to reconstruct the object from its old serialized form. To avoid the problems mentioned above, you can implement custom serialization for your classes. This is done by specifying the data that gets serialized and the order in which the data gets serialized. To do so, your class still needs to implement the Serializable interface. You then implement two special methods that perform the customized serialization. The rst method, writeObject(), is where you specify how your class is serialized. You must implement this method exactly as shown below:
private void writeObject( ObjectOutputStream out ) throws IOException { }

If you attempt to serialize an object that contains nonserializable variables, a NotSerializable Exception will be thrown.

If you are using default serialization and you recompile your program, you run the risk of problems when trying to reconstruct old versions of serialized objects.

custom serialization: A mechanism that explicitly denes how a class is serialized.

Lesson 7: The java.io Package

241

When an instance of your class is serialized, your writeObject() method will be invoked. An ObjectOutputStream object is passed as a parameter. You use this output stream to write out your data that you want serialized. The ObjectOutputStream class contains many methods for writing data to the stream. The following table lists some of these methods:
Notice that the ObjectOutputStream class does not provide a writeString() method. Instead, to write a string, you can use the writeUTF() method.

Method
writeBoolean( b ) writeByte( b ) writeChar( c ) writeDouble( d ) writeFloat( f ) writeInt( i ) writeLong( l ) writeObject( obj ) writeShort( s ) writeUTF( string )

Description
Writes a boolean value to the stream. Writes a byte to the stream. Writes a character to the stream. Writes a double value to the stream. Writes a oat value to the stream. Writes an integer value to the stream. Writes a long value to the stream. Writes an object to the stream. The object must implement the Serializable interface. Writes a short value to the stream. Writes a UTF-encoded string to the stream. UTF simply means the encoding method used to write the string.

Within your writeObject() method, you invoke the appropriate ObjectOutputStream method for each global variable in your class. For example, the writeObject() method for the Person class could be implemented as follows:
private void writeObject( ObjectOutputStream out ) throws IOException { out.writeUTF( name ); out.writeInt( sex ); out.writeObject( birthdate ); }

Notice that when you serialize the birthdate variable, you need to use the writeObject() method, because there is no writeDate() method available from the ObjectOutputStream class. Custom serialization also allows you to serialize an object whose global variables are not all serializable. For such variables, you can either choose to not write them to the stream, or to write an alternative form of data to the stream that is serializable. The alternative piece of data can be used later, to reconstruct the non-serializable piece of data. For example, the Image class is not serializable, meaning you cannot use default serialization to serialize an object that has an Image object as a global variable. You could, using custom serialization however, serialize the images lename and then use that lename at a later time to re-create the object in the Image object. This approach allows you serialize almost anything. The other method your class needs to implement in order to perform custom serialization, is the readObject() method. This method species how to reconstruct a serialized copy of an object that is an instance of your class. You must implement this method exactly as shown here:

242

Java 2 Programming for Developers

private void readObject( ObjectInputStream in ) throws IOException { }

When an object input stream attempts to reconstruct an instance of your class, your readObject() method will be invoked. You will be passed an ObjectInputStream object as a parameter. You use this input stream to read data from the serialized copy of the object. The ObjectInputStream class contains many methods for reading data from the stream. Every writeXXX() method of the ObjectOutputStream class has a corresponding readXXX() method in the ObjectInputStream class. When you implement your readObject() method, you must read the data from the stream in the same order as you wrote it out when the object was originally serialized. As you read in the data, you store it in the variables from which it originally came from. When you have nished, you are left with a copy of the original object. For example, the readObject() method for the Person class could be implemented as follows:
private void readObject( ObjectInputStream in ) throws IOException { name = in.readUTF(); sex = in.readInt(); birthdate = (Date)in.readObject(); }

Notice that when you restore the birthdate eld, you need to cast the result of the readObject() method to the appropriate class type. This is because readObject() will always return an Object. Using custom serialization is more work than using default serialization, but it provides you with more control on how your class is serialized. It also allows you to serialize objects that contain non-serializable data by serializing alternative data that achieves the same result. Your class is also less likely to experience problems caused by recompiling your code when you make changes to your program.

Writing an Object to a File


Writing an object to a le is fairly straightforward, once you understand object serialization. You simply create a le output stream, convert it to an object output stream, and then write an object to the stream. You then close the stream and are left with a serialized copy of an object, stored on your hard drive. As mentioned earlier, in order to write an object to a stream, the object must be serializable. To write a serialized copy of a Person object to a le called person.obj, you would use the following code:
// create the person object Person p = new Person(); p.setName( "John Doe" ); p.setSex( Person.MALE ); p.setBirthdate( new Date() ); // write the object to disk FileOutputStream fileOut = new FileOutputStream( "person.obj" ); ObjectOutputStream out = new ObjectOutputStream( fileOut ); out.writeObject( p ); out.close();

Lesson 7: The java.io Package

243

Reading an Object from a File


Reading an object from a le is similar to writing an object to a le. To do so, you create a le input stream, convert it to an object input stream, and read the object from the stream. In order to reconstruct the object successfully, you must have the objects class available on your system. For example, if you serialize a Person object, the Person class must be accessible by the Java Virtual Machine when you try to reconstruct the object. If the class is not found on your system, a ClassNotFoundException will be thrown. To reconstruct a serialized copy of a Person object from a le called person.obj, you would use the following code:
// read in the object FileInputStream fileIn = new FileInputStream( "person.obj" ); ObjectInputStream in = new ObjectInputStream( fileIn ); Object obj = in.readObject(); in.close(); // cast the reconstructed object to a person object Person p = (Person)obj; // use the person object ...

When reading an object from an object input stream, the objects class must be available on your system. If it is not, a Class NotFoundException will be thrown.

Notice that the readObject() method returns an Object. Before you can use the object as a Person object, you must cast it to a Person object.

TASK 7D-1:
Serializing an Object
Objective: To practice serializing an object and reconstructing a serialized copy of an object. 1. 2. Open the le Address.java and observe its contents. The Address class contains several constants, elds, and methods. To make the Address class serializable, add the following code to the class declaration:
public class Address implements Serializable {

3.

Locate the main() method of the program. Within the main() method, create a new Address object called myAddress:
Address myAddress = new Address();

4.

Use the methods of the Address class to populate the objects data. For example:
myAddress.setName( "Janice Smith" ); myAddress.setStreet( "500 Canal View Blvd." ); myAddress.setCity( "Rochester" ); myAddress.setState( "NY" ); myAddress.setZip( 14623 ); myAddress.setType( Address.BUSINESS );

In this step, substitute your own personal information for ours.

244

Java 2 Programming for Developers

5.

Within the rst try block, serialize the object and save it in a le called address.obj. Create a le output stream, convert it to an object output stream and then write the object to the stream. Dont forget to close the stream after you write out the object. Include a message to the user that signies that the object was successfully serialized:
FileOutputStream fileOut = new FileOutputStream( "address.obj" ); ObjectOutputStream out = new ObjectOutputStream( fileOut ); out.writeObject( myAddress ); out.close(); System.out.println( "Object successfully serialized..." );

6.

Within the second try block, restore the object from the saved le. Create a le input stream, convert it to an object input stream and then read the serialized object from the stream. Save the restored object in a variable called myAddressCopy. Include a message to the user that signies that the object was successfully deserialized:
FileInputStream fileIn = new FileInputStream( "address.obj" ); ObjectInputStream in = new ObjectInputStream( fileIn ); Address myAddressCopy = (Address)in.readObject(); in.close(); System.out.println( "Object successfully deserialized..." );

7.

To verify that the data has been restored properly, output the objects data to the screen:
System.out.println( System.out.println( System.out.println( System.out.println( System.out.println( System.out.println( "Name: " + myAddressCopy.getName() ); "Street: " + myAddressCopy.getStreet() ); "City: " + myAddressCopy.getCity() ); "State: " + myAddressCopy.getState() ); "Zip: " + myAddressCopy.getZip() ); "Type: " + myAddressCopy.getType() );

8.

Compile and run the program. Compare your results with the following:

9.

In Notepad, open address.obj and observe the contents of the le. The le contains the serialized copy of the Address object you created. The le contains binary data that, while it may not mean much to the human eye, can still be used to reconstruct your Address object at any time.

Lesson 7: The java.io Package

245

Suggested Time: 30 Minutes

CHECK YOUR SKILLS 7-1


Implementing Custom Serialization
1. How much data from an Address object in Task 7D-1 needs to be saved in order to reconstruct the object at a later time? The only data that needs to be saved are the global variables of the class. They consist of name, street, city, state, zip, and type. 2. Implement custom serialization for the Address class in Task 7D-1. You will need to implement both the writeObject() method and the readObject() method. You should only serialize the data that is absolutely required to restore the object at a later time. These methods are illustrated in the code segment below:
private void writeObject( ObjectOutputStream out ) throws IOException { out.writeUTF( name ); out.writeUTF( street ); out.writeUTF( city ); out.writeUTF( state ); out.writeInt( zip ); out.writeInt( type ); } private void readObject( ObjectInputStream in ) throws IOException { name = in.readUTF(); street = in.readUTF(); city = in.readUTF(); state = in.readUTF(); zip = in.readInt(); type = in.readInt(); }

3.

Compile and run the program. The output of the program should be the same. The difference is that you are using more efficient serialization because you wrote your own custom serialization routines.

Summary
In this lesson, you learned about I/O in Java, concentrating on le I/O. You explored the java.io package and the services that it provides. You learned how to read data from and write data to a le. You also learned about object serialization and how you can use it to store objects in a le and restore them at a later time.

246

Java 2 Programming for Developers

Lesson Review
7A What is the purpose of the File class?
The File class is used to encapsulate the properties of a le or directory. Why is using a File object, instead of a string, better for representing a le on your computer? A string can only represent the lename. A File object can provide much more information about the le, such as le size. How do standard input and output streams differ from readers and writers? Input and output streams read and write bytes of data, while readers and writers read and write characters of data. When would you use an input stream versus a reader? You would use an input stream when reading binary data. A reader should be used when reading textual data. What is special about the RandomAccessFile class compared with other classes in the java.io package? Answers could include: The RandomAccessFile class can both read and write data. Other classes, such as byte and character streams, have separate classes for input and output. The RandomAccessFile class can read and write data to random locations within the le. Other classes, such as byte and character streams, can only read or write data sequentially.

What kind of data can you read and write using the RandomAccessFile class? You can read and write all the primitive types and strings.

7B How do you create a FileReader object?


You can either create a FileReader object by using a string:
FileReader in = new FileReader( "somefile.txt" );

. . .or by using a File object:


File f = new File( "somefile.txt" ); FileReader in = new FileReader( f );

When you are nished reading data from a le, what should you do? You should always close the le when are done reading data from it. This can be done by using the close() method of the FileReader class.

7C When would you want to append to a le rather than overwrite it?


When you need to preserve the data already in the le and you simply want to add to it. For example, when writing to a log le.
Lesson 7: The java.io Package 247

Why is closing a le so important after writing to it? Because closing a le commits your changes and writes the le to disk. If you dont close a le, there is a chance the le will not be saved.

7D What is object serialization?


Object serialization is the process of converting an object into a series of bytes, which can be used to reconstruct the object at a later time. What are the drawbacks to default serialization? Answers may include: Its not effcient. You cannot serialize an object using default serialization if that object contains other, non-serializable data. Recompiling your program may cause default serialization to fail when restoring old versions of serialized objects.

What classes are used to read and write objects? ObjectInputStream and ObjectOutputStream.

248

Java 2 Programming for Developers

Multi-threaded Programming
Overview
One of Javas many strengths is the languages built-in support for multithreaded programming. Simply put, multi-threaded programming allows your program to perform two or more tasks concurrently. Other programming languages require library extensions or other updates in order to support multiple threads. With Java, however, this functionality is built-in and very easy to use.

LESSON

8
Data Files ThreadDemo.java Counter.java LightShow.java ProducerConsumer.java Lesson Time 3 hours, 30 minutes

Objectives
To be able to perform programming tasks concurrently, you will: 8A Dene and discuss multi-threaded programming. Before you can learn how to use threads, you need to explore where the idea of concurrently performing tasks came from. You will see how computers evolved to be able to execute multiple programs at the same time and how this idea translates to multi-threaded programming. 8B Use multiple threads in your programs. Just as a computer can have multiple programs running on it, a program can have multiple threads running within it. You will learn how to use multiple threads in the Java programming language. 8C Synchronize multi-threaded programs. Multi-threaded programs can cause problems when accessing shared data between threads. You will learn how to properly synchronize threads in order to avoid potential problems.

Lesson 8: Multi-threaded Programming

249

Topic 8A
Overview of Threads
The very rst computers were designed to execute one program. You loaded the program, the program executed, and you got your output. A typical program might have taken hours or even days to execute. If you had more than one program to run, you would have to be prepared to load the new program into the computer after the current one had nished executing. After a while, computers were redesigned so that programs could be batch processed. With this new approach, several programs were loaded into a computer. The computer would execute each program one-by-one, until all the programs had been executed. This was a revolutionary idea because programmers no longer had to wait around for their programs to nish executing. They could load several programs into the computer and come back the next day to nd all the programs were complete and the output for each program was waiting for them. Figure 8-1 illustrates three programs that have been batch processed and their relationship over time.
Three Batched Programs

Figure 8-1: Three batched programs. Batch processing was a major step forward for computers. Then, programmers noticed that their programs were not utilizing 100 percent of the computers processor. They noticed that the program was often sitting idle waiting for a device, such as a disk drive, to become available. This was unfortunate because it meant that a computers processing power was being wasted on a program that didnt even require the processor.
The discussions in this lesson assume that you are programming on a computer with only one processor. A single processor computer can execute processes at virtually the same time. A multi-processor computer can actually execute multiple processes at the same time.

Then came the idea of allowing batched programs to share the computers processor. Each program would be given a set amount of time to use the processor. If a particular program didnt need the processor at any given time, it would benet the other programs because they would get more processor time. These new computers were referred to as multi-process computers. Each program was considered a process, and a multi-process computer could concurrently run multiple processes.

250

Java 2 Programming for Developers

The result of multi-process computers is that programs took slightly longer to run. This is because each program had to share the processor with all other programs. The time it took to execute the entire batch of programs, however, signicantly decreased. This is illustrated in Figure 8-2.
Batch Processing vs. Multiprocess Computers

Figure 8-2: Batch processing vs. multi-process computers. Notice in Figure 8-2 that each program takes slightly longer to execute, but all three programs nish executing sooner with a multi-process computer.

TASK 8A-1:
Observing a Computers Processes
Objective: To observe the many processes running concurrently on your computer. 1. Press [Ctrl][Alt][Delete] simultaneously. The Windows Security dialog box is displayed.

Lesson 8: Multi-threaded Programming

251

2.

Click on the Task Manager button. The Windows NT Task Manager is displayed.

3.

Select the Processes tab. A list of all the processes running on your computer is displayed.

252

Java 2 Programming for Developers

4.

Observe the list of processes. Notice that, at any one time, your computer is executing many processes. By looking at the CPU column, you can determine how much processor time each process is receiving. Most processes sit idle until they are needed. They use the processor, and then go right back to being idle. You can see the total usage of your computers processor by looking at the CPU usage indicator at the bottom of the Task Manager.

5.

Using your mouse, drag the Task Manager around the screen and observe the CPU usage indicator. Your CPU usage should increase as you drag windows around the screen. As you do more with your computer, more processor usage will be required. The more the processor is used, the less each individual process will get to use the processor, and thus, your computer slows down.

Threads
You have just seen how a computer can execute multiple programs, or processes, concurrently. Programs, too, can contain multiple smaller programs. These smaller programs are called threads. A thread can be thought of like a mini program. Technically though, a thread is dened as an individual ow of control within a program. Programs can contain multiple threads, all of which can be executing concurrently. All Java programs have at least one thread, the main thread. The main thread is created by the Java Virtual Machine and it is this thread that executes the code in your main() method. As you call other methods from your main() method, the ow of control of your program is passed around to other methods. Consider the following code:
public static void main( String[] args ) P someMethod(); } public static void someMethod() { // do something here }

thread: Individual ow of control within a program. Can also be thought of like a mini program.

Suppose someMethod() takes 10 seconds to execute. That would mean that the ow of control would not be returned to your main method for 10 seconds. Figure 8-3 illustrates the control ow of this code.
Control Flow for a Single Thread

Lesson 8: Multi-threaded Programming

253

Figure 8-3: Control ow for a single thread. An alternative would be for the main() method to create a separate thread, or ow of control, that executes someMethod(). The advantage to this is that someMethod() is executed independently of the main() method. This is shown in Figure 8-4.
Control Flow of a Program with Two Threads

254

Java 2 Programming for Developers

Figure 8-4: Control ow of a program with two threads. Notice, in Figure 8-4, that the ow of control is never taken away from the main() method. Instead, a new ow of control is created and used to execute someMethod(). Processors are able to execute multiple processes concurrently by allowing each process to share processor time. The same is true of threads. While a program can concurrently execute many threads, only one thread is actually executing at any one time. When a thread sits idle, or no longer needs the processor, another thread is allowed to execute. To the human eye, however, it appears that all threads are executing at the same time. From within your program, you can create your own threads to perform tasks such as animation, background processing, or anything else that you need to happen concurrently with the execution of the rest of your program.

Lesson 8: Multi-threaded Programming

255

TASK 8A-2:
Observing a Multi-threaded Program
1.
Feel free to take a look at the source code to this program. If you dont understand the code right now, thats okay. You will have a chance to write your own multithreaded program a little later.

Compile and run the program located in ThreadDemo.java. This program demonstrates the performance differences between a single thread program and a multi-threaded program. The program completes ve tasks. Each task will take a random amount of time to complete. Compare your output with the following:

2.

The program noties you when it is entering and exiting the main() method and when it is performing tasks. Notice that the main() method cannot complete until all the tasks have completed. Also, notice that each task may not begin until the previous task has completed. This is because the program only contains one thread, or ow of control. 3. You will now run the program againonly this time, you will put the program into multi-threaded mode. At the command prompt, type the following:
java ThreadDemo mt

The command-line argument mt tells the program to run in multi-threaded mode. In this mode, the program creates a new thread for every task. This

256

Java 2 Programming for Developers

means that the tasks will execute independently of each other and of the main() method. 4. Compare your output with the following:

Notice that the main() method completes almost immediately. It does not have to wait for the tasks, because the tasks are on their own threads. The tasks execute concurrently and independently. You should have also noticed that the program takes much less time to complete while in multi-threaded mode.

Topic 8B
Using Threads
Java programs need an entry point, that is, a place where execution begins. This entry point for a program is the main() method. Threads, too, need an entry point. The entry point for threads is the run() method. Threads rely on objects that contain this method. To specify to a thread that an object contains the run() method, that objects needs to implement the Runnable interface. The Runnable interface species that an object contains the run() method. The syntax of the run() method is as follows:
public void run() { ... }
The Runnable interface is located in the java.lang package.

Notice that the run() method takes no parameters and does not return a value. Inside the run() method is where you would place the code that you want executed on a separate thread. Within this method, you can make calls to other methods, create local variables, and access global variables. By specifying a run() method, you have not made your program multithreaded. You have simply dened the code that you want executed on a separate thread. The next step is to create a new thread that can execute your run() method. Creating new threads and maintaining already existing threads is accomplished through the use of the Thread class.

Lesson 8: Multi-threaded Programming

257

The Thread Class


The Thread class, found in the java.lang package, is used to encapsulate the functionality of a thread in your program. Using the Thread class, you can: Create a new thread. Set a threads runtime properties. Start a thread so that it begins executing. Manage a thread.

Creating a New Thread


Creating a new thread is as simple as creating a new Thread object. When you create a new thread, you need to specify a Runnable object whose run() method you want called when the thread begins executing. An example of a Runnable object is shown below:
MyRunnableObject is being used as an example only. A typical Runnable object would do more than simply say, Hello World.

public class MyRunnableObject implements Runnable { public void run() { System.out.println( "Hello World!" ); } }

To create a new thread, using this object, you would use the following code:
// create a new runnable object MyRunnableObject myRunnable = new MyRunnableObject(); // create the new thread using the runnable object Thread t = new Thread( myRunnable );

The code above creates an unstarted thread which, when started, will call the run() method of your MyRunnableObject class. If you dont want to use a Runnable object, you have a second option when creating a new thread. The Thread class implements Runnable and denes an empty run() method that doesnt do anything. You can extend the Thread class and override its run() method to perform whatever tasks you need it to. For example:
public class HelloThread extends Thread { public void run() { System.out.println( "Hello World!" ); } }

You can then create a new thread without using a Runnable object. Instead, you just create a new HelloThread object:
HelloThread t = new HelloThread();

The preceding code creates an unstarted thread which, when started, will call the run() method that you have overridden.

258

Java 2 Programming for Developers

To summarize, you have two choices when creating a new thread and writing a run() method. The rst is to write a new class that implements Runnable. You then need to create a new Thread object that will use your Runnable object. Your other option is to write a new class that extends, or inherits, the Thread class. When you extend the Thread class, you need to override the run() method to do whatever you need it to do. When trying to decide whether to extend Thread or implement Runnable, remember that Java only allows you to extend one class. If the class you are creating already extends another class, you will have to implement the Runnable interface. Typically implementing Runnable is a little more exible, but it will always depend on the programming situation.

Setting a Threads Runtime Properties


Before you start a thread, you have the option of setting some runtime properties of the thread. These include: The threads name. The threads priority. The threads type (daemon or non-daemon).

Naming a Thread
Every thread has a name that can be used to identify the thread. When a new thread is created, it is given a name generated by Java. You can use the setName() method of the Thread class to change a threads generated name. For example:
Thread t = new Thread(); t.setName( "helper thread" );

Thread Priority
We mentioned earlier that a programs threads must share processor time. The amount of processor time each thread receives will depend on the threads priority. The operating system has a mechanism called the scheduler that determines which thread is allowed to execute and for how long. The scheduler uses thread priority values to assist in the process of delegating processor time to threads. The specics of how the scheduler is implemented varies from one operating system to another. Fortunately, through Java, the details of interacting with the scheduler are handled for you. You simply assign priorities to threads and the scheduler does the rest. When a new thread is created, it is assigned the same priority of the thread that created it. This priority can be changed by using the setPriority() method of the Thread class. This method takes one parameter, an integer, which species the new priority. Since the meaning of this number could vary from system to system, the Thread class provides three constants for specifying priority. They are: Thread.MAX_PRIORITY Thread.MIN_PRIORITY Thread.NORM_PRIORITY

priority: The property of a thread that determines how much processor time the thread will receive from the operating system.

scheduler: A mechanism contained within the operating system that determines which thread is allowed to execute and for how long.

Lesson 8: Multi-threaded Programming

259

These constants allow you to assign a priority to a thread that is constant across all systems. For example, to assign the highest possible priority to a thread, you would use the following code:
Thread importantThread = new Thread(); importantThread.setPriority( Thread.MAX_PRIORITY );

In the code above, importantThread is assigned the highest priority a thread can have. This will most likely result in the particular thread receiving much more processor time compared with threads having normal or low priority.

Daemon vs. Non-daemon Threads


There are two types of threads in Javadaemon and non-daemon. The main thread in your program is a non-daemon thread. The Java Virtual Machine automatically exits when it detects that all non-daemon threads have terminated. This is because a program in considered to be nished when all of its non-daemon threads have nished executing. Daemon threads, on the other hand, are used to perform tasks that are not essential to the completion of your program. This does not mean that daemon threads are not useful. For example, a daemon thread might control an animated icon within your programs user interface. While this is a nice feature, it is probably not essential to the completion of your program. Writing a le to a disk would be an essential task that you want to be sure completes before your program shuts down. Therefore, you would use a non-daemon thread for this. In general, if a program is dependent on a thread completing some task, that thread should be a non-daemon thread. If a non-daemon thread creates a new thread, the new thread will be a nondaemon thread by default. Likewise, if a daemon thread creates a new thread, the new thread will be a daemon thread by default. To manually specify whether a thread is a daemon thread, you can use the setDaemon() method of the Thread class. For example, to force a thread to be a daemon thread, you would use the following code:
You can only call the setDaemon() method prior to starting the thread. If you call the setDaemon() method after you have started a thread, an IllegalThreadState Exception will be thrown.

daemon thread: A type of thread that performs a task that is not essential to the completion of a program. The Java Virtual Machine will terminate even while daemon threads are still running.

// creates a daemon thread Thread t = new Thread(); t.setDaemon( true );

Or if you want to force a thread to be a non-daemon thread, you would use the following code:
// creates a non-daemon thread Thread t = new Thread(); t.setDaemon( false );

The only restriction to using the setDaemon() method is that you must use it prior to starting a thread. If you start a thread and then try to use the setDaemon() method, an IllegalThreadStateException will be thrown.

260

Java 2 Programming for Developers

TASK 8B-1:
Deciding Between Daemon and Non-daemon Threads
Objective: To determine which type of thread to use in a given programming situation. 1. You are writing a calendar program that contains a digital clock in the corner of the screen. You want to use a separate thread to update the time on the clock periodically. Should this thread be a daemon or nondaemon thread? Why? This thread should be a daemon thread because this thread could technically run forever. It will remain active as long as your program keeps running. In other words, the thread is dependent on the program running; the program is not dependent on the thread running. 2. You are writing a program that computes Pi to the 1,000th decimal place. You want to use multiple threads to speed up the calculations. Should the threads be daemon or non-daemon? Why? The threads should be non-daemon. If the purpose of your program is to compute Pi, and the threads are responsible for doing so, then your program cannot exit until the threads have nished executing. In other words, the program is dependent on the threads. 3. You are writing a program that will upload a large le to an FTP server. You want to use a separate thread to perform the actual upload. Should this thread be a daemon, or a non-daemon thread? Why? This thread should be a non-daemon thread. You would most-likely want the entire le to be uploaded successfully to the FTP server. Because of this, the program would not be able to terminate until the thread terminated. Because of this, the program is dependant on the thread. 4. You are writing a chat program and you need to create a thread that constantly checks the status of your network connection. If the network connection is ever lost, an error message should be displayed and the program should exit. Should this thread be a daemon or non-daemon thread? Why? This thread should be a daemon thread. While its true that the thread may cause the program to exit, the program may also exit simply because the user shuts the program down. If there are no problems with the network, this thread will remain running as long as the program keeps running. Because of this, the program is not dependent on the thread nishing.

Starting a Thread
Once you have set a threads properties, you can start the thread. Starting the thread will cause the run() method in your Runnable object to be executed concurrently with the rest of your program. In other words, you will have multiple threads executing at the same time.

Lesson 8: Multi-threaded Programming

261

To start a thread, you can use the start() method of the Thread class. For example:
Do not use the run() method to start a thread. Doing so will execute the code in your run() method, but it will not execute it on a different thread. Always use the start() method when starting a thread.

Thread t = new Thread(); t.start();

The start() method should only be called once. If you attempt to invoke the start() method on a thread that has already been started, an IllegalThreadState Exception will be thrown.

Managing a Thread
The Thread class provides several methods for managing the threads within your program. Using these methods, you can: Check to see if the thread is alive. Wait for a thread to die (nish executing). Cause a thread to wait for a certain amount of time. Cause a thread to give up its time with the processor and allow other threads to execute.

If you attempt to invoke the start() method on a thread that has already been started, an IllegalThreadState Exception will be thrown.

The isAlive() Method


A thread is considered to be alive if it has been started and has not nished executing. To check to see if a thread is alive, you can use the isAlive() method of the Thread class. This method will return true if the thread is alive and false otherwise. For example:
Thread t = new Thread(); t.start(); ... // check to see if the thread is still alive if ( t.isAlive() ) { System.out.println( "The thread is still alive!!!" ); }

The join() Method


A thread is considered to be dead if it has nished executing. This happens when the run() method has nished executing normally, or when an exception gets thrown (causing the run() method to terminate abnormally). If you need to have one thread in your program wait for another thread to die, you can use the join() method of the Thread class. The thread that calls the join() method will be forced to wait for the other thread to nish executing. If the other thread has already died, the join() method does nothing. The following code segment illustrates the use of the join() method:
The wait() method, inherited from the Object class, is not used to wait for a thread to die. Be sure you dont accidently use the wait() method when you mean to use the join() method.

262

Java 2 Programming for Developers

Thread t = new Thread(); t.start(); // wait for the thread to finish try { t.join(); } catch ( InterruptedException e ) { // the thread got interrupted for some reason }

The join() method has the potential for throwing an InterruptedException. As shown above, you need to wrap your code in a try and catch block.

The sleep() Method


The sleep() method, provided by the Thread class, allows you to pause an individual thread for a specied amount of time. This method takes one parameter that species, in milliseconds, the amount of time for the thread to sleep. Since the sleep() method is static, you can invoke it at any time, from anywhere within your program. The thread that invokes the method is the thread that will pause for the specied amount of time. The following code segment demonstrates the sleep() method:
public void run() { // perform some tasks ... // pause for 5 seconds try { Thread.sleep( 5000 ); } catch ( InterruptedException e ) { // the thread got interrupted for some reason } // perform some more tasks ... }

Just like the join() method, the sleep() method has a potential for throwing an InterruptedException. Notice that you need to wrap your code in a try, catch block. Also, notice the static usage of the sleep() method.

The yield() Method


There may come a time when one of your threads starts hogging the processor. This can happen when a thread enters a loop or if a thread has a higher priority that the rest of the threads in your program. You can force a thread to allow other threads to execute by using the yield() method of the Thread class. The yield() method causes a thread to pause just long enough so that the operating system can allow another thread to execute. Just like the sleep() method, the yield() method is static; however, it takes no parameters. The following code segment demonstrates the yield() method:

Lesson 8: Multi-threaded Programming

263

public void run() { while ( true ) { // perform a task ... // allow other threads to execute Thread.yield(); } }

Note: The Thread class also denes the stop(), suspend(), and resume() methods. Beginning with Java 1.2, these methods were deprecated because they are unsafe and should not be used. For this reason, this course will not cover these methods. For more information, refer to the J2SE API documentation.

TASK 8B-2:
Creating a Multi-threaded Program
Objective: To create a multi-threaded program that allows you to observe thread priorities and how priority determines how much processor time a thread receives. 1. Open Counter.java and take a look at the contents of the le. The Counter class contains the global variables time and count, a constructor, and the getTime() method. There is also an empty main() method dened in the Counter class. The Counter class will be used to time how long it takes for a thread to count from zero to ve million. Make the Counter class runnable by extending the Runnable interface:
public class Counter implements Runnable {

2.

3.

Dene a run() method for the Counter class:


public void run() { }

4.

Within the run() method, store the current system time in a long variable called startTime:
long startTime = System.currentTimeMillis();

The currentTimeMillis() method provided by the System class returns the number of milliseconds that have elapsed since January 1, 1970.

This value will be used to determine how much time has passed while the thread is counting up to ve million.

264

Java 2 Programming for Developers

5.

Create a while loop that will continue looping while the count variable is less than ve million:
while ( count < 5000000 ) { }
A loop such as this is rather unrealistic, but it will cause the thread to rely heavily on the computers processor. This will allow you to better observe the difference in thread priorities.

6.

Within the while loop, increment the count variable:


count += 1;

7.

To be sure the thread does not hog the processor while in the loop, allow other threads to execute by using the yield() method of the Thread class:
Thread.yield();

Your while loop method should look similar to the following:


while ( count < 5000000 ) { count += 1; Thread.yield(); }

8.

Outside of the while loop, compute the total time it took to process the loop, and store the value in the time variable. You can compute the time by taking the current time and subtracting the startTime variable that you saved earlier in the method:
time = System.currentTimeMillis() - startTime;

Your run() method is now complete and should look similar to the following:
public void run() { long startTime = System.currentTimeMillis(); while ( count < 5000000 ) { count += 1; Thread.yield(); } time = System.currentTimeMillis() - startTime; }

9.

Now, turn your attention to the main() method. Within the main() method, create three Counter objects. Name them counter1, counter2, and counter3:
Counter counter1 = new Counter(); Counter counter2 = new Counter(); Counter counter3 = new Counter();

10. Create three new Thread objects. Use the corresponding Counter object when initializing each Thread object. Name the threads thread1, thread2, and thread3.
Thread thread1 = new Thread( counter1 ); Thread thread2 = new Thread( counter2 ); Thread thread3 = new Thread( counter3 );

11. Using the setPriority() method, set the priority of each thread to correspond with the following table:
Lesson 8: Multi-threaded Programming 265

Thread
thread1 thread2 thread3

Priority
Thread.MIN_PRIORITY Thread.NORM_PRIORITY Thread.MAX_PRIORITY

thread1.setPriority( Thread.MIN_PRIORITY ); thread2.setPriority( Thread.NORM_PRIORITY ); thread3.setPriority( Thread.MAX_PRIORITY );

12. Start the threads:


thread1.start(); thread2.start(); thread3.start();

13. Have the main() method wait for the three threads to nish, or die, by using the join() method. You will need to wrap this code in a try block:
You dont need to take any action if an exception is thrown. Just leave the catch block empty.

try { thread1.join(); thread2.join(); thread3.join(); } catch ( InterruptedException e ) {}

The three counter threads will continue to perform their tasks while the main thread is waiting. 14. Finally, output the time it took each thread to complete its task. You can nd this out by using the getTime() method of the Counter class:
System.out.println( "Counter 1: " + counter1.getTime() + " milliseconds" ); System.out.println( "Counter 2: " + counter2.getTime() + " milliseconds" ); System.out.println( "Counter 3: " + counter3.getTime() + " milliseconds" );

15. Compile and run the program. Your output should look similar to the following:
If there is not a noticeable difference in the times for the three threads, try increasing the number in the while loop in step 5.

266

Java 2 Programming for Developers

Notice that the counter with the highest priority takes the shortest amount of time to complete its task. This is because a thread with high priority is given more processor time than the other threads.

Topic 8C
Synchronization
A single-threaded program has exclusive access to its own variables and methods. A multi-threaded program, on the other hand, could contain several threads that all share common data and/or methods. This presents a potential problem that could negatively affect the performance of your program. Consider the following method:
public void logMessage( String message ) { try { FileWriter out = new FileWriter( "log.txt" ); PrintWriter printOut = new PrintWriter( out ); printOut.println( message ); printOut.close(); } catch ( IOException e ) { // something went wrong writing the log file } }

This method provides a convenient way to write a message to a log le. In a single-threaded environment, this code works ne. But imagine if this method were available in a multi-threaded environment. If two threads tried to invoke this method at the same time, one of the threads would cause an exception to be thrown. This is because only one thread is allowed to write to a le at any one time. What is needed, is a way to coordinate the threads in your program so that they can safely share data and other resources. This process is called synchronization. In Java, there are two mechanisms for synchronizing threads.
synchronization: The process of coordinating the interaction of multiple threads so that they can access shared data and other resources safely.

Monitors
A monitor is a mechanism that allows you to control access to a particular resource in your program. This resource could be a variable, method, or even a single line of code. To better understand the concept of a monitor, lets rst look at an analogy. Think about a hall pass in elementary school. If a student needs to leave the classroom, they must rst obtain the hall pass from the teacher. If a student is using the hall pass and another student requests it, that student will have to wait until the rst student returns it. The next student may then ask for the hall pass and then leave the classroom. At any point in time, the hall pass is either sitting there unused, or one student is in the hall with the hall pass. In this analogy, the hall pass is a monitor. The students are threads and the right to leave the classroom is the resource that we need to control access to. In general, when a thread needs to access a shared resource, it must rst obtain a lock on the appropriate monitor.

monitor: A mechanism that allows you to control access to a particular resource in your program.

Lesson 8: Multi-threaded Programming

267

In Java, every object has a monitor that can be used to synchronize two or more threads. You obtain the lock on an objects monitor by using a synchronized block:
synchronized ( object ) { // access shared resource here }

Once you successfully obtain the lock on the objects monitor, the code inside the synchronized block is executed. If multiple threads try to obtain a lock on the same monitor, only one will be allowed to proceed. The other threads are forced to wait until the rst thread exits the block. The code inside the synchronized block is called a critical section. A critical section is a block of code that is unsafe to execute concurrently between multiple threads. A monitor is used to guarantee that no two threads execute code within a critical section at the same time. Consider the following class:
public class Bridge { public void crossBridge( Car c ) { // move car across bridge ... } }

critical section: A block of code that is unsafe to execute concurrently between multiple threads.

In this example, crossing the bridge is considered to be the critical section.

Assume you were writing a multi-threaded program that simulated a one-lane bridge. Each thread would represent a car in your simulation. To cross the bridge, a car would need to call the crossBridge() method. Only one car is permitted to be on the bridge at a time. However, there is currently no way to enforce this rule. The problem with this situation is that multiple threads can concurrently access the crossBridge() method. You can remedy this situation in one of two ways. The rst is to declare a new global variable in the Bridge class that can be used to lock access to the bridge. Then, place a synchronized block in the crossBridge() method.
public class Bridge { private Object lock; public void crossBridge( Car c ) { synchronized( lock ) { // move car across bridge ... } } }

Now when a thread tries to access the crossBridge() method, it must rst obtain a lock on the monitor. If the lock has already been obtained by another thread, the current thread must wait for the lock to become available. The other way to control access to the crossBridge() method is to declare the method to be synchronized:

268

Java 2 Programming for Developers

public synchronized void crossBridge( Car c ) { // move car across bridge ... }

With this solution, there is no need to create the separate lock variable. Instead, the instance of the class (this) is used as the monitor. When you declare that a method is synchronized, only one thread can access that method at a time. You should note that: This code:
public synchronized void someMethod() { ... }

Is equivalent to:
public void someMethod() { synchronized( this ) { ... } }

A class can also declare that multiple methods are synchronized. For example, you may want to add a raiseBridge() method to your Bridge class in order to simulate a drawbridge:
public class Bridge { public synchronized void crossBridge( Car c ) { // move car across bridge ... } public synchronized void raiseBridge() { // raise the drawbridge ... } }

Notice that both methods in the Bridge class are synchronized. The instance of the class is used to synchronize both methods. This guarantees that only one thread can be in only one of the two methods at any given time. Think about the real life situation. Either a single car is crossing the bridge, or the bridge is being raised. Both conditions shouldnt happen at the same time.

When to Use a Monitor


You should use a monitor to synchronize multiple threads if there is a chance that the threads might: Get or set the value of the same object or variable. Read from and/or write to the same le. Read from and/or write to the same I/O stream, such as System.in or System.out.

An unsynchronized program is not guaranteed to fail. In fact, a program that displays any of the behaviors above, will probably work correctly 99 out of 100 times. The goal of synchronization is to eliminate that one time when something might go wrong.

Lesson 8: Multi-threaded Programming

269

TASK 8C-1:
Synchronizing a Light Show
Objective: In this task, you will use a monitor to synchronize several threads. 1.
If students are interested, you may want to walk them through the code in the LightShow class.

Open LightShow.java and take a look at the contents of the le. The LightShow class opens a window containing several different colored blocks. The colored blocks represent critical sections. When a block is lit up, it signies that the particular thread has entered the critical section. When the block is no longer lit, the thread has left the critical section. Your task will be to synchronize the threads so that only one thread can be in a critical section at a time. Most of the coding has been done for you. You will be writing the synchronization code. Compile and run the program. Observe the non-synchronized behavior of the lights:

2.

Nothing prevents two or more lights from turning on at the same time. Since these lights represent critical sections, this is not a good thing. 3. To be able to synchronize the multiple threads, there needs to be a common object available to all the threads. This objects monitor will be used to control access to the critical sections. In the LightShow class, immediately following the class declaration, declare a static object named sync. The object should be of type Object:
public class LightShow extends Frame { public static Object sync;

4.
Students may be unfamiliar with static initializers. You might want to explain them to the class.

To be sure the static object gets property initialized, immediately following the object, include a static initializer:
public static Object sync; static { sync = new Object(); }

5. 6.

Locate the run() method in the LightPanel class. The LightPanel class is an inner class within LightShow. Locate the critical section in the run() method. The critical section is denoted by comments.

270

Java 2 Programming for Developers

7.

Wrap the critical section in a synchronized block that obtains a lock from the static sync object in the LightShow class:
synchronized( LightShow.sync ) { // ***** BEGIN CRITICAL SECTION CODE ***** setBackground( myColor ); repaint(); pause(); setBackground( Color.black ); repaint(); // ***** END CRITICAL SECTION CODE ***** }

8.

Recompile and run the program. The lights should now be synchronized.

The lights indicate that no threads are ever in the critical section at the same time.

Wait and Notify


The other synchronization mechanism provided by Java is called wait and notify. The wait and notify mechanism, together with the use of a monitor, allows you to synchronize the execution of two threads by causing one thread to wait, until it is notied by another thread that it is okay to proceed. This is done by using the wait(), notify(), and notifyAll() methods, which are dened in the Object class. Since all objects extend the Object class, these methods are available from every class in the Java programming languageeven the classes you write yourself.

wait and notify: A synchronization mechanism that causes one thread to wait, until it is notied by another thread that it is okay to proceed.

How it Works
When a thread determines that it needs to wait until it is notied by another thread, it rst obtains a lock on a monitor. While it is holding the lock, the thread calls the wait() method of that monitor. For example, if the monitor you were using was named sync, you could wait on that monitor by using the following code:
synchronized( sync ) { try { sync.wait(); } catch ( InterruptedException e ) {} }
You must own the lock on the monitor before you try to wait on that monitor. If you try to invoke wait() on an object without owning the objects monitor, an IllegalMonitorState Exception will be thrown.

At this point, the thread releases the lock it has on the monitor. The thread then halts execution and begins to wait. The thread will continue to wait until it is notied by another thread that it is okay to continue. There is no limit to the number of threads that can wait on a particular monitor concurrently.

Lesson 8: Multi-threaded Programming

271

At some point, another thread will come along and decide that it is okay for a waiting thread to proceed. First, the thread obtains a lock on the same monitor. It now has two choices. While it is holding the lock, the thread can call the notify() method to notify one thread (that is waiting on the particular monitor) that it is okay to proceed:
You must own the lock on the monitor before notifying other threads that are waiting on that monitor. If you try to invoke notify() or notifyAll() on an object without owning the objects monitor, an IllegalMonitorState Exception will be thrown.

synchronized( sync ) { // release one thread sync.notify(); }

The other option is to call the notifyAll() method, which will notify all threads (that are waiting on the particular monitor) that it is okay to proceed:
synchronized( sync ) { // release all waiting threads sync.notifyAll(); }

It is important to note that, after a call to notify() or notifyAll(), the waiting threads are not immediately allowed to continue. Instead, the thread that called notify() or notifyAll() nishes executing the code in its synchronized block. It then releases its lock on the monitor. At this point, if the notify() method was called, the scheduler picks one of the waiting threads and allows it to continue. That thread will once again hold the lock on the monitor until it leaves the synchronized block. If the notifyAll() method was called, each of the waiting threads will take turns regaining the lock on the monitor and proceeding.

TASK 8C-2:
The Producer/Consumer Problem
Objective: One of the most common examples of using wait and notify is the producer/consumer problem. This is where one thread produces the data and another thread consumes the data. In this task, you will use wait and notify to improve an existing producer/consumer program. 1.
If students are interested, you may want to walk them through the code in the ProducerConsumer class. You should make a special point of having the students observe the user of monitors in the program.

Open ProducerConsumer.java and take a look at the contents of the le. This multi-threaded program simulates a producer/consumer situation. Notice the heavy use of monitors in this program. Compile and run the program. The Producer/Consumer window appears on-screen:

2.

The window displays the number of items that are waiting to be consumed. There is also a button that allows you to produce more items. Youll notice

272

Java 2 Programming for Developers

that while the program is running, the consumer is constantly consuming items. 3. to add more items to the list. The Click the Produce button more items you produce, the more items are consumed. Observe the console window. Youll notice that once the items are all gone, the consumer starts complaining about not having any data to consume.
When trying to press the Produce button, you may nd that your mouse doesnt respond fast enough. If this is the case, you can also use the [Spacebar] to activate the Produce button.

4.

This isnt good, because the consumer is wasting valuable processing time constantly checking to see if there is more data. To avoid this, use the wait and notify mechanism to make the consumer wait for more data to arrive. 5. 6. 7. Close the Producer/Consumer window. Locate the consume() method of the ProducerConsumer class. Within the if block, change the System.out statement to read:
System.out.println( "CONSUMER => Waiting..." );

8.

Immediately after the System.out statement you just modied, insert the following code:
try { data.wait(); } catch ( InterruptedException e ) {}

This will cause the consumer thread to wait on the array lists monitor. 9. Move the code that is currently inside the else block, outside of the else block. This should leave you with an empty else block.

Lesson 8: Multi-threaded Programming

273

10. Delete the empty else block. Your synchronized block should look similar to the following:
synchronized( data ) { if ( data.isEmpty() ) { System.out.println( "CONSUMER => Waiting..." ); try { data.wait(); } catch ( InterruptedException e ) {} } System.out.println( "CONSUMER => Consuming Item" ); data.remove( 0 ); updateCounter(); }

The consumer will now wait when it detects that there is no more data available. Now we need a way to notify the consumer when data arrives. 11. Locate the produce() method of the ProducerConsumer class. 12. Immediately after the updateCounter() statement, add the following line of code:
data.notify();

Your synchronized block should look similar to the following:


synchronized( data ) { System.out.println( "PRODUCER => Producing Item" ); data.add( new Object() ); updateCounter(); data.notify(); }

13. Recompile and run the program. After the consumer consumes all the items, it begins to wait.

14. Click the Produce button to add more items to the list. Notice that as soon as more items are produced, the consumer begins consuming them. Once all the items are consumed, the consumer begins to wait once again.

274

Java 2 Programming for Developers

Summary
In this lesson, you learned about multi-threaded programming in the Java programming language. You saw how single program computers began batching multiple programs and how this led to multi-process computers. You also saw that, just as computers can execute more than one program concurrently, programs can execute more than one thread concurrently. You used the Thread class and the Runnable interface to develop multithreaded programs. You saw how multi-threaded programs can lead to problems when accessing shared data across multiple threads. You also learned how to properly synchronize these threads using monitors. Finally, you learned how to use the wait and notify mechanism to further synchronize your multi-threaded programs.

Lesson Review
8A What was the problem with batch processing programs on older computers?
Programs did not always utilize 100 percent of the processor. This meant processing power was being wasted on programs that didnt require use of the processor. In a Java program, how many threads can be actively executing at any one point in time? Explain your answer. Only one thread can be active at any one time. This is because all threads must share processor time. To the human eye, it appears that all threads are executing at the same time.

8B What does a threads priority determine?


A threads priority determines how much processor time the thread will receive. What is a daemon thread? A daemon thread performs a task that is not essential to the completion of a program. The Java Virtual Machine will terminate even while daemon threads are still running. When is a thread considered to be dead? A thread dies when the threads run() method returns normally, or when an exception causes the run() method to terminate abnormally.

8C What is a critical section?


A critical section is a block of code that is unsafe to execute concurrently between multiple threads. When should you synchronize threads using a monitor? Answers may vary, but may include:
Lesson 8: Multi-threaded Programming 275

When multiple threads get or set the value of the same object or variable. When multiple threads read from and/or write to the same le. When multiple threads read from and/or write to the same I/O stream, such as System.in or System.out.

Describe the wait and notify mechanism. Wait and notify is a synchronization mechanism that causes one thread to wait until it is notied by another thread that it is okay to proceed.

276

Java 2 Programming for Developers

JDBC
Overview
JDBC is Javas database access API. Using JDBC, you can query and manipulate relational databases directly from your Java programs. In this lesson, you will learn how to establish a connection to a database, query the database for information, and modify the contents of the database. You will also learn about Structured Query Language (SQL), which is the language used to query databases when using JDBC.

LESSON

9
Data Files bookstore.mdb DatabaseQuery.java Lesson Time 3 hours, 30 minutes

Objectives
To access relational databases using JDBC, you will: 9A Explore and discuss the Structured Query Language. Structured Query Language, also known as SQL, is a standardized language used to communicate with databases. You will learn how to use SQL to query and manipulate databases. 9B Access a database using JDBC. Database access in Java is performed using the java.sql package. You will explore this package and see how its components are used to access relational databases.

Lesson 9: JDBC

277

Topic 9A
Overview of SQL
Databases have become a popular topic in the computer industry. Every major company implements some kind of database, whether its to keep track of personnel, products, security logs, or any other kind of information worth storing.
This topic may be a review for some students. Other students may be seeing this information for the rst time.

A database is a collection of related information, organized into tables. Each table contains one or more records. A record is represented by a row in the table. All the data within a record is related in some way. The tables also contain columns, which hold a single piece of information for each record. Figure 9-1 illustrates an example of a single table within a database.

database: A collection of related information, which is organized into tables.

record: A row of related information in a table.

Figure 9-1: Example of a database table.

The Bookstore Database


In this lesson, you will be working with an imaginary bookstore database. This database contains four tables. The table names are as follows: Authors Publishers Subjects Titles

The Authors Table


The Authors table maintains information about all the authors in the bookstore system. The data is arranged into the following columns: AuthID AuthLast AuthFirst

278

Java 2 Programming for Developers

The Publishers Table


The Publishers table maintains information about all the publishers in the bookstore system. The data is arranged into the following columns: PubID Publisher

The Subjects Table


The Subjects table maintains a list of all the possible categories a book could be under. The data is arranged into the following columns: SubjID Subject

The Titles Table


The Titles table maintains a list of all the books in the bookstore system. The data is arranged into the following columns: TitleID AuthID SubjID PubID Title PubDate Price ISBN Info LastMod Image

Structured Query Language


Structured Query Language (SQL) is a standardized language used to manipulate and obtain information from databases. SQL is actually three languages in one. The three components to SQL are: Data Denition Language (DDL)Subset of SQL used to create (and delete) database tables and other components. Data Control Language (DCL)Subset of SQL used to control who has access to the database and what level of access they have. Data Manipulation Language (DML)Subset of SQL used to manipulate data within the database.

SQL: (Structured Query Language) A standardized language used to manipulate and obtain information from databases.

Lesson 9: JDBC

279

The DDL and DCL portions of SQL are generally the responsibility of database administrators. Programmers are concerned with the DML portion, and it is this portion of SQL that we will explore in this topic.
In this lesson, we will use CAPITAL LETTERS to distinguish SQL keywords in a SQL statement.

SQL consists of several types of statements. These statements include special keywords, along with mathematical and logical operators. SQL statements can span multiple lines and, in some cases, multiple lines help to organize a long SQL statement. Generally, SQL statements are not case-sensitive and are terminated with an optional semi-colon ( ; ). You should be aware, however, that some databases may be case-sensitive and may require a semi-colon at the end of an SQL statement. Note: SQL is, for the most part, standardized. However, many database vendors have added their own proprietary SQL statements and keywords into the language. In this lesson, we will be using the most general SQL statements that are available across the majority of database vendors.

Obtaining Information from a Database


When you want to obtain information from a database, you perform a query. A query is a request for information based on some criteria. When is query is performed on a database, a temporary table is created to hold the results of the query. This temporary table is called the result set. How much, or how little, information is present in the result set will depend on what you ask for in your query.

query: A request for information based on some criteria.

The SELECT Statement


result set: The temporary table that gets created in order to hold the results of a query against a database.

In SQL, the SELECT statement is used to query a database. The general format of the SELECT statement is shown below:
SELECT columns FROM tables WHERE condition ORDER BY columns;

The SELECT and FROM clauses are required in a SELECT statement. You need to specify the columns you want and which tables the columns come from. A comma is used to separate the column names. For example, to obtain the ISBN number and price of all the books in the bookstore database, you could use the following SELECT statement:
SELECT ISBN, Price FROM Titles;

This query returns a result set containing the ISBN and Price columns of the Titles table. The result set is illustrated in Figure 9-2.

Figure 9-2: ISBN and Price columns from the Titles table.
280 Java 2 Programming for Developers

With a SELECT statement, you can select as many columns as you wish. Also, the column order you specify does not have to match the column order in the database table, meaning that you can re-order the columns. For example, you could choose to add the book title to the last query:
SELECT ISBN, Title, Price FROM Titles;

The result set from the query above is illustrated in Figure 9-3.
ISBN, Title, and Price Columns from the Titles Table

Figure 9-3: ISBN, Title, and Price columns from the Titles table. You can use the asterisk ( * ) to select all the columns from a table:
SELECT * FROM Titles;

The WHERE Clause


The WHERE clause of a SELECT statement is used to narrow down, or lter, the results of the query. Within the WHERE clause, you specify a condition that must be true for a record to be added to the result set. For example, you may want to display the title and price of all books under 20 dollars. To do so, you could use the following SELECT statement:
SELECT Title, Price FROM Titles WHERE Price < 20;

The result set from the query above is illustrated in Figure 9-4.

Figure 9-4: Titles of books under 20 dollars. The following table describes the comparison operators available in SQL: Operator
= <>

Meaning
equal to not equal

Lesson 9: JDBC

281

Operator
< <= > >=

Meaning
less than less than or equal to greater than greater than or equal to

These comparison operators can compare both numeric and alpha-numeric data. For example, to display the ISBN and price of the book XML: An Introduction, you could use the following query:
SELECT ISBN, Price FROM Titles WHERE Title = 'XML: An Introduction';

The result set from the query above is illustrated in Figure 9-5.

Figure 9-5: ISBN and price of the book XML: An Introduction. Notice that when you compare alpha-numeric data, you need to enclose strings in single quotes. You can also combine conditions using the logical operators AND, OR and NOT. For example:
SELECT Title, Price FROM Titles WHERE Price <=50 AND SubjID = 4;

There is also a simple pattern matching feature available in SQL. The LIKE operator is used for pattern matching. For example, if you wanted to nd all the books containing the word Web in the title, you could use the following query:
SELECT Title FROM Titles WHERE Title LIKE '%Web%';

The percent sign ( % ) is used to specify a wildcard pattern in a string. The result set from this query is illustrated in Figure 9-6.

Figure 9-6: Titles of all books containing the wordWeb.

The ORDER BY Clause


You can sort the data in a result set by using the ORDER BY clause of a SELECT statement. You simply specify a list of columns that will determine the order. The elements are sorted by the rst column you specify. If there are any duplicates in that column, they are sorted by the second column you specify, and so on. For example, to sort the books based on price and title, you could use the following query:
SELECT Price, Title FROM Titles ORDER BY Price, Title;

The result set from the query above is illustrated in Figure 9-7.

282

Java 2 Programming for Developers

Figure 9-7: All books, sorted by price and title. Notice that the books are sorted by price. If there are duplicate prices, those books are then alphabetically sorted by title. The default for the ORDER BY clause is to sort data in an ascending sequence. You may choose to sort the data in a descending sequence by using the DESC keyword. For example:
SELECT Price, Title FROM Titles ORDER BY Price DESC, Title;

The result set from the query above is illustrated in Figure 9-8.

Figure 9-8: All books, sorted by price (descending) and title.

Joining Tables
Sometimes the data you require is in two separate tables. When this occurs, you will need to join two tables together. This is done by using the FROM clause and the WHERE clause. The two tables you join must have a common column. You specify the two column names in the FROM clause. You then use the WHERE clause to specify the join condition (how the tables are joined). For example, to obtain the name of the author for every book, you need to join the Titles table and the Authors table. You will join the tables so that both tables AuthID columns need to be equal for the join to take place. The following query will accomplish this:

Lesson 9: JDBC

283

SELECT Title, AuthFirst, AuthLast FROM Titles, Authors WHERE Titles.AuthID = Authors.AuthID;

The result set from the query above is illustrated in Figure 9-9.
Result from Joining the Titles Table and the Authors Table

Figure 9-9: Result from joining the Titles table and the Authors table. Since both tables contain an AuthID column, dot notation is used when referring to a particular column. For example, Titles.AuthID and Authors.AuthID. If you didnt use dot notation during a join, SQL would not be able to tell which column you were referring to.

TASK 9A-1:
Working with the SELECT Statement
Objective: To practice writing queries by using the SELECT statement. 1. Write a SELECT statement that obtains a list of all the publishers in the bookstore database. The list should only include publishers names and should be in alphabetical order.
SELECT Publisher FROM Publishers ORDER BY Publisher;

2.

Write a SELECT statement that obtains a list of all authors whose rst name is Francis. The list should include both rst and last names.
SELECT AuthFirst, AuthLast FROM Authors WHERE AuthFirst = 'Francis';

284

Java 2 Programming for Developers

3.

Write a SELECT statement that obtains a list of all books whose price is between 30 and 40 dollars. The list should include all the columns of the Titles table.
SELECT * FROM Titles WHERE Price > 30 AND Price < 40;

4.

Write a SELECT statement that obtains a list of titles and subjects for all the books in the database. (Hint: You will need to join the Titles table and the Subjects table.)
SELECT Title, Subject FROM Titles, Subjects WHERE Titles.SubjID = Subjects.SubjID;

Manipulating Information in a Database


SQL is not just used for querying a database. You can also use it to modify the data in a database. You using SQL, you can: Add records to a table. Modify the records in a table. Delete records from a table.

Adding Records
Records are added to a database table by using the INSERT statement. The general format of the INSERT statement is:
INSERT INTO table ( columns ) VALUES ( data );

When using the INSERT statement, you need to specify the table into which you are adding the new record. You also need to specify the order of the columns in which you are adding the data. Finally, you need to supply the actual data. For example, to add a new book to the bookstore database, you could use the following statement:
INSERT INTO Titles ( Title, ISBN, Info ) VALUES ( 'Java 2: Programming for Developers', 1234567890, 'Advanced Java Topics' );

Since the INSERT statement above only populates three of the eleven elds in the Titles table, the remaining elds of the new record will be lled with nulls. Sometimes, the database may not allow nulls in a particular eld. If this is the case, the INSERT statement could fail if you dont provide the record with enough data.

Modifying Records
You can modify existing records in a database by using the UPDATE statement. The general format of the UPDATE statement is:
UPDATE table SET column = value WHERE condition;

When using the UPDATE statement, you rst need to specify the table you want to update. You then specify the column you want to modify, along with the columns new value. If you dont include the WHERE clause, the UPDATE statement will update every record in the table. For example, to set the price of all the books in the database to 20, you could use the following statement:

Lesson 9: JDBC

285

UPDATE Titles SET Price = 20;

The WHERE clause in the UPDATE statement is used just like the WHERE clause in the SELECT statement.

By using the WHERE clause, you can specify which record(s) is updated. For example:
UPDATE Titles SET Price = 40 WHERE TitleID = 1;

You can also modify multiple columns in a record with one UPDATE statement. This is done by providing a list of columns in the SET clause. For example:
UPDATE Titles SET Price = 40, PubDate = '3/16/02' WHERE TitleID = 1;

Deleting Records
Records can be deleted from a database table by using the DELETE statement. The general form of the DELETE statement is:
DELETE FROM table WHERE condition;

When using the DELETE statement, you need to specify a table from which you want to delete records. You also need to specify the records to delete by using the WHERE clause. For example:
DELETE FROM Authors WHERE AuthID = 40;
The WHERE clause in the DELETE statement is used just like the WHERE clause in the SELECT statement.

This DELETE statement will delete the record from the Authors table that has an AuthID value of 40.

TASK 9A-2:
Modifying Data in a Database
Objective: To practice writing queries that use the INSERT, UPDATE, and DELETE statements. 1. Write an SQL statement that adds John Doe to the Authors table.
INSERT INTO Authors ( AuthFirst, AuthLast ) VALUES ( 'John', 'Doe' );

2.

Write an SQL statement that sets the price of all books under 20 dollars to the new price of 10 dollars.
UPDATE Titles SET Price = 10 WHERE Price < 20;

3.

Write an SQL statement that removes all records from the Titles table that have a SubjID equal to 4.
DELETE FROM Titles WHERE SubjID = 4;

286

Java 2 Programming for Developers

Topic 9B
Using JDBC
JDBC is Javas database access API. The classes and interfaces that make up JDBC can be found in the java.sql package. Using JDBC, you can access any database or other data source for which a JDBC driver is available.

JDBC Drivers
JDBC was designed to be database-independent. This means that JDBC can access any database, regardless of the type, vendor, or format of the database. This ability comes from the use of JDBC drivers. A JDBC driver is a small piece of software that instructs JDBC how to connect to and interact with a particular type of database. Many popular database providers, such as Oracle and IBM, provide JDBC drivers that can used to access their databases through a Java program. JDBC drivers come in many formats. Some are partially written in Java and partially written in a native language. Others are written entirely in Java. Regardless of the format, all JDBC drivers contain a Java class through which you access the driver.

JDBC driver: A small piece of software that instructs JDBC how to connect to and interact with a particular type of database.

The JDBC-ODBC Bridge


You have a choice when selecting a JDBC driver. You can either use the driver provided by your database vendor or you can use a driver developed by a thirdparty company. You can also use the driver which comes with the Java SDK. This driver is called the JDBC-ODBC bridge. The JDBC-ODBC bridge makes it possible for a Java program to communicate with any database that is compatible with ODBC. Open Database Connectivity (ODBC) is an API that enables you to access a database without concerning yourself with the underlying implementation of that database. Consider database access without ODBC, where you would connect your program directly to a database. For example, Figure 9-10 shows a program connected to an Oracle database.

JDBC-ODBC bridge: A JDBC driver that allows a Java program to communicate with any database that is compatible with ODBC. This driver is included with the Java SDK.

ODBC: (Open Database Connectivity) An API that enables you to access a database without concerning yourself with the underlying implementation of that database.

Figure 9-10: A program connected directly to an Oracle database.

A Program Connected Directly to an Oracle Database

Lesson 9: JDBC

287

The problem with connecting directly to a database is that you need to use database-specic communication between the program and the database. In Figure 9-10, OCI is required to communicate with an Oracle database. If a company decided to change the type of database it uses, the program in Figure 9-10 would need to be modied. With ODBC, an extra layer is added to database access, as shown in Figure 9-11.
Database Access Via ODBC

Figure 9-11: Database access via ODBC. ODBC handles the details of how to communicate with a particular database. If a company were using ODBC and decided to change the type of database it uses, the program wouldnt need any modications. Instead, ODBC can be recongured to communicate with the new database. Since Java can not communicate directly with ODBC, the JDBC-ODBC bridge creates another layer during database access, as shown in Figure 9-12.
Database Access Via the JDBC-ODBC Bridge

Figure 9-12: Database access via the JDBC-ODBC bridge. In this lesson, you will use the JDBC-ODBC bridge to access a database through ODBC. Before this can happen, you need to congure ODBC for use with your database.

TASK 9B-1:
Configuring ODBC for Use with JDBC
Objective: To congure ODBC to communicate with a database, in preparation for using the JDBC-ODBC bridge. 1. Using Windows Explorer, create a directory named C:\databases. Move the bookstore.mdb database from the C:\077954 directory to the C:\databases directory.

288

Java 2 Programming for Developers

2.

Choose StartSettingsControl Panel. This will open the Control Panel.


On Windows 2000 and Windows XP computers, you can nd the ODBC Data Sources inside the Administrative Tools folder of the Control Panel.

3.

Double-click on ODBC Data Sources to open the ODBC Data Source Administrator:

4.

Click Add. The Create New Data Source dialog box is displayed.

Lesson 9: JDBC

289

5.

Select the Microsoft Access Driver and click Finish. The ODBC Microsoft Access Setup dialog box is displayed.

6. 7. 8.

In the Data Source Name text box, type Bookstore. A Data Source Name (DSN) is used to identify a particular database on your system. Click Select. Choose the le C:\databases\bookstore.mdb. The Bookstore DSN is now congured to point to the database located in the le C:\databases\bookstore.mdb.

9.

Click OK to close the ODBC Microsoft Access Setup dialog box.

10. Click OK to close the ODBC Data Source Administrator. ODBC has now been congured to communicate with an Access database.

290

Java 2 Programming for Developers

Loading JDBC Drivers


Before you can use JDBC to access your database, a JDBC driver needs to be loaded and registered with the driver manager. JDBC drivers can register themselves, but you need to load the driver. To load a JDBC driver from within your program, you can use the Class.forName() method. You need to pass the entire class name, including the package, of the JDBC driver class into the Class.forName() method. For example, to load the JDBC-ODBC bridge driver, you would use the following code:
Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" );
Remember, a JDBC driver is a class. You need to be sure that the driver class is accessible via your class path before you try to load it.

The code above loads the JDBC-ODBC bridge driver into memory. The driver automatically registers itself with the driver manager. The driver manager keeps track of all the drivers that have been loaded into the system.

Connecting to a Database
After loading a JDBC driver, you need to establish a connection with the database. This is done via the getConnection() method of the DriverManager class. There are three different getConnection() methods, each of which are described in the table below: Method
getConnection( String url )

The Class.forName() method is part of JDBC. However, JDBC requires the driver class to be loaded dynamically at runtime. The Class.forName() method accomplishes this.

Description
Connects to the database specied by the url parameter. This method assumes the database does not require a username and/or password. Connects to the specied database, using the supplied username and password. Connects to the specied database, using the list of properties specied in the Properties object. This list of properties can contain a username and password, along with any other database-specic properties required to make the connection.
If your database requires a username and/or password, you should never hard-code this information into your program. Always prompt the user for this information at runtime.

getConnection( String url, String user, String password ) getConnection( String url, Properties info )

The getConnection() methods are static, meaning that you dont need to create an instance of the DriverManager class in order to use them. You can simply call the methods like this:
DriverManager.getConnection( url );

The Database URL


The getConnection() method requires a URL that species the database you want to connect to. The general form of the URL is as follows:
jdbc:sub-protocol:data-source

The URL is divided into three parts, all separated by colons. The rst part, jdbc, identies this URL as a JDBC URL. The second part, sub-protocol, identies the sub-protocol. This value will vary based on the driver you are using. The nal part of the URL, data-source, species the data source that you wish to connect to. This value will also vary based on the driver you are using. Your JDBC driver documentation should tell you what values to use for the subprotocol and for the data source.
Lesson 9: JDBC 291

When using the JDBC-ODBC bridge, the sub-protocol is always: odbc. The data source will always match the data source name you specify when using the ODBC Datasource Administrator. For example, in Task 9B-1, you created a data source name called Bookstore that pointed to the database. The URL for this particular database would be:
jdbc:odbc:Bookstore

The Connection Object


When you invoke the getConnection() method, the DriverManager class attempts to nd an appropriate driver to connect to the database. When it nds one, a new Connection object is created and returned to you. You will want to store this object in a variable, as you will be using it to access and query the database. For example:
Connection conn = DriverManager.getConnection( "jdbc:odbc:Bookstore" );

Once you obtain a Connection object, you can begin to access the database using the methods dened in the Connection interface. The following table describes some of the methods of the Connection interface:
All of the methods dened in the Connection interface have a potential for throwing an SQLException. You will need to properly handle any exceptions that are thrown.

Method
close() commit()

Description
Closes the connection to the database and releases any resources used by the connection. If the connection does not perform auto-commits when you modify the database, this method will commit your changes. This method is the opposite of the rollback() method. Creates, and returns to you, a Statement object that is used to send SQL statements to the database. Returns true if the connection is performing auto-commits; false otherwise. Returns a DatabaseMetaData object that can be used to obtain information about the database. Returns true if the connection is open; false otherwise. Returns true if the connection is read-only; false otherwise. Allows you to access stored procedures in the database. Returns a CallableStatement object. Allows you to send parameterized SQL statements to the database. Returns a PreparedStatement object. If the connection does not perform auto-commits when you modify the database, this method will undo all of your changes since the last time you called commit(). This method is the opposite of the commit() method. Allows you to turn auto-commit on and off.

createStatement()

getAutoCommit() getMetaData()

isClosed() isReadOnly() prepareCall()

prepareStatement()

rollback()

setAutoCommit()

292

Java 2 Programming for Developers

Method
setReadOnly()

Description
Allows you to enable and disable read-only mode.

Auto-commit
When you issue SQL statements to a database, there is an option of having the database be updated either immediately or whenever you choose. This option is called auto-commit. When you rst establish a connection, auto-commit is enabled by default. You can enable and disable auto-commit by using the setAutoCommit() method of the Connection object. With auto-commit enabled, every change you make to the database is permanent. When auto-commit is disabled, you will need to use the commit() method to make your changes permanent. If, for some reason, you need to undo all your changes, you can use the rollback() method and the database will be reverted back to the point when it was last committed. You should only use the commit() and rollback() methods when auto-commit is disabled.

auto-commit: The JDBC feature that allows for a database to be updated after every SQL statement is executed. This feature can be enabled and disabled, and is enabled by default.

Closing the Connection


Connections to a database are automatically closed when the Connection object is garbage-collected, either because the program exits or the object is no longer being referenced. While this is true, its always a good idea to close the connection yourself by using the close() method. For example:
Connection conn; ... // close the connection object conn.close();

Issuing SQL Statements to the Database


Once you have a connection established, you can begin sending SQL statements to the database. To do so, you need to obtain a Statement object. This is done by using the createStatement() method, as dened in the Connection interface. The createStatement() method returns a Statement object that you should store in a variable. For example:
Statement stmt = conn.createStatement();

The Statement interface denes several methods used to issue SQL statements to the database. The following table describes these methods and their uses: Method
executeUpdate()

Description
Used to issue an SQL statement to the database that modies the database in some way. This method should be used for INSERT, UPDATE, and DELETE statements. Used to process multiple SQL statements that update the database. Used to query the database using a SELECT statement. This method returns a ResultSet object.

executeBatch() executeQuery()

Lesson 9: JDBC

293

Method
execute()

Description
Used to process an SQL statement that can return multiple results. Can be used for updates and queries.

Updating the Contents of the Database


When you are issuing an SQL statement that updates the database in some way, you need to use the executeUpdate() method. This method takes one parameterwhich is the SQL statement that you want to executeand returns the number of rows that were updated. The following code segment demonstrates the use of executeUpdate():
Connection conn; ... Statement stmt = conn.createStatement(); String updateStatement = "INSERT INTO AUTHORS VALUES ( 54, 'Doe', 'John' );"; // execute the statement int numRowsUpdated = stmt.executeUpdate( updateStatement );

The code above obtains a Statement object and uses the executeUpdate() method to execute a SQL statement, which is stored in a string. The result of the executeUpdate() method is stored in the numRowsUpdated variable. You dont have to store the result of the executeUpdate() method if you dont need to use it for anything. Instead, you can just execute the update, for example:
stmt.executeUpdate( updateStatement );

Performing a Batch Update


Sometimes you may want to execute several update statements at the same time. The Statement object supports batch updating, which is performed using the addBatch(), executeBatch(), and clearBatch() methods. First, you use the addBatch() method to add SQL statements to the batch. When ready, you call the executeBatch() method to execute all the statements in the batch. The executeBatch() method returns an array of integers. Each integer in the array corresponds with an SQL statement in the batch. The value of each integer will tell you the status of the corresponding update. The following table describes the possible values for each integer in the array: Return Value
returnValue >= 0

Meaning
The statement executed successfully and the return value represents how many rows were modied during the update. The statement was executed successfully, but the number of modied rows is not known. The statement did not execute successfully.

returnValue == -2 returnValue == -3

294

Java 2 Programming for Developers

If, after adding statements to the batch, you decide not to execute the batch, you can use the clearBatch() method to remove all the SQL statements currently in the batch. When you successfully execute a batch, the batch is cleared for you automatically. The following code segment demonstrates the use of batched statements:
Connection conn; ... Statement stmt = conn.createStatement(); // add statements to the batch stmt.addBatch( ... ); stmt.addBatch( ... ); stmt.addBatch( ... ); stmt.addBatch( ... ); // execute the batch int[] results = stmt.executeBatch();

Performing a Database Query


When you need to obtain information from the database using a SELECT statement, you need to use the executeQuery() method. This method takes one parameterthe SQL statement that you want to execute. The executeQuery() method differs from executeUpdate() in that executeQuery() returns a ResultSet object instead of an int. When you call the executeQuery() method, you need to save the result set that it returns in a variable. The following code segment demonstrates the use of executeQuery():
Connection conn; ... Statement stmt = conn.createStatement(); String queryStatement = "SELECT * from Titles;"; // execute the statement ResultSet rs = stmt.executeQuery( queryStatement );

The code above obtains a Statement object and uses the executeQuery() method to execute a SQL statement, which is stored in a string. The result set returned by the executeQuery() method is stored in the rs variable. You will need to process this result set in order to get the results from your query.

Processing a ResultSet
When you query a database using the executeQuery() method, a ResultSet object is returned to you. This object gives you access to the result set created by the database in response to your query. Recall that a result set is a table with rows and columns. Each row represents one record, or result, to your query. When processing a result set, you will typically process each record, one at a time, until there are no records left.

Lesson 9: JDBC

295

Every result set has a cursor that points to the current record. You can use the next() method of the ResultSet object to move to the next record in the result set. Initially, when the result set is rst returned to you, the cursor is positioned just before the rst record. This is shown in Figure 9-13.
A Result Set and its Cursor

Figure 9-13: A result set and its cursor.


If the rst call to next() returns false, it means that there are no records in the result set. In other words, your query returned no results.

The rst call to next(), points the cursor to the rst record of the result set. The next() method will continue to return true until there are no more records in the result set. This makes it possible to set up a loop that processes every record, without needing to know ahead of time how many records there are. For example:
ResultSet rs = stmt.executeQuery( queryStatement ); while( rs.next() ) { // process the current record }

Processing Records
When the cursor is pointing to a record in the result set, you can access the columns of that record. This is done by using the get() methods dened in the ResultSet interface. There is a get() method for almost every datatype you would need. Some of the get() methods available from a ResultSet object are:

296

Java 2 Programming for Developers

getBoolean() getDate() getDouble() getFloat() getInt() getLong() getObject() getString() getTimeStamp()


The getDate() method does not return a java.util.Date object. Instead, it returns a java.sql.Date object. The java.sql.Date class is a subclass of the java.util.Date class.

When you call one of the methods listed above, you need to specify a column in the result set. This can be done in one of two ways. The rst is to specify a column by name. For example:
// get the author's first name String firstName = rs.getString( "AuthFirst" );

The other option is to specify a column by number. Result set columns in JDBC are one-based, meaning they start at 1, not 0. If you wanted to retrieve data from the third column in your result set, you could use the following code:
// get the data from the third column String firstName = rs.getString( 3 );

The get() method you use to retrieve data does not necessarily have to match the datatype of the column. For example, if you use the getString() method to retrieve data from a column containing an integer, JDBC will convert the data for you.

When processing a result set in JDBC, column numbers are one-based, meaning column numbers start at 1. This may confuse you at rst because almost everything else in Java is zero-based.

Result Set Metadata


JDBC provides a mechanism for obtaining information about a result sets columns. This information is called result set metadata and is useful when you are unfamiliar with the data being returned from a query. To obtain this information, you can use the getMetaData() method of the result set. This will return you a ResultSetMetaData object. For example:
ResultSetMetaData metadata = rs.getMetaData();

The following table describes some of the most common methods of the ResultSetMetaData interface: Method
getColumnCount() getColumnName( column ) getColumnType( column )

result set metadata: Information about a result sets columns. This information includes the number of columns, type of columns, and the column names of the result set.

Description
Returns the number of columns in the result set. Returns the name of the specied column. Returns the datatype of the specied column.
A result sets row information is not available via result set metadata.

Using the methods above, you can create a dynamic program that can process a result set without knowing how many columns there are or what the columns names are.

Closing the Result Set and Statement Object


When you have nished processing the data in the result set, you should close it by using the close() method. For example:
Lesson 9: JDBC 297

ResultSet rs; ... // close the result set rs.close();

You should also close the Statement object when have nished sending SQL statements to the database. This is done by using the statements close() method. For example:
Statement stmt = conn.createStatement(); ... // close the statement object stmt.close();

Both ResultSet and Statement objects will be closed automatically by JDBC if you do not close them. However, closing them yourself will ensure that any system resources used by these objects will be released immediately.

TASK 9B-2:
Querying a Database
Objective: To use JDBC to connect to and query a database. Setup: Task 9B-1 has been completed. 1. Open the le DatabaseQuery.java and examine its contents. The program contains an empty main() method where you will be communicating with a database. Notice that the le imports the java.sql package, which contains the classes and interfaces necessary for using JDBC. Create a static String constant that holds the URL of the bookstore database. Name the variable DATABASE_URL:
public static String DATABASE_URL = "jdbc:odbc:Bookstore";

2.
The two static String constants you are creating should be global variables in the DatabaseQuery class.

3.

Create another static String constant that holds the SQL statement that we are going to execute. Name this variable DATABASE_QUERY:
public static String DATABASE_QUERY = "SELECT * FROM Titles;";

Storing the query as a constant makes it easy to locate and change, if desired.

298

Java 2 Programming for Developers

4.

Within the main() method, load the JDBC-ODBC bridge driver using the Class.forName() method. You will need to wrap the code that does this in a try block because the Class.forName() method might throw an exception:
try { Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" ); } catch ( ClassNotFoundException e ) { System.err.println( "JDBC driver not found! Exiting program..." ); System.exit( 1 ); }

Notice that if an exception gets thrown, the program should simply display an error message and then exit. 5. Set up a try and catch block. You will perform the remaining steps within the try block. The catch block should catch an SQLException. If an exception gets thrown, display a detailed error message:
try { } catch ( SQLException e ) { System.err.println( "An error occurred while accessing the database:" ); System.err.println( e.toString() ); }

6.

Within the try block, connect to the database using the getConnection() method of the DriverManager class. Store the Connection object in a variable called conn:
Connection conn = DriverManager.getConnection( DATABASE_URL );

7.

Obtain a Statement object by using the connections createStatement() method. Store the Statement object in a variable called stmt:
Statement stmt = conn.createStatement();

8.

Execute the database query by using the statements executeQuery() method. Save the result set that is returned in a variable called rs:
ResultSet rs = stmt.executeQuery( DATABASE_QUERY );

9.

Obtain the result set metadata by using the result sets getMetaData() method. Save the ResultSetMetaData object in a variable called metadata:
ResultSetMetaData metadata = rs.getMetaData();

10. We are going to be displaying the results of the query to System.out. First, display the SQL query:
System.out.println( "Query: " + DATABASE_QUERY ); System.out.println();

Lesson 9: JDBC

299

11. Using the result sets next() method, create a while loop that keeps looping while there are more records left in the result set:
while ( rs.next() ) { }

12. Within the while loop, create the following for loop:
for ( int colNum = 1; colNum <= metadata.getColumnCount(); colNum += 1 ) { }

This for loop uses the result set metadata to iterate through all the columns of the result set. You should now have a for loop, within a while loop. 13. Within the for loop, obtain the current columns name by using the metadatas getColumnName() method. Remember, the current column number is being stored in the colNum variable. Store the result in a variable called colName:
String colName = metadata.getColumnName( colNum );

Remember that if the current column is storing something other than a string, the getString() method will perform any necessary conversions for you.

14. Obtain the current columns value by using the result sets getString() method. Remember, the current column number is being stored in the colNum variable. Store the result in a variable called colValue:
String colValue = rs.getString( colNum );

15. Output the current columns name and value, separated by a colon:
System.out.println( colName + ": " + colValue );

16. Outside of the for loop (but still inside of the while loop), print a blank line to keep the formatting looking good:
System.out.println();

17. Outside of the while loop, close the ResultSet object, the Statement object, and the Connection object:
rs.close(); stmt.close(); conn.close();

18. Observe your program. It should look similar to the following:


import java.sql.*; public class DatabaseQuery { public static String DATABASE_URL = "jdbc:odbc:Bookstore"; public static String DATABASE_QUERY = "SELECT * FROM Titles;"; public static void main( String[] args ) { try { Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" ); } catch ( ClassNotFoundException e ) {

300

Java 2 Programming for Developers

System.err.println( "JDBC driver not found! Exiting program..." ); System.exit( 1 ); } try { Connection conn = DriverManager.getConnection ( DATABASE_URL ); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery( DATABASE_QUERY ); ResultSetMetaData metadata = rs.getMetaData(); System.out.println( "Query: " + DATABASE_QUERY ); System.out.println(); while ( rs.next() ) { for ( int colNum = 1; colNum <= metadata .getColumnCount(); colNum += 1 ) { String colName = metadata.getColumnName( colNum ); String colValue = rs.getString( colNum ); System.out.println( colName + ": " + colValue ); } System.out.println(); } rs.close(); stmt.close(); conn.close(); } catch ( SQLException e ) { System.err.println( "An error occurred while accessing the database:" ); System.err.println( e.toString() ); } } }

19. Compile and run the program. When you run the program, you may want to redirect the output of the program into a text le. This will make is easier to examine the output. To do so, you can use the following command at the DOS prompt:
java DatabaseQuery > out.txt

This command will run the program and save the output into a le called out.txt. 20. Observe the programs output. Notice that your program was able to determine column names by using the result set metadata.

Lesson 9: JDBC

301

Suggested Time: 30 Minutes

Apply Your Knowledge 9-1


Performing More Queries
Setup: Task 9B-2 has been completed. Using result set metadata makes your program very dynamic. This is because you dont have to hard-code column names or numbers in the program. You simply execute the query and let the result set tell you program what kind of data it contains. To prove this fact, we will use the program you wrote in Task 9B-2 to perform different queries with very little modication. 1. 2. 3. 4. Open DatabaseQuery.java. Assign a new query to the global DATABASE_QUERY constant. This query can be anything you wish. Refer to Topic 9A for ideas. Recompile and run the program. Observe the programs output. Notice that the same program can be used to perform a different query. The only necessary modication to the program was changing the query string. Take a moment to experiment with some other queries by repeating Steps 24.

5.

Summary
In this lesson, you learned how to perform database communication using JDBC. You explored the java.sql package and saw how the classes and interfaces contained within it are used to communicate with a database. You used the JDBC-ODBC bridge to communicate with a database via ODBC. You also learned about the Structured Query Language, also known as SQL. You used SQL to manipulate and query a database.

Lesson Review
9A What is a database?
A database is a collection of related information, which is organized into tables. What is a query and what is it used for? A query is a request for information based on some criteria. When you want to obtain information from a database, you perform a query. When do you need to join tables? You need to join tables when the data you require is in two separate tables.

302

Java 2 Programming for Developers

9B What is a JDBC driver and what is it used for?


A JDBC driver is a small piece of software that instructs JDBC how to connect to and interact with a particular type of database. JDBC drivers are used in order to provide JDBC with database independence. What is the difference between the executeUpdate() method and the executeQuery() method? The executeUpdate() method is used to execute an SQL statement that updates the database in some way. The executeQuery() method is used to query the database using a SELECT statement. The executeUpdate() method returns the number of rows modied during the update, while the executeQuery() method returns a ResultSet object. What is result set metadata used for? Result set metadata is used to obtain information about a result sets columns. This information includes the number, type, and names of the columns.

Lesson 9: JDBC

303

304

Java 2 Programming for Developers

GLOSSARY
== operator An operator in Java that compares two primitive datatypes or two object references for equality. abstraction The concept of hiding the details of the implementation by focusing exclusively on the denition of the communications interface. applet A Java application that is intended to be embedded in a Web page. The AWT Applet class is a subclass of Panel and is automatically constructed by the browser. arithmetic operator A symbol or representation that indicates a specic kind of arithmetic operation that will be performed on or between basic arithmetic or numeric values or operands. array A non-resizable data structure that stores multiple objects or primitive types together as a single object. auto-commit The JDBC feature that allows for a database to be updated after every SQL statement is executed. This feature can be enabled and disabled, and is enabled by default. class An object-oriented programming template that contains the denitions of the variables and methods of an object. collection A storage mechanism in Java that takes an object-oriented approach to the storage, retrieval, and manipulation of data. comment A portion of a source code le that is ignored by the compiler. comparative operator A symbol that represents a comparison operation for equality that will be performed between basic numeric, characterbased, or date-based values or operands. constructor A group of Java statements that enables initialization of the object state when the object is instantiated using the keyword new. control flow The order in which statements, or blocks of statements, are executed within a program. critical section A block of code that is unsafe to execute concurrently between multiple threads. custom serialization A mechanism that explicitly denes how a class is serialized. daemon thread A type of thread that performs a task that is not essential to the completion of a program. The Java Virtual Machine will terminate even while daemon threads are still running. database A collection of related information, which is organized into tables. default serialization The built-in mechanism that performs object serialization automatically. do-while loop A code statement that ensures that the code will be processed at least once.

Glossary

305

GLOSSARY
dot notation A type of code notation that uses periods to separate identiers. In the example java. awt.Graphics, the period identies the full reference for the Graphics class: that the Graphics class is contained within the awt package, which is contained within the java package. In myJag.moveIt(), the period indicates that you are invoking the moveIt method of the myJag instance. encapsulated classes Classes that contain all of the elds and methods that enable the class to function. The elds in encapsulated classes are manipulated only by methods of the class. event An occurrence in the runtime system. Events occur when a user interacts with the system by pressing a button, clicking the screen, or performing other actions. event adapter class An abstract class that receives mouse events and contains empty method stubs that save a programmer from needing to dene each method in an interface implementation. exception An event that is triggered because something abnormal happens during execution of a program. When such an event occurs, program execution is immediately halted and control is passed to an exception handler. exception handler A block of code whose purpose is to catch an exception, deal with it, and return the program to normal execution. fatal error An error from which recovery is not possible. floating point A number that includes fractional parts. Also known as a real number. for loop A numeric loop with a mechanism to specify the starting value, the nal value, and the way to increment values after an iteration. I/O Short for input and output. IDE (Integrated Development Environment) A GUI programming environment that includes tools to facilitate the application development cycle. if statement A code statement that enables a program to perform a certain action only if a condition (boolean expression) is true. if-else statement A code statement that enables a program to perform a certain action if a condition (boolean expression) is true and to perform an alternative action if the condition is false. if-else-if statement A code statement that enables you to nest a second if statement that will only be processed if the rst if condition is false. inner class A class that is declared within the specication of another class. In other words, it is dened within the opening and closing curly braces of another class denition. instanceof An operator in Java that tests whether or not an object is an instance of a particular class type.

306

Java 2 Programming for Developers

GLOSSARY
integer A non-fractional number that can be positive, negative, or zero. interface A collection or set of abstract methods. iterator An object that enumerates the elements of a collection and returns them to you one at a time. Java Virtual Machine (JVM) A software or hardware environment that enables Java applications to run on a client computer. JDBC driver A small piece of software that instructs JDBC how to connect to and interact with a particular type of database. JDBC-ODBC bridge A JDBC driver that allows a Java program to communicate with any database that is compatible with ODBC. This driver is included with the Java SDK. listener An object that is notied by a registered source when an event, such as a button press, occurs. A listener object implements an event-listener interface that corresponds to the component to which it is assigned. logical operator A symbol or representation that indicates a logical operation that will be performed between boolean values or operands. method A section of code that behaves like an independent program and that an be invoked using the method name. In Java, you can write executable statements only within methods. Accordingly, methods represent processes or behavior. method overloading Declaring multiple methods with the same name and ensuring uniqueness of signature by declaring a different number of arguments or by declaring a unique sequence of argument datatypes. monitor A mechanism that allows you to control access to a particular resource in your program. node A single element of a linked list. object serialization The process of converting an object into a series of bytes, which can be used to reconstruct the object at a later time. ODBC (Open Database Connectivity) An API that enables you to access a database without concerning yourself with the underlying implementation of that database. operator A symbol or representation that indicates a specic kind of mathematical, logical, or character-based operation (or manipulation) that will be performed on or between the basic values or operands. overloading constructors Specifying many constructors in one class with different signatures. overriding methods Declaring a method with the same name and signature as the parent classs method, thereby hiding the parent classs method. package A collection of related classes.

Glossary

307

GLOSSARY
peer components Similar objects on different operating systems. Also known as heavyweight components. For instance, the Java AWT text eld component has a Windows peer component which is also known as a texteld. platform independence A feature of a software application or language that enables it to be run on any operating system. polymorphism A feature of many object-oriented programming languages that enables objects to assume various forms. primitive datatypes The core built-in datatypes that are not derived from any other class or type. priority The property of a thread that determines how much processor time the thread will receive from the operating system. query A request for information based on some criteria. random access file A le I/O technique that allows random, or non-sequential, access to a le. Data can be read from or written to any location in the le at any time. re-throwing The process of catching an exception and immediately throwing it again. reader A special type of input stream that reads characters instead of bytes. record A row of related information in a table. reference A pointer to an object in memory.
308 Java 2 Programming for Developers

reference variable A variable that points to an object in memory rather than a primitive. result set The temporary table that gets created in order to hold the results of a query against a database. result set metadata Information about a result sets columns. This information includes the number of columns, type of columns, and the column names of the result set. return_type Species the datatype of the returned value. RGB Color dened by its red, green, and blue components. RGB is typically used for dening colors displayed on-screen, since those are the colors used in monitors. runtime exception A special type of exception that is not checked by the compiler to see if it might be thrown within a method. scheduler A mechanism contained within the operating system that determines which thread is allowed to execute and for how long. signature of a method The name of the method, the number of arguments, and the datatype of the arguments. SQL (Structured Query Language) A standardized language used to manipulate and obtain information from databases.

GLOSSARY
stack trace Shows you where an exception originated, as well as all the methods that re-threw the exception or passed it on without catching it. stream Apipe of information used to move data from one place to another. switch statement A control structure that executes code branches based on an exact match between a passed parameter and the values dened by individual case statements. synchronization The process of coordinating the interaction of multiple threads so that they can access shared data and other resources safely. thread The smallest pathway of an executable code. A Java application can process multiple threads at once. try, catch, finally Blocks of code used to dene an exception handler. typecasting Also called casting, the mechanism by which Java converts an existing value of a given datatype to a new value with a new datatype. Unicode A character set that includes all (or nearly all) of the alphabet characters in the world. wait and notify A synchronization mechanism that causes one thread to wait, until it is notied by another thread that it is okay to proceed. writer A special type of output stream that writes characters instead of bytes.

Glossary

309

310

Java 2 Programming for Developers

INDEX
== operator, 31-33

A
abnormal exiting, 64-71 Abstract Window Toolkit See: AWT abstraction, 113-114 access modiers, 110-113 adding menus, 195-196 Adding Records, 285 AND operator, 19 anonymous inner classes, 132-138 AORR method, 94-99 API Specication, 9-11 applet, 185 Applet class, 185 Area of Rectangular Room See: AORR method arithmetic operator, 18 array, 72, 73-77 creating a fully populated, 74 creating an, 73 declaring an, 73 determining size of an, 75 lling an, 78 initializing an, 73-74 manipulating an, 77-80 multi-dimensional, 75 performing a binary search on an, 79 retrieving data from an, 74 sorting, 78-79 storing data in an, 74 testing for equality, 78 array element, 73-77 array index, 73-77 assigning a layout manager, 187-189 auto-commit, 293 AWT, 180 Applet class, 185 containers, 180-181

batch update, 294-295 binary search, 79 bitwise operators, 20-21 boolean, 12-14 boolean datatype, 14 boolean literals, 14 BorderLayout, 186-187 break statement, 64-71 byte, 12-14

C
CardLayout, 186-187 cascading menu, 195-198 casting, 24-29 catch block, 143-145 writing a, 151-152 catching exceptions, 143-145 char, 12-14 character datatype, 13 character stream reader, 218-219 writer, 219-220 character streams, 218-221 class, 5-9, 100-104 inner, 132-138 Math, 169-177 String, 164-168 closing les, 228, 236 collection, 72, 81-83 creating a, 83-84 other functionality, 86 retrieving data from a, 85-86 storing data in a, 84-85 types, 81 using a, 83-88 Collections class, 89-91 Color class, 204 comment, 5 comparative operator, 18-19 comparing for equality, 30, 31-33 comparison operators, 281-282 compiling Java applications, 6 component, 182 creating a, 182-183

connection closing a, 293 Connection object, 292-293 constructor, 124-127 default, 127-129 overloading, 129-132 container, 180-181 creating a, 181-182 continue statement, 64-71 creating a collection, 83-84 creating a File object, 210-211 creating a menuing system, 195-198 creating an array, 73, 74 creating components, 182-183 creating containers, 181-182 critical section, 267-271 custom serialization, 241-243

D
daemon thread, 260 data reading and processing, 226-228 Data Control Language See: DCL Data Denition Language See: DDL Data Manipulation Language See: DML data structures, 72 database, 278 closing the connection, 293 connecting to a, 291-292 deleting records from a, 286 issuing SQL statements to a, 293-295 manipulating, 279-280 obtaining information from, 279-280, 281-282 Oracle, 287-288 updating a, 285-286 updating contents of a, 294 database query, 295 database URL, 291-292 datatype boolean, 14

B
batch processing, 250-253

Index

311

INDEX
character, 13 datatypes, 12 oating point, 13 integer, 12-13 primitive, 31 DCL, 279-280 DDL, 279-280 decimal notation, 12-13 declaration modiers, 110-113 declaring a method, 94-96 declaring an array, 73 declaring variables, 15-16 default constructor, 127-129 default serialization, 241-243 DELETE statement, 286 deleting records, 286 determine size of an array, 75 directory structure, 107 DML, 279-280 do-while loop, 53-60 documentation comment, 5 dot notation, 96, 97-98 double, 12-14 runtime, 148 throwing an, 142-143 uncaught, 148-150 exception handler, 143-145 including an, 146 writing an, 150, 151, 152 exception object, 152 exception-throwing code, identifying, 150-151 Exclusive OR See: XOR operator GridBagConstraints class, 189-190 GridBagLayout, 186-187, 189-194 using, 190-191 GridLayout, 186-187 GUI, 148-150, 180

H
handling exceptions, 142, 145-148 heavyweight component, 180 hexadecimal notation, 12-13 hiding implementation See: abstraction history of Java, 2-5

F
fatal error, 142 File class, 210-215 File object creating a, 210-211 using a, 211-212 lling an array, 78 nally block, 143-145 including a, 152-156 oat, 12-14 oating point datatypes, 13 ow control with do-while, 53-60 with for, 60-64 with if, 38-40 with if-else, 40-42 with if-else-if, 42-46 with switch, 47-53 with while, 53-60 FlowLayout, 186-187 for loop, 60-64 FROM clause, 283-284 fully populated array, 74 function, 94-99

I
I/O, 210 IDE, 6 identiers, 14-17 identifying exception-throwing code, 150-151 if statement, 38-40 if-else statement, 40-42 if-else-if statement, 42-46 compared to switch statement, 47-53 information manipulating in a database, 285-286 inheritance, 105-106 initializing an array, 73-74 inner classes declaring, 132-138 input stream, 215-216 input/output See: I/O InputStream class, 215-216 INSERT statement, 285 instanceof operator, 23-24 instantiation, 100-104 int, 12-14 integer datatypes, 12-13 integer notation, 12-13 Integrated Development Environment See: IDE interface, 105-106

E
encapsulated class, 110-113 End Of File exception See: EOF exception EOF exception, 143 equality, comparing for, 30, 31-33 equals() method, 33-35 escape sequences, 13 event, 198-199 event adapter class, 200 event delegation model, 198-203 event listener, 198-199 assignment, 200-201 evolution of Java, 2-5 exception, 142 catching an, 143-145 declaring that a method might throw an, 147 handling an, 145-148 re-throwing, 151-152

G
garbage collection, 156-158 Gosling, James, 2-5 graphical user interface See: GUI Graphics class, 204-207 graphics in Java, 204-207

312

Java 2 Programming for Developers

INDEX
invoking a method, 96 isAlive() method, 262 iterator, 85-86 CardLayout, 186-187 FlowLayout, 186-187 GridBagLayout, 186-187, 189-194 GridLayout, 186-187 legal identiers, 14-17 linked list, 81-82 linked node, 81-82 list, 81-82 listener, 198-199 assignment, 200-201 literals boolean, 14 local inner classes, 132-138 logical operator, 19-22 long, 12-14

N
narrowing conversion, 24-29 nested ifs, 42-46 no-arg constructor, 127-129 node, 81-82 non-daemon thread, 260 NOT operator, 20

J
J2SE API Specication, 9-11 Java benets of, 2-4 compiling applications, 6 evolution of, 2-5 history of, 2-5 resources, 9-11 running applications, 6 Java Foundation Class See: JFC Java identiers, 14-17 Java keywords, 15 Java Language Specication, 9-11, 15 Java Software Developers Kit See: SDK Java Virtual Machine See: JVM java.awt package, 180 java.io package, 210 java.lang package, 162-163 java.sql package, 287 JDBC, 287 JDBC driver, 287-290 loading a, 291 JDBC-ODBC bridge, 287-288 JFC, 180 join() method, 262-263 joining tables, 283-284 JVM, 6, 148

O
Oak, 2-5 object, 100-104 reading from a le, 244-246 writing to a le, 243 object references, 30-31 object serialization, 240 customized, 241-243 performing, 241-243 object-orientation, 2-4 octal notation, 12-13 ODBC, 287-288 Open Database Connectivity See: ODBC opening les, 225-226, 234-235 operator, 17-19 ==, 31-33 AND, 19 arithmetic, 18 bitwise, 20-21 comparative, 18-19 instanceof, 23-24 logical, 19-22 NOT, 20 OR, 19-20 shift, 20-21 XOR, 20 operator precedence, 21-22 OR operator, 19-20 Oracle, 287-288 ORDER BY clause DESC keyword, 282-283 order of precedence, 21-22 output stream, 216-217 OutputStream class, 216-217

M
main method, 40-41 manipulating arrays, 77-80 Math class, 169-177 member inner classes, 132-138 menu, 195-198 adding, 195-196 method, 94-99 arguments, 94-99 benets of, 97 declaring a, 94-96 invoking a, 96 isAlive(), 262 join(), 262-263 overloading, 119 overriding, 121-124 parameters, 94-99 return_type, 94-96 returned value, 94-99 signature, 118-121 sleep(), 263 yield(), 263-264 modifying records, 285-286 monitor, 267-271 when to use, 269 multi-dimensional array, 75 multi-line comment, 5 multi-process computers, 250-253

K
keywords, 15

L
layout manager, 186-187, 189-194 assigning a, 187-189 BorderLayout, 186-187

Index

313

INDEX
overloading constructors, 129-132 overloading methods, 119 overriding methods, 121-124 retrieving data from an array, 74 return_type, 94-96 returned value, 94-99 RGB color, 204 running Java applications, 6 runtime exception, 148

T
testing arrays for equality, 78 this keyword, 114 thread, 2-4, 253-257 creating a new, 258-259 daemon, 260 managing a, 262-267 naming a, 259 non-daemon, 260 overview of, 250-253 priority, 259-260 setting runtime properties, 259-261 starting a, 261-262 using, 257 Thread class, 258 throwing an exception, 142-143 try block, 143-145 placing code in a, 151 try, catch, nally, 143-145 two-dimensional array, 75 type conversion, 24-29 type promotion, 26-28 typecasting, 24-29

P
package, 106-110 java.awt, 180 java.io, 210 java.lang, 162-163 java.sql, 287 peer component, 180 performing a database query, 295 platform independence, 180 polymorphism, 23-24, 118 precedence, order of, 21-22 primitive datatypes, 12, 15-16, 31 and wrapper classes, 84-85 priority, 259-260 processing data, 226-228 Project Green, 2-5

S
scheduler, 259-260 SDK, 6 SELECT statement, 280-281 WHERE clause, 281-282 set, 81 shift operators, 20-21 short, 12-14 signature of a method, 118-121 single inheritance, 105-106 single line comment, 5 sleep() method, 263 Software Developers Kit, 6 sorting arrays, 78-79 SQL, 279-280 issuing statements, 293-295 stack trace, 152 Statement object, 297-298 statements abnormal exiting, 64-71 static inner classes, 132-138 storing data in a collection, 84-85 storing data in an array, 74 stream, 215-218 character, 218-221 converting byte to character, 220 input, 215-216 output, 216-217 String class, 13, 164-168 String Constant Pool, 13 Structured Query Language See: SQL Sun Microsystems, 2-5 super keyword, 114 switch statement, 47-53 synchronization, 267, 269, 271-274

Q
query, 280-285

R
random access le, 222 re-throwing, 151-152 reader, 218-221 reading and processing data, 226-228 reading les, 224 reading objects from les, 244-246 steps to, 225-233 record, 278 processing, 296-297 reference, 30-31 reference variable, 13 result set, 280-285 closing a, 297-298 metadata, 297 processing a, 295-302 sorting data in a, 282-283 retrieving data from a collection, 85-86

U
uncaught exceptions, 148-150 Unicode, 13 UPDATE statement, 285-286 using a collection, 83-88 using a File object, 211-212

V
variables assigning values, 15-16 declaring, 15-16

W
wait and notify, 271-274 how it works, 271-272 WHERE clause, 281-282, 283-284 while loop, 53-60 widening conversion, 24-29 wrapper classes, 84-85, 163

314

Java 2 Programming for Developers

INDEX
writer, 218-221 writing an exception handler, 150, 151, 152 writing les, 233 steps to, 233-239 writing objects to les, 243

X
XOR operator, 20

Y
yield() method, 263-264

Index

315

316

Java 2 Programming for Developers

1.0

Potrebbero piacerti anche