You are on page 1of 187

A Java Primer

Author: Banji Lawal

October 22, 2011

Contents
1 Conguring Eclipse 1.1 1.2 1.3 Downloading And Installing Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1.1 Downloading & Installing Eclipse For Linux . . . . . . . . . . . . . . . . . . . . . . . . Writing Your First Java Program With Eclipse . . . . . . . . . . . . . . . . . . . . . . . . . . Layout Of Eclipse Workbench . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3.1 1.3.2 1.3.3 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.5 1.5.1 1.5.2 1.5.3 1.6 1.7 1.8 Perspectives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Views Dealing Directory Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Navigator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Views Dealing With Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Views Dealing With Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Views Dealing With Program Components . . . . . . . . . . . . . . . . . . . . . . . . Views Dealing With Execution/Testing . . . . . . . . . . . . . . . . . . . . . . . . . . Javadoc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Customizing Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Setting Autocompletion Time out . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Setting Word Wrapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Folding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 14 14 14 16 17 17 17 17 17 17 17 18 18 18 18 18 19 19 19 19 19 19 19 21 21 21 22 22 22 22

Commonly Used Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Some Helpful Editor Customizations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Eclipse Keyboard Shortcuts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Saving Your Perspective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Eclipse Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2 Introduction 2.1 2.2 What is Java? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1 2.2.1 2.2.2 2.3 Java Versions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tools & Tool APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Java Runtime Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Components Of Java Standard Edition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Java Objects, Classes & Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2.4 2.5

Layout of a Java Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Java Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5.1 2.5.2 Identiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

23 23 23 24 26 27 27 27 29 29 29 31 31 32 35 35 35 36 38 39 44 44 45 45 51 51 54 54 54 54 55 55 55 56 57 61 64 64 65 67

2.6 2.7 2.8

Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Arithmetic Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.7.1 Precedence Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3 Basic Console Input/Output 3.1 Java Print Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.1 3.1.2 3.1.3 3.2 Print . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Printf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Println . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

The Scanner Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4 Flow of Control 4.1 Java Branching Mechanisms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.1 4.1.2 4.1.3 4.1.4 4.2 4.2.1 4.2.2 4.2.3 5 Methods 5.1 5.2 5.3 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Denition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Method Header . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3.1 5.3.2 5.3.3 5.3.4 5.4 5.5 5.6 5.7 5.8 5.9 Modier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Return Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Method Name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Parameter List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The If Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . If-Else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Boolean Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . While Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Do-While Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . For Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Iteration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

The Method Body . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Invoking Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Scope Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Function Overloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.7.1 5.8.1 How The Interpreter Evaluates Overloaded Functions . . . . . . . . . . . . . . . . . . Using Javadoc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Documenting Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tips For Using Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

5.9.1 5.9.2 5.9.3 5.9.4 5.9.5 5.9.6

One Task Per Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Brevity Is Best . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dont Overdo Overloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Debug As You Go . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Provide Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . When There Is Repetition Use A Function . . . . . . . . . . . . . . . . . . . . . . . .

68 68 68 68 68 68 68 71 71 75 75 75 76 78 78 78 78 80 80 81 81 82 85 85 86 86 86 87 93 93 94 94 94 99

5.10 Advantages Of Using Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 Objects And Classes 6.1 Components Of A Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.1 6.1.2 6.1.3 6.2 6.3 6.4 Instance Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Creating An Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Static versus Nonstatic Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pass By Value Versus Pass By Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.4.1 6.4.2 Pass By Value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pass By Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6.5 6.6

Anonymous Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Packages & Classpath . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.6.1 6.6.2 6.6.3 Classpath . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Making Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Marking Classes As Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7 Arrays 7.1 Declaring Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.1.1 7.1.2 7.2 7.3 IndexOutBounds Error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Char Versus String Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Initializing arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Array Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.3.1 7.3.2 7.3.3 Comparing Arrays For Equality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Copying Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Methods With Variable Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7.4 7.5 7.6 7.7

Referencing Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Passing Arguments To Main . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Enumerated Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Multidimensional Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 103

8 Inheritance 8.1 8.2

Properties Of Subclasses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 Invoking Super Class Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 8.2.1 8.2.2 Reference Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 Protected Instance Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 5

8.3 8.4

Invoking A Superclass Methods 8.3.1 8.4.1 8.4.2

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

Overriding Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 Final Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 Final Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 Static Methods Cannot Be Inherited . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 Static Imports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

The Final Modier And Its Eects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114

8.5

Eects of The Static Modier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 8.5.1 8.5.2

8.6

Accessors That Return Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 117

9 Polymorphism 9.1 9.1.1 9.1.2 9.2 9.2.1 9.2.2 9.2.3 9.3 9.3.1 9.3.2 9.3.3 9.4 9.5

Method Binding In Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 Early Binding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 Late Binding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 Upcasting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 Downcasting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 Upcasting/Downcasting Guidelines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 Guidelines For Making A Method Abstract . . . . . . . . . . . . . . . . . . . . . . . . 138 Properties Of Abstract Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 Properties Of Abstract Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

Upcasting Versus Downcasting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120

Abstract Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138

Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 Inner Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 153 . . . . . . . . . . . . 153

10 Exceptions 10.1.1 Termination Versus Resumption Models Of Exception Handling

10.1 Generalized Exception Handling Mechanism . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 10.2 Handling Exceptions With If-Else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 10.3 Handling Exceptions With Try-Catch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 10.3.1 Try Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 10.3.2 Catch Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 10.4 Handling Exceptions With Try-Catch-Finally . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 10.4.1 Finally Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 10.4.2 The Dierence Between A Try Block & A Try Statement . . . . . . . . . . . . . . . . 161 10.5 Overview Of The Throwable Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 10.6 The Exception Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 10.6.1 Exceptions Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 10.6.2 Exceptions Mutators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 10.6.3 Exceptions Accessors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 10.6.4 Exceptions Commonly Used Subclasses . . . . . . . . . . . . . . . . . . . . . . . . . . 163 10.7 throw . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 6

10.7.1 Scope Of Thrown Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164 10.8 Using Throws In Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 10.9 Exception Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 10.9.1 Excepetions Message Utilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 10.10Rethrowing Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 10.11Stack Unwinding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 10.12Chained Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 10.13Rolling Your Own Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 10.14Assertions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 11 Debugging 171

11.1 The Debugging Process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 11.2 Doing Code Walk Throughs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 11.3 Using Print To Debug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 11.3.1 Advantages Of Print Statement Debugging . . . . . . . . . . . . . . . . . . . . . . . . 171 11.3.2 Disadvantages Of Print Statement Debugging . . . . . . . . . . . . . . . . . . . . . . . 171 11.4 Using Assert To Debug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 11.5 Debuggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 11.5.1 Stack Tracer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 11.5.2 Breakpoints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 11.5.3 Prolers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 11.5.4 Code Analysis Engine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 11.6 Using The Eclipse Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 11.6.1 Setting Breakpoints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 11.6.2 Running The Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 11.6.3 Viewing The Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 11.6.4 Watching Values Of Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172 12 Unit Testing 13 Files 14 I/O Streams 15 Generics 16 Collectors & Iterators 17 Threads 18 Basic GUI Input/Output 19 UML Basics 173 175 177 179 181 183 185 187

List of Figures

10

List of Tables
2.1 2.2 2.3 2.4 3.1 3.2 4.1 4.2 5.1 5.2 5.3 7.1 7.2 8.1 Java Reserved Words . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Java Primitive Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Binary Arithmetic Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Arithmetic Operator Precedence Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Java Escape Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Java Format Speciers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Table4.1: Java Comparison Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Table 4.2: Complete Precedence Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . GetArea.javas Layout in RAM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mains Initial Address Space . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Final State Of Area.javas Method Stacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . charArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 24 27 28 30 32 38 39 57 57 58 85

Best Little Jolo Rice House In Texas Menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 Allowed Child Class Access Modiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112

10.1 Unchecked Exceptions Found in RuntimeException . . . . . . . . . . . . . . . . . . . . . . . . 163 10.2 Checked Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163

11

12

Chapter 1

Conguring Eclipse
Most of the time programmers do not use plain text editors for creating code. The reason why is that most development projects entail the following tasks. Editing code. Compiling the code. Maintaining dierent versions of the source code. Tracking changes made by dierent people. Debugging Tracing the programs execution. Frequently a developer has to do all these things continuously and most text editors do not have the capability of doing all these tasks. So many editors such as Notepad, TextEdit, MS Word or are completely unsuitable. There are other editors which such as TextPad, Vim, Emacs, and TextMate which are more appropriate for programming and they have numerous plugins that make all the latter group of editors very popular among programmers. However they have some limitations. The main limitations have to deal with standardization of behaviour and ease of use for a specic language. The standardization and ease of use can come down to things like the editor doing autocompletion of common words, commands and phrases that occur in a language, linking to libraries and placing stubs into code so that the developer do not have to keep typing the same things over and over again. Most programmer editors such as Vim, Emacs, TextPad can do all these things. I actually use Vim for almost everything. However its easier to write Java code using an Integrated Development Environment (IDE). With IDEs you are able to spend more time on writing actual new code and maintaining your code than with nonIDEs. Also in a large shop with many programmers its easier to have a standard template and conguration that everyone can use. The two most popular IDEs for Java are NetBeans and Eclipse. For this class we shall be using Eclipse as the IDE. 13

1.1

Downloading And Installing Eclipse

To get Eclipse goto http://eclipse.org/downloads and select the link Eclipse IDE for Java Developers. As of this writing the size of the download is 98MB. The website should detect your operating system and automatically start the download of the appropriate binary. Installing Eclipse In Windows Or MacOSX The binaries should be fairly straightforward to install I would recommend consulting the documentation that comes with your binary and looking at the Eclipse FAQs if you have problems installing the IDE.

1.1.1

Downloading & Installing Eclipse For Linux

Most modern Linux distributions will come bundled with Eclipse. And if they do not your distribution should have a means of downloading and installing Eclipse and any needed Java packages. If you are using a RedHat based distro such as Fedora or CentOS its likely that Eclipse can be downloaded via Yum or PackageKit. For Ubuntu use Apt. Its a bad idea to download the Eclipse binaries or tarballs ans install them since it will make it harder to manage all the packages on your system when you manually install apps. If there are problems consult the documentation for your distro on installing Eclipse.

1.2

Writing Your First Java Program With Eclipse

Once you have installed Eclipse we can create our rst Java program to do this we start Eclipse. For now you can use the default settings for the workspace. In the future you might decide to change your workspace but do not worry about that right now. Once the Eclipse is launched click on File New Java Project then in the Project Name bar put in HelloWorld and click Next and Finish buttons. After doing this you should see the HelloWorld project in the Project Window list. Right click on HelloWorld project and select New Class. In the Name eld put HelloWorld and check the box for public static void main(String[] args). If you have done everything correctly the only line you will have to add to the program is System.out.println(Hello world.); as seen in 1 2 3 4 5 6 7 8 9 10 11 12 /* * * @param args */ 14 /* * * @author griot */ public class HelloWorld { /* * * */

13 14 15 16 17 18 }

public static void main ( String [] args ) { System . out . print ( " Hello world . " ) ; }

Program 1.1: HelloWorld.java

To run the program you can click on Run Run and select the Java Application checkbox. In the Console Window the output will be displayed as seen in Figure 1.1. Instead of clicking on the menu items you can also click on the green play button.

15

1.3

Layout Of Eclipse Workbench

When you start Eclipse, after it has launched and opened your workspace its window is called the workbench. The workbench has the following components; Perspectives Views Editor 16

1.3.1

Perspectives

A collection of Views and an Editor window. A particular perspective is good for creating, testing, maintaining, and running applications made under a language.

1.3.2

Views

These show us information about the program or the results of running an Eclipse command.

1.3.3

Editor

This is where you type the code for your program. Like all editors the program editor does spellchecking but it also has some nice features that you will nd helpful as you create you programs.

1.4

Commonly Used Views

You can have your views grouped in a section of the workbench by tabs. There are so many views that here I shall simply describe some of the most frequently used ones by programmers. Which are;

1.4.1

Views Dealing Directory Structure

These have to do with lay out of the program les in the Eclipse workspace.

Package Explorer Generally all your related programs will be grouped in package. This view shows the things in the package.

Project Explorer

1.4.2 1.4.3

Navigator Views Dealing With Output

Though we could classify other views under output for now we shall only consider the following.

Console When the Java program is run without a GUI the output is shown here.

Progress Shows how the execution is progressing. 17

1.4.4

Views Dealing With Errors

Problems Things that might keep the program from working. Some of these will be easy to x and Eclipse will suggest quick xes for you.

Error Log Errors are things that happen during compilation.

1.4.5

Views Dealing With Program Components

There are two of these.

Outline Shows all the functions and the variables that are in the code.

Type Hierarchy There are diering types of data and this shows the things that make up the data type.

1.4.6

Views Dealing With Execution/Testing

The two main one that we shall deal with are;

JUnit Used for looking at results of unit tests.

Ant Used for running Java programs as Ant apps.

1.4.7

Javadoc

Shows the documentation for the program.

1.4.8

Customizing Views

You can customize the layout of your views by moving them, resizing, grouping them, deattaching, and reattaching them to the perspective. For a description on how to do all these things look at the appropriate sections in the Eclipse Help manual that comes with your install. 18

1.5

Some Helpful Editor Customizations

As you use the editor you might nd some customizations helpful two of the ones you might like the most are autocompletion and word wrapping.

1.5.1

Setting Autocompletion Time out

There are lots of words duplicated when we program and they can be fairly long to type. Eclipse will autocomplete for you. It will also autocomplete commands that you invoke.

1.5.2

Setting Word Wrapping

Sometimes when a line is too long Eclipse might decide to break it up. This can cause problems for you so we can set how word wrapping is done.

1.5.3

Folding

Since programs can be fairly long and we usually only on one section of code many editors will minimize code blocks, functions or other things to make it easier for us to focus on the section we need to deal with.

1.6

Eclipse Keyboard Shortcuts

The less you use the mouse the faster and more fun you will have developing programs with Eclipse. To do this it will be helpful to learn the shortcuts for common task such as saving les, compiling. The table below shows them.

1.7

Saving Your Perspective

After you have made any changes to the layout of your perspective you will want to save it so that when it starts up again it will display all the Views in the layout that you found best for your workow. To do this click on Window Save Perspective As Java.

1.8

Eclipse Resources

The purpose of this chapter is not to be an exhaustive guide to Eclipse, but simply a guide to help you get started. There are many ne documents and videos on using Eclipse, and the best place to nd them is at http://help.eclipse.org/helios/index.jsp, http://www.eclipse.org/resources/resource.php? id=532, and http://www.eclipse.org/resources/?category=Getting%20Started.

19

20

Chapter 2

Introduction
2.1 What is Java?

Java is an object oriented language that generates platform independent executables that are interpreted by the computer byte by byte instead of being compiled into machine specic instructions. Java programs are run by the Java Virtual Machine (JVM) which interprets Java instructions and pass them on to the operating system for execution. The fact that Java code is interpreted makes it more portable so code can be run on diering systems and architectures without having out be compiled from source. Now that we have briey talked about Java as an interpreted language we can look at its object oriented nature.

2.1.1

Java Versions

Java is a rich family of languages that has diering versions and can run under diering types of environments. The dierent versions of Java are:

Java Standard Edition For desktops current version is 7.

Java Enterprise Edition Meant for servers.

Java Micro Edition For devices like cellphones, game controllers and other electronics.

Java Card For smart cards. 21

2.2

Components Of Java Standard Edition

We will be using Java Standard Platform Edition in this book. The parts of JSE6 are:

2.2.1

Tools & Tool APIs

This includes all the programming tools and their Application Programming INterfaces (APIs) which specify how other programs can interact with them.

2.2.2

Java Runtime Environment

This consists of the Java Virtual Machine, and the libraries.

Java Virtual Machine A simulation of a machine, runs the Java bytecode.

Libraries These are all the libraries, they are stored in class les.

2.3

Java Objects, Classes & Methods

When we are trying to solve a problem frequently our solution depends and the nature of the things involved with the problem or categories that the solution applies to. For example certain attributes dene what a car is; some of these properties are that all cars have are metal doors, windows, chairs, seatbelts, an engine, radiator, and the ability to accelerate, slow down, or stop. On the other hand a person has arms, legs, a head, and can do things like walk, talk, sleep, eat. From looking at the class of objects that is motor vehicles we see that there are certain action associated with a car and that these actions as well as its physical properties determine its state at any point in time. Another example is that an bag is an object that can go from the states full and empty. We can move between these states by either putting things in the bag or taking things out. Therefore we see a bag object which has properties such as lled volume, empty volume, total volume can have all of those values changed whenever we put an item in the bag or take one out. In Java we also deal with objects and each object is a member of a class similar to the way Peugeots are member of the class of cars and Rotimis Peugeot 305 is a particular instance of the Peugeot object. In Java the operations that we can perform on a Peugeot such as accelerating, rolling down the window, stooping, opening a door are called methods. We can consider a method as being an operation that changes the state of an object. 22

2.4
1 2 3 4 5 6 7 } }

Layout of a Java Program

Java programs are in the following format; public class HelloWorld { public static void main ( String [] args ) { System . out . println ( " Hello world ! " ) ; System . out . println ( " The square of " + 3 + " is " + (3 * 3) ) ;

Program 2.1: HelloWorld.java To execute the program we must save the code into a le named HelloWorld.java. All Java program names must match their class name. Later on we shall use Eclipse but for now we will compile from the command line by typing javac HelloWorld.java, javac converts the source into object code. After compiling it we can use the java interpreter, which is called java, to execute the bytecode. The commands that we type in the console to get the compile and run the program are shown highlighted in yellow. $ javac HelloWorld . java $ java HelloWorld Hello world ! The square of 3 is 9 $ The command prompt on my laptop is a $ sign, so, that character in the output can be ignored.

2.5

Java Expressions

Java programs consist of a series of statements where we either declare a variable, assign a value to an object, evaluate an expression or call a method. To do these things we use identiers.

2.5.1

Identiers

An identier is the name of a variable, object class, or method. There are four rules to follow when naming identiers. i An identier cannot begin with a number. ii Identier names can only consist of alphanumeric characters and underscore. iii It is illegal to use Java keywords as identiers. To see what Javas reserved words are look at http: //java.sun.com/docs/books/tutorial/java/nutsandbolts/_keywords.html as well as Table2.1. iv Some words such as println are not reserved but if you use them as identiers in your code your application may become unstable.

23

absract assert boolean break byte case catch char class const continue default do double else enum extends false

nal nally oat for goto if implements import instanceof int interface long native new null package private protected

public return short static strictfp super switch synchronized this throw throws transient true try void volatile while

Table 2.1: Java Reserved Words

2.5.2

Variables

In Java all variables must be declared prior to being used, variable declarations are in the format;

variable-type variableName1, ....., variableNameN;


The variable can be either one of Javas builtin primitives, standard objects, or user dened objects. Table2.2 shows the Java primitive data types. Type boolean char byte short int long oat double Kind of Value true or false single unicode characters integer number integer number integer number integer number real number real number Size in Bytes 1 2 1 2 4 8 4 8

Table 2.2: Java Primitive Data Types Some examples of variable declarations are; float speed ; char gender ; int count , year , age ;

24

Variable Assignment The assignment operator,

= , is used to give a variable a value. It is used as follows; variable = expression;

Examples of variable assignment are; int count = 0; float height = 5.0; letter = a ; area = length * height ; The assignment operator evaluates left right to left so the expression x = y = 45; will be evaluated in the order; i The value 45 is stored in y. ii the value of y is stored in x. Variable Initialization It is good programming practice to initialize your variables after they have been declared. If you do not initialize them the values stored in them will be arbitrary and contain whatever information had in that memory location previously. Furthermore to make your code readable put each variable declaration on its own line. Implicit and Explicit Typecasting Sometimes we might want to store an integer in a oat, or vice versa. Or we might want to do convert an integer to a character. Generally a variable of smaller size can be assigned to one of type that uses more bytes, therefore the following code fragment is perfectly acceptable in Java. int size = 3; float delta = 0 f ; delta = size ; But putting avogadroNumber in roundedAvogadro will give an error. double avogadroNumber = 6.023 e23 ; int roundedAvogadro = avogadroNumber ; We can assign values of one type to another when they are in the following precedence; byte short int long oat double 25

For assigning an integer to an char, int char, long char Typecasting from char to integer is also legal, char int, char long Since Java uses unicode instead of ASCII refrain from switching between integers and characters so that any incompatibilities are avoided. If want to typecast a larger sized data type into a smaller one we must explicitly tell Java to do this byte using the typecast command. The syntax for the typecast operations is.

(target data-type) variable


In the code fragment below we can see how explicit typecasting is done. float weightInKilos = 72.3 f ; // Must put " f " after the number for floats . int aNumber = 5; aNumber = ( int ) weightInKilos ; Whenever we typecast a larger data type to a smaller one the larger one will get truncated. If on the other hand we typecast a smaller data type to a larger one the smaller one will get rounded up.

2.6

Constants

Sometimes we need a variables value to be xed, for example p = 3.1459. To make sure that you do not inadvertently change the value of a constant use the keywords public, static, nal as shown below public static final float PI = 3.1459; public static final int BUFFER_SIZE = 1024; Best practices recommend when using constants is that you declare your constants outside the maid method as shown in GetDistanceFallen.java. 1 2 3 4 5 6 7 8 9 10 11 12 finalSpeed = F R E E _ F A L L _ A C C E L E R A T I O N * timeInSeconds ; distanceInMetres = finalSpeed * timeInSeconds ; 26 public static void main ( String [] args ) { double timeInSeconds = 53.0; double distanceInMetres = 0.0; double finalSpeed = 0.0; // unit of acceleration is metres per second per second . public static final double F R E E _ F A L L _ A C C E L E R A T I O N = 9.8; public class Get Dista nceFal len {

13 14 15 16 17 } Program 2.2: GetDistanceFallen.java When we run GetDistanceFallen.java we get output shown below; the $ is simply the console prompt on my computer. $ javac GetDi stance Fallen . java $ java GetDi stance Fallen The object fell 27 52 8. 20 00 000 00 00 4 metres in 53.0 seconds . $ } System . out . print ( " The object fell " + distanceInMetres + " metres " ) ; System . out . print ( " in " + timeInSeconds + " seconds .\ n " ) ;

2.7

Arithmetic Operators

In Java there are a number of unary and binary arithmetic operators, at this time we shall only discuss the binary arithmetic operators are displayed in Table2.3 Operator + * / % ++ Action addition subtraction multiplication division modulo increment by 1 Operator = -= += *= %= Action assignment assign result of subtraction assign result of addition assign result of multiplication assign result to of modulus decrement by 1

Table 2.3: Binary Arithmetic Operators

2.7.1

Precedence Rules

Whenever an arithmetic expression is evaluated the operations that comprise the expression are evaluated in terms of their order of importance. If two operations are of equal precedence the left most operation is evaluated rst. Though there are more precedence rules for this class we will only deal with the binary arithmetic operators shown in Table2.4. To make your code easier to read always use braces to show what the precedence is supposed to be.

2.8

Strings

languages such as C, C++, and Fortran have a string primitive, however, Java does not. To use string in Java we used the String class, string are declared in Java with statements of the form, 27

Precedence Highest

Lowest

Operator ++ typecast */% += *= /= %= += -=

Table 2.4: Arithmetic Operator Precedence Rules

String variable-name;
for example, String firstName = " Banji " ; We can concatenate string with the + operator as shown in the code fragments, String firstName = " Banji " ; String lastName = " Lawal " ; String fullName = firstName + lastName ; There are a number of string methods that belong to the String class, these methods are invoked by using

. notation. For example to nd the length of the string lastName we would do,
1 2 3 4 5 6 7 8 9 10 11 12 } Program 2.3: PrintStringLength.java On running PrintStringLength.java through interpreter we see ......... $ java Print String Length The string ; " Obatala and Shiva are both gods . " is 32 characters long . $ Later on in the course we shall examine Strings in more detail. } System . out . print ( " The string ; \" " + aString + " \" " ) ; System . out . println ( " is " + stringLength + " characters long . " ) ; public class Pri ntStr ingLen gth { public static void main ( String [] args ) { String aString = " Obatala and Shiva are both gods . " ; int stringLength = aString . length () ;

28

Chapter 3

Basic Console Input/Output


Other names for the console are the command line, or terminal. The terminal is the simplest interface between the user and the operating system which is responsible for running all the programs. For programs that are interactive, that get input from a person then show a response to the users input, using the terminal for I/O is the easiest way of doing this. Java has many functions, classes, and libraries for dealing with input/output; some of those for console I/O are in the System class and further divided into the daughter classes out and in. :

3.1

Java Print Functions

For printing output we can use the functions print, println, and printf. These functions display output on the terminal, they do not have anything to do with sending a le to a printer. All three of these are methods in class System.out; you can nd out more about this from looking at http://java.sun.com/javase/6/ docs/api/index.html

3.1.1

Print

This method takes a String as an argument. Print does not add a carriage return to the string when its displayed on the terminal. The syntax of this command is;

System.out.print(String);
Below we see an example of print being used.

29

1 2 3 4 5 6 7 8

public class UsesPrint { public static void main ( String [] args ) { int number = 5; System . out . print ( " The number is " + number ) ; } } Program 3.1: UsesPrint.java The output that ShowsPrintfUsage.java generates is shown below. You can see that when runs that there is no carriage return after the message is printed on the screen. $ java UsesPrint The number is 5 $ If we want to have a newline (carriage return) also sent to the console we use the escape sequence \n as seen below. System . out . print ( " The number is " + number + " \ n " ) ; After adding the newline to our string we get the more readable output that we see here. $ java UsesPrint The number is 5 $

\n is one of the common control sequences, some other common ones are;
Escape Sequence \t \r \ \ \\ \b \n Action prints tab carriage return single quote double quote backslash bell newline

Table 3.1: Java Escape Sequences

Please note that when we are using the single quote, , in a string we do not need to escape it, however, if we want to set a char to be the single quote we will have to escape it as seen in the declaration below. char glyph = \ ; If on the other hand you had tried to do; char glyph = ; You would get a syntax error. 30

3.1.2

Printf

To get formatted output for a variable we use System.out.printf. Printf takes as its arguments a string, format specier and the variable to be printed. The program ShowsPrintfUsage.java will give you an idea of how to printf works. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 } Program Program3.2: ShowsPrintfUsage.java Note that for We see that the format speciers layout is %x.yT where: % shows beginning of the format specier x number of spaces to print in front of decimal point y number of spaces to print after the decimal point . decimal point for real numbers T indicates type of data Table 3.2 shows the Java format speciers. The printf function does not append the newline by default so we need to always add the builtins; DecimalFormat and NumberFormat their use is outside the scope of this class. } System . out . printf ( " anInteger = %1 d \ n " , anInteger ) ; System . out . printf ( " formatted double = %3.5 f \ n " , aDouble ) ; System . out . printf ( " exponential double = %1.2 e \ n " , aDouble ) ; System . out . printf ( " formatted float = %1.12 f \ n " , aFloat ) ; System . out . printf ( " formatted glyph = %4 c \ n " , glyph ) ; System . out . printf ( " formatted string = %10 s \ n " , quote ) ; System . out . printf ( " anInteger = %12 d \ n " , anInteger ) ; public class ShowsPrintfUsage { public static void main ( String [] args ) { int anInteger = 56; double aDouble = 1 2 3 6 8 4 9 . 0 0 0 8 5 3 8 2 7 9 4 ; float aFloat = -34.67 f ; char glyph = d ; String quote = " Bongos Ikwe likes hearing cockrows at dawn . " ;

\n character

to get carriage returns. Lastly, though there are other methods for getting formatted output such as the

3.1.3

Println

The dierence between print, printf, & println is that println will automatically append a carriage return to the string. We have already seen println being used. 31

Format Specier %f %d %e %g %s %c

Data Type Floating Point Integer Exponential General Floating Point String Character

Table 3.2: Java Format Speciers

3.2

The Scanner Class

To get input from the keyboard we use the Scanner object. Before we can invoke Scanner we must add its libraries to our program with the import statement, import java . util . Scanner ; In Java libraries are usually called packages. To actually use the scanner we declare a Scanner object in our program with a statement similar to Scanner myInput = new Scanner(System.in); The statement creates a new instance of the object Scanner called myInput. MyInput gets its value from standard input, which is the keyboard. However to get the input that was typed at the keyboard we need to tell our Scanner object what type of data its getting. To do this Scanner class uses the following methods. nextInt() Returns an integer. nextLong() Returns a long. nextByte() Returns a byte. nextShort() Returns a short. nextDouble() Returns a double. nextFloat() Returns a oat. nextLine() Returns the line until there is a carriagereturn. nextBoolean() Returns a boolean. next() Returns all characters till the next delimiter. The default the delimiter is white space. In GetStaticForce.java we can see how the Scanner class is used to get input from the user. 1 2 3 4 5 6 /* GetStaticForce . java is used to calculate the magnitude of the Coloumbic attraction between two charged bodies . formula for this is ; * * * F = k * ( Q1 * Q2 ) /( r ^2) where Q1 -- First charge Q2 -- Second charge 32 The

7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45

* * */

k -- Coloumbic constant r -- distance

import java . util . Scanner ; public class GetStaticForce { public static final double C OL OU MB IC _C ON ST AN T = 8.987551787 e +9; public static void main ( String [] args ) { double distance = 0.0; // Distance between charges in metres . double chargeOne = 0.0; // Charge one s magnotude in coloumbs . double chargeTwo = 0.0; // The second charge s magnitude , also in coloumbs . // Use numerator & denominator to make electrostatic magnitude // calculation easier to read . double numerator = 0.0; double denominator = 0.0; double e l e c t r o S t a t i c M a g n i t u d e = 0.0; // Scanner input = new Scanner ( System . in ) ; System . out . print ( " Distance between charges ( metres ) : " ) ; distance = input . nextDouble () ; System . out . print ( " Charge One magnitude ( coulombs ) : " ) ; chargeOne = input . nextDouble () ; System . out . print ( " Charge Two magnitude ( coulombs ) : " ) ; chargeTwo = input . nextDouble () ; numerator = CO LO UM BI C_ CO NS TA NT * chargeOne * chargeTwo ; denominator = distance * distance ; e l e c t r o S t a t i c M a g n i t u d e = numerator / denominator ;

33

46 47 48 49 50 } }

System . out . printf ( " \ n \ nFor charges of %.3 f and %.3 f coloumbs " , chargeOne , chargeTwo ) ; System . out . printf ( " \ nthat are %.3 f metres from each other ,\ n " , distance ) ; System . out . printf ( " the electrostatic magnitude : %.3 g \ n \ n " , electroStaticMagnitude );

Program 3.3: GetStaticForce.java On running the program we get the output shown below. $ java GetStaticForce Distance between charges ( metres ) : 23 Charge One magnitude ( coulombs ) : 9.67 Charge Two magnitude ( coulombs ) : 5.43

For two charges with 9.670 and 5.430 coloumbs that are 23.000 metres from each other , the electrostatic magnitude : 8.92 e +08 $

34

Chapter 4

Flow of Control
All programming languages mange the ow of logic in an algorithm by using repetition and branching mechanisms. Repetition is achieved either by using iterative or recursive operations while branching has traditionally been done with some variant of the if statement. Let us start by examining Javas branching mechanisms.

4.1

Java Branching Mechanisms

In Java like most programming languages ow of control goes from the start to the stop in a linear sequence of steps. However in all algorithms we need to make choices about the which option to follow out of several possible ones, each of these paths will change the programs ow of execution. To decide which path to take Java has a number of branching constructs, these constructs are; if if-else switch In the remainder of this section we shall look at each construct in more detail.

4.1.1

The If Statement

The format of an if statement is;

if (boolean expression)

statements for true

The statement that immediately follows an if is executed when the if statements condition is true. If we want to execute multiple statement we group them with curly braces. A code fragment has been shown to give you an idea of how the if statement is used. 35

if ( bloodPressure >= 120.0) { alarm = " on " ; System . out . print ( " \ n " ) ; } It can be seen from the code fragment that if we want to execute multiple commands with the if statement we place curly braces around them.

4.1.2

If-Else

A limitation of the if statement is that we do not explicitly state what will be done if the boolean condition in parenthesis is not met. To choose between two options we use the if-else construct, its syntax is;

if (boolean expression)

statements for true

else statements for false

GetsPenStatistics.java uses if-else statements in deciding which logic to execute. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 } Program 5.1: GetsPenStatistics.java 36 } else System . out . println ( " Since there are " + numOfPens + " no new orders of pens are necessary " ) ; } if ( numOfPens <= orderThreshold ) { amountToOrder = orderThreshold - numOfPens ; System . out . println ( " Order " + amountToOrder + " pens " ) ; { public static void main ( String [] args ) { int numOfPens = 6; int orderThreshold = 10; int amountToOrder = 0; /* If the number of pens in inventory falls below 10 boxes GetPenStatistics * will print a message saying taht more need to be ordered , otherwise it * will report that no new pens should be ordered . */ public class Get sPenS tatist ics

Nested If-else Statements We can nest if-else statements as shown in AssignsLetterGrade.java which is shown below. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 else { letterGrade = N ; System . out . println ( " Invalid score . " ) ; 37 /* Depending on the value of percentage we assign a specific grade . * If there is a problem assigning a grade then we print an error * message that says invalid score and assigns N to letterGrade . */ if ( percentage >= 90) letterGrade = A ; else if (( percentage <= 89) && ( percentage >= 80) ) letterGrade = B ; else if (( percentage <= 79) && ( percentage >= 70) ) letterGrade = C ; else if (( percentage <= 69) && ( percentage >= 60) ) letterGrade = D ; else if (( percentage <=59) && ( percentage >= 0) ) letterGrade = F ; Scanner input = new Scanner ( System . in ) ; // Get the percentage from the user . System . out . print ( " Enter the percentage : " ) ; percentage = input . nextDouble () ; public class A ss ig ns Le tt er Gr ad e { public static void main ( String [] args ) { char letterGrade ; double percentage = 0.0; // The percentage of points recieved . import java . util . Scanner ; /* Ass ig ns Le tt er Gr ad e will give a letter grade based on the percentage * that the student recieved out of the total possible points . */

39 40 41 42 43 44 45 46 47 48 } }

} if ( letterGrade != N ) { System . out . printf ( " For a score of %2.2 f percent " , percentage ) ; System . out . printf ( " the grade is %1 c .\ n " , letterGrade ) ; }

Program 5.2: AssignsLetterGrade.java

4.1.3

Boolean Operators

Decisions in Java are made using boolean logic and we have a certain number of comparison operators available. Javas comparison operators are shown in the table below. Operator == != > <= >= && | & | Function Equality Not equal Less than Greater than Less than or equal to Greater than or equal to Partial logical and Partial logical or Complete logical and Complete logical or

Table 4.1: Table4.1: Java Comparison Operators The dierence between the && and & operators is that && does not evaluate the whole logical expression before returning either true or false instead the rst time it sees a false case it returns false. On the other hand & will evaluate the whole expression before it returns its result. Since && and give a false the rst time one of their options fails we say they use lazy evaluation. Consider the code fragment x = 5; if (( x < 6) || ( x == 2) ) result = x + 23; Since the rst condition is true Java will return true without checking the x == 2 condition. A second case is; 38

angle = 45.0 f ; s pe e d In M e tr e s Pe r S e c = 14.5 f ; if (( angle >= 48.5 f ) && ( speed > 135) ) damage = mass * speed * speed * 403; damage = mass * speed * 12.4; Since the angle is less than 48.5 the if statement will not check the second condition and return false without checking that the speed is greater than 135 so it will calculate damage with the formula, damage = mass speed 12.4 If we used the & operator instead it would not use lazy evaluation. The boolean operators also have precedence so now we can expand our precedence table that we discussed earlier.

4.1.4

Switch

We have seen that multiple branches can be done with nested if statements, however this method can be dicult to follow without indentation. Another construct that can be used for selecting among several outcomes is the switch statement. Precedence Highest Function ++ typecast */% +<><=>= == != & || && | = *= /= %= += -=

Lowest

Table 4.2: Table 4.2: Complete Precedence Rules The format of a switch statement is: switch ( variable ) { case value1 : statement ; break ; case value2 : statement ; 39

break ; case valueN : statement ; break ; default : statement ; break ; } The default case is optional and is executed if the variables current value is not handled by any of the other case statements. Best practices are to always have a default statement in a switch since it can be used for error checking. One of the limitations of switch is that can only take single integers or possibly characters. To see how switch and nested if-else statements compare look at the following two implementations of associating numbers with names of months, ConvertsNumberToMonth.java & ConvertsNumberToMonth2.java. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 switch ( number ) { case 1: nameOfMonth = " January " ; break ; 40 System . out . print ( " Number : " ) ; number = input . nextInt () ; System . out . print ( " C o n v e r t s N u m b e r T o M o n t h 2 displays the month that " ) ; System . out . print ( " corresponds to the number that the user entered ."); System . out . print ( " \ nIf the value input is larger than 12 " ) ; System . out . print ( " then only an error message is displayed .\ n " ) ; Scanner input = new Scanner ( System . in ) ; public static void main ( String [] args ) { int number = 0; String nameOfMonth = " " ; public class C o n v e r t s N u m b e r T o M o n t h { public static final int NUM_OF_MONTHS = 12; import java . util . Scanner ;

27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 }

case 2: nameOfMonth = " February " ; break ; case 3: nameOfMonth = " March " ; break ; case 4: nameOfMonth = " April " ; break ; case 5: nameOfMonth = " May " ; break ; case 6: nameOfMonth = " June " ; break ; case 7: nameOfMonth = " July " ; break ; case 8: nameOfMonth = " August " ; break ; case 9: nameOfMonth = " September " ; break ; case 10: nameOfMonth = " October " ; break ; case 11: nameOfMonth = " November " ; break ; case 12: nameOfMonth = " December " ; break ; default : System . out . println ( " Invalid number " ) ; System . exit (2) ; break ;

System . out . printf ( " % d corresponds to the month named " , number ) ; System . out . printf ( " % s .\ n " , nameOfMonth ) ;

41

68 69 }

Program 5.3: ConvertsNumberToMonth.java If we had run the same program with nested if-else it would have been as follows; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 else if ( number == 5) 42 else if ( number == 4) nameOfMonth = " April " ; else if ( number == 3) nameOfMonth = " March " ; else if ( number == 2) nameOfMonth = " February " ; if ( number == 1) nameOfMonth = " January " ; System . out . print ( " Number : " ) ; number = input . nextInt () ; Scanner input = new Scanner ( System . in ) ; System . out . print ( " C o n v e r t s N u m b e r T o M o n t h 2 displays the month that " ) ; System . out . print ( " corresponds to the number that the user entered ."); System . out . print ( " \ nIf the value input is larger than 12 " ) ; System . out . print ( " then only an error message is displayed .\ n " ) ; public static void main ( String [] args ) { int number = 0; String nameOfMonth = " " ; public class C o n v e r t s N u m b e r T o M o n t h 2 { public static final int NUM_OF_MONTHS = 12; import java . util . Scanner ;

35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 } } else else

nameOfMonth = " May " ; else if ( number == 6) nameOfMonth = " June " ; else if ( number == 7) nameOfMonth = " July " ; if ( number == 8) nameOfMonth = " August " ; else if ( number == 9) nameOfMonth = " September " ; else if ( number == 10) nameOfMonth = " October " ; else if ( number == 11) nameOfMonth = " November " ; else if ( number == 12) nameOfMonth = " December " ;

{ System . out . println ( " Invalid number " ) ; System . exit (2) ; } System . out . printf ( " % d corresponds to the month named " , number ) ; System . out . printf ( " % s .\ n " , nameOfMonth ) ;

Program 5.4: ConvertsNumberToMonth2.java The Switch statement can only be used with integers and chars. We also cannot use it for a range of numbers as was seen in AssignsLetterGrade. One thing that you may notice about ConvertsNumberToMonth is that it appears cleaner than ConvertsNumberToMonth2 so it may be easier to follow the former programs logic. However, both programs produce the same output as seen in below. $ java C o n v e r t s N u m b e r T o M o n t h 2 C o n v e r t s N u m b e r T o M o n t h 2 displays the month that corresponds to the number 43

that the user enters . If the value input is larger than 12 then an error message is printed . Number : 56 Invalid number $ java C o n v e r t s N u m b e r T o M o n t h C o n v e r t s N u m b e r T o M o n t h 2 displays the month that corresponds to the number that the user entered . If the value input is larger than 12 then only an error message is displayed . Number : 56 Invalid number $ java C o n v e r t s N u m b e r T o M o n t h C o n v e r t s N u m b e r T o M o n t h 2 displays the month that corresponds to the number that the user entered . If the value input is larger than 12 then only an error message is displayed . Number : 6 6 corresponds to the month named June . $ java C o n v e r t s N u m b e r T o M o n t h 2 C o n v e r t s N u m b e r T o M o n t h 2 displays the month that corresponds to the number that the user enters . If the value input is larger than 12 then an error message is printed . Number : 6 6 corresponds to the month named June . $

4.2

Iteration

The second group of control structures in Java is used for repeating a set of tasks until a condition is met in the literature you will read that iterative structures are also referred to as loops. Java has the following constructs for looping; while do-while for

4.2.1

While Loop

The format of a while loop is

while (boolean expression)


44

statement;

Without brace the while loop only does the one statement immediately after the while. So for the code fragment int count = 0; while ( count < 22) System . out . println ( " Count is " + count ) ; count ++; will print Count is 0 an innite amount of times. If we ever get out of the loop it will then increment count to 1. So to get both the print statement and the count of be incremented we will use curly braces. int count = 0; while ( count < 22) { System . out . println ( " Count is " + count ) ; count ++; } With a while loop the boolean expression is evaluated before the statements are executed so it is possible that the statements in the loop body are never executed when the boolean evaluates to false.

4.2.2

Do-While Loop

The format of a do-while loop is

do {

statements;

} while (boolean expression);

An example of a do-while loop is do { letter = scannerObject . nextString () ; } while (( letter != " \ t " ) || ( letter != " " ) ; We see that in a do-while loop the statements are executed at least since since the test is at the bottom of the do-while construct.

4.2.3

For Loop

The traditional use of a for loop was for accessing the elements of an array or incrementing a counter. For loops only work with numbers, ideally you should only use integers with a for loop while the while and do-while can work with all data types. The for loops syntax is,

for (initialization; boolean expression; update expression)

vspace5mm statements;

45

for ( initialization ; boolean_test ; update _expre ssion ) statements ; An example of a for statement is shown in the code fragment below. for ( index = 0; index < 10; index ++) System . out . println ( " Index : " + index ) ; If we look at ChecksBalance.java we can see how all the ow control elements can be used in a program. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public static void main ( String [] args ) { int accountNumber = 0; 46 } private static void PrintsAppInfo () { System . out . println ( " ChecksBalance prints out what the customer s current balance is . " ) ; System . out . println ( " Its inputs are ;\ nthe six digit account number , previous balance , payments , charges , and the credit limit . " ) ; System . out . println ( " To stop ChecksBalance types N to quit . " ) ; System . out . println ( " As output it displays the current balance and available credit " ) ; System . out . println ( " When the credit limit is exceeded the message , \" credit limit exceeded \" is printed . " ) ; public class ChecksBalance { public static final float INTEREST_RATE = 0.052 f ; /* Name : Banji Lawal * Lab : 1 * Class : CSC101 * Date : 23/10/2009 * * Filename : ChecksBalance . java * Program Function : ChecksBalance reports if there is any available credit for an account . */ import java . util . Scanner ;

30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68

String answer = " y " ; float oldBalance = 0.0 f ; float newBalance =0.0 f ; float charges = 0.0 f ; // Amount of money borrowed float payments = 0.0 f ; // How much was paid in the last month float creditLimit = 0.0 f ; float availableCredit = 0.0 f ;

// We need two Scanners , one for getting numbers , // the other for Strings . Scanner getsNumber = new Scanner ( System . in ) ; Scanner getsAnswer = new Scanner ( System . in ) ; // Print statements explaining what ChecksBalance . java does . the // user interacts with it . PrintsAppInfo () ; // Priming read for our loop . System . out . print ( " \ n \ nContinue ( y / n ) ? " ) ; answer = getsAnswer . nextLine () ; while ( answer . equalsIgnoreCase ( " y " ) ) { System . out . print ( " \ nSix Digit Account Number : " ) ; accountNumber = getsNumber . nextInt () ; // Here we are making sure that account numbers are 6 digits long . // we only enter this loop when account numbers are wrongly formatted . while (( accountNumber >= 0) && ( accountNumber < 100000) ) { System . out . println ( " Invalid account number " ) ; System . out . print ( " Account Number : " ) ; accountNumber = getsNumber . nextInt () ; } and how

47

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 } //

// Get information about payments , charges , balances , and the credit limit . System . out . print ( " Old Balance : " ) ; oldBalance = getsNumber . nextFloat () ; System . out . print ( " Charges : " ) ; charges = getsNumber . nextFloat () ; System . out . print ( " Payments : " ) ; payments = getsNumber . nextFloat () ; System . out . print ( " Credit Limit : " ) ; creditLimit = getsNumber . nextFloat () ; // Calculating the new balance and availabe credit . newBalance = (( oldBalance * INTEREST_RATE ) + oldBalance + charges ) - payments ; availableCredit = creditLimit - newBalance ; // Display information about the account System . out . println ( " \ n *********** Current Account Summary *********** " ) ; System . out . printf ( " \ nAccount Number : " + accountNumber + " \ n " ) ; System . out . printf ( " Credit Limit : %.2 f \ n " , System . out . printf ( " New Balance : %.2 f \ n " , creditLimit ) ; newBalance ) ;

System . out . printf ( " Available Credit : %.2 f \ n " , availableCredit ) ; if ( newBalance >= creditLimit ) System . out . println ( " Credit limit exceeded . " ) ; // User is given the chance to exit the loop . System . out . print ( " \ n \ nContinue ( y / n ) ? " ) ; answer = getsAnswer . nextLine () ; } When the user indicates that they want to stop exit the program . { System . exit (0) ; }

if (( answer == " n " ) || ( answer == " N " ) )

48

107 108 } Program 5.5: ChecksBalance.java From this we have now looked the three elements of all algorithms in Java, since we have looked at simple Java statements, decisions, and loops.

49

50

Chapter 5

Methods
5.1 Introduction

One of the things that happens frequently in a program is repetition, We might repeat a code block because a variable meets certain conditions as in the code fragment below. 1 2 3 4 5 6 } we could create a subroutine that would evaluate the if statement. This is necessary because there are many Watergate conspirators. For another example to nd the square root of a number with Heros formula as is done in GetSquareRoot.java. 1 2 3 4 5 6 7 8 9 10 11 12 13 /* * * Main method finds the square by using the Babylonian method . For * information about the algorithm see * http :// en . wikipedia . org / wiki / Methods_of_computing_square_roots , The * arguments are an double and an it that are passed from the command line . * 51 /* * * GetSquare class will find the square of a number . */ public class GetSquareRoot { package src ; name = aScanner . next () ; while ( !( name . equals ( " I want to stop " ) ) { if ( name . equals ( " George McBundy " ) ) System . out . println ( " Another Watergate conspiracist !! " ) ;

14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

* @param number * * */ public static void main ( String [] args ) { double seed = 0; // We start our square root approximation with this . double approxRoot ; double number = 0; // Get from command line int index = 0; // This is used in finding the seed . int tempNumber = 0; // A holding value . int numOfPasses = 0; // Get from command line // The following code block is used to get our arguments and // does some basic error checking . if ( args . length == 2) { try { number = Double . parseDouble ( args [0]) ; numOfPasses = Integer . parseInt ( args [1]) ; } catch ( N u m b e r F o r m a t E x c e p t i o n e ) { System . out . println ( " Arguments are not numbers . " ) ; System . exit (5) ; } } else { System . out . println ( " Invalid number of arguments " ) ; System . exit (2) ; } // Explain what the program is doing at this stage . System . out . print ( " Trying to find the square root of " + number ) ; System . out . print ( " in " + numOfPasses + " passes .\ n " ) ; // We are doing the steps below to calculate the seed . The size // of the seed depends on the number of digits that our number // has . tempNumber = ( int ) number ; the value whose root will be found . how many iterations of the method will be done . * @param numOfPasses

52

54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93

int numOfDigits = 0; int remainder = 0; int sum = 0; // Using this while loop to count the number of digits in number . // This can probably be done in a simpler way . while ( tempNumber > 0) { remainder = tempNumber % 10; sum += remainder ; tempNumber /= 10; System . out . print ( " . " ) ; numOfDigits ++; } // Now that we know numOfDigits we can find the seed . The seed s // value differs if numOfDigits is even or odd . if (( numOfDigits % 2) == 0) { index = ( numOfDigits - 2) / 2; seed = 6 * Math . pow (10 , index ) ; } else { index = ( numOfDigits - 1) / 2; seed = 2 * Math . pow (10 , index ) ; } // Initial value of our square root is the value of the seed . approxRoot = seed ; // Iterate using the formula ; // current approxRoot = 0.5 ( last approxRoot + ( number /( last // approxRoot ) ) // for ( int i = 0; i < numOfPasses ; i ++) { // System . out . print (" pass #: " + i ) ; // System . out . print (" Current square root : " + approxRoot + "\ n ") ; System . out . print ( " . " ) ; approxRoot = 0.5 * ( approxRoot + ( number / approxRoot ) ) ;

53

94 95 96 97 98 99 100 }

} // Display the final result . System . out . printf ( " \ n %.3 f is the square root of %.3 f \ n " , approxRoot , number ) ; }

Program 6.1: GetSquareRoot.java Again we see that there are certain operations that are run multiple times and we can easier to understand and maintain by using methods, also know as functions, procedures, or subroutines, in a larger Java program. Now we can dene what a method is an explore how they are used.

5.2

Denition

A method is a block of code in a program that has its own address space in main memory, its own variables. The beginning of a function is designated by the method header and an opening curly brace, the close is indicated by a closing curly brace.

5.3

The Method Header

The method header gives us information about the type of data that is sent to the calling program; as well as the functions name, how the method is accessed, and what it needs as inputs.

modier returnType methodName(parameter list)


Now we can examine each eld in the method header.

5.3.1

Modier

The modier deals with how the function is accessed by other Java programs or functions. At the current time shall only deal with the public modier. This modier means that other programs, classes and methods can access and use the subroutine.

5.3.2

Return Type

Subroutines are called from a larger program that they are a part of; or by a completely separate application. When a subroutine is called it either returns a value to whatever entity invoked it; or it will conduct an operation that does not generate a value such as displaying a message, sort a list, or open a le. For the latter type of functions we use the keyword void to show that nothing is returned.

54

On the other hand subroutines that pass a value back to their invoker will specify what type of data will be passed back to the caller when method has completed its run. In this case the return type corresponds to either the primitive data type or object that is needed by the invoker.

5.3.3

Method Name

Method names should describe what the function does, so a name like GetsMailingAddres is a good, descriptive function name, whereas func1 is not. If a subroutines name captures what is hoped to be accomplished in the subroutine then it makes it easier for the reader to intuitively grasp what is happening. Its a good idea to avoid using the letter l I, or O in all method and identier names since these can be confused with 1 and 0 on some displays. Whenever possible put the word get in a functions name if its returning a value. Lastly, unction names should always begin with a lowercase letter so that they are not confused with class names.

5.3.4

Parameter List

These are the inputs that the method needs to complete its task, these inputs are enclosed within braces. The parameters can either be primitive or abstract data types. The parameter list is composed of each inputs data type as well as its identier. If there is more than one parameter they are separated by commas as seen in the examples below. public int getsMax ( int x1 , int x2 , int x3 ) public void dis playS ocketI nfo ( Socket s ) public String getsInput ()

5.4

The Method Body

As was stated earlier the statements that are used to accomplish a subroutines goal are enclosed withing curly braces. If the subroutine returns a value then the last statement executed in it must be a return as seen in getTime. public String getTime () { String time = System . exec ( time ) ; return time ; } While printsTime is a void function. public void printTime () { Process p = null ; Runtime runner ;

55

try { runner = Runtime . getRuntime () ; p = runner . exec ( " time " ) ; } catch ( Exeception e ) { System . out . println ( " Error get proccess .) ; System . exit (22) ; } System . out . print ( " The current time is " ) ; System . out . print ( " System . out .( p ) ; }

5.5

Invoking Functions

The way a procedure is called depends on its return type. If its a void method then we can invoke the procedure with a statement similar to,

methodName(arguments)
On the other hand subroutines that pass a value back to their caller need a palce to store their value, so these subroutines are always invoked with an assignment operator,

variable = methodName(arguments)
For examples of both classes of function call look at Area.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 } 56 public static void PrintsArea ( String shape , double area ) { System . out . printf ( " The % s has an area of %.2 f \ n " , shape , area ) ; } return area ; public static double getsTriangleArea ( double height , double base ) { double area = 0.5 * base * height ; } public static double getsCircleArea ( double radius ) { return ( Math . PI * radius * radius ) ; public class Area { package src ;

18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 } Program 6.2: Area.java } PrintsArea ( shape , triangleArea ) ; triangleArea = getsTriangleArea (6 , 14) ; shape = " triangle " ; PrintsArea ( shape , circleArea ) ; String shape = new String () ; circleArea = getsCircleArea (5) ; shape = " circle " ; public static void main ( String [] args ) { double triangleArea = 0; double circleArea = 0;

5.6

Scope Rules

Programs are stored in the computers hard drive as les. When we execute a program they get moved to main memory (the RAM) where its assigned some slices of the memory address space to store its values. The only time that the central processing unit can fetch the program to execute its instructions is when the program is in RAM. In the RAM a certain amount of the space is assigned to each variable and method. So from this we can surmise that Area.javas memory layout is as follows. getsTriangleArea getsCircleArea main Table 5.1: GetArea.javas Layout in RAM Table5.1 shows that the each section of Areas address space is assigned toa function, if there were global variables those would also be in the address space. The next table shows mains address space. Variable circleArea triangleArea Value 0 0

Table 5.2: Mains Initial Address Space 57

Later the other two methods are called by main and then the programs call stack changes to what we see in the next diagram.

Then when the processor has executed all the instructions in Area.java the programs functions will be in the nal state shown in table 5.3. You will notice that main and getsCircleArea have dierent values assigned to radius.

main circleArea triangleArea radius

78.5714 42.0 7

getsCircleArea radius

getsTrianleArea base height area

13 6 42

Table 5.3: Final State Of Area.javas Method Stacks This shows us that a functions variables only exist in the methods address space furthermore, all of methods variables are completely independent and unrelated to another functions variables. Another way of explaining the relations between a method and its variables is to say that generally the scope of its existence and operations are restricted to the subroutine that created it. ScopeIllustrator.java also shows how scope rules work.

1 2 3

package src ; public class ScopeIllustrator { 58

4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 } Program 6.3: ScopeIllustrator.java Scope rules also apply to code blocks that are surrounded by curly braces. So in following code fragment there are two variables named x. The one inside the loop is completely unrelated to the one outside it. x = 5; for ( int x = 1; x < MAX_VALUE ; x ++) { System . out . print ( " x is " + x + " \ n " ) ; } If you put the next fragment into a Java program you will see that the inner and out as have dierent scopes. int a = 12; char aChar = d ; if ( aChar == d ) { int a = 6; while ( a < 20 ) { System . out . println ( " Inner a : " + a ) ; a ++; } 59 } swap ( neroValue , yhwhValue ) ; System . out . print ( " \ n From main nero s number is " + neroValue + " while " ) ; System . out . println ( " yhwh s value is " + yhwhValue ) ; public static void main ( String [] args ) { int neroValue = 666; int yhwhValue = 777; } public static void swap ( int neroValue , int yhwhValue ) { int temp = neroValue ; neroValue = yhwhValue ; yhwhValue = temp ; System . out . print ( " From swap nero s number is " + neroValue + " while " ) ; System . out . println ( " yhwh s value is " + yhwhValue ) ;

} System . out . println ( " Outer a : " + a ) ; It is possible to create variables that can be changed any where in the program. These variables are global in scope. If you look at ConvertsTemperature.java you will see that its only global variable is answer. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 if ( scale . equalsIgnoreCase ( " F " ) ) { scale = " Farenheit " ; oppositeScale = " Celsius " ; c els iu sT oF ar en he it ( temp ) ; 60 System . out . print ( " Temperature : " ) ; temp = getTemp . nextDouble () ; System . out . print ( " Scale ( Type \" F \" for Farenheit or \" C \" fo Celsius ) : " ) ; scale = getScale . next () ; Scanner getTemp = new Scanner ( System . in ) ; Scanner getScale = new Scanner ( System . in ) ; String scale = new String () ; String oppositeScale = new String () ; public static void main ( String [] args ) { double temp = 0.0; public static void cel si us To Fa re nh ei t ( double farenheitTemp ) { answer = (5.0 * farenheitTemp / 9.0) - 32.0; } } public static void far en he it To Ce ls iu s ( double celsiusTemp ) { answer = (9.0 * celsiusTemp / 5.0) + 32.0; public class Co n v e rt s T em p e ra t u re { static double answer = 0.0; import java . util . Scanner ; package src ;

36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 } }

} else if ( scale . equalsIgnoreCase ( " C " ) ) { scale = " celsius " ; oppositeScale = " Farenheit " ; f are nh ei tT oC el si us ( temp ) ; } else { System . out . println ( " Invalid temperature scale . " ) ; System . exit (55) ; } System . out . printf ( " %.2 f in % s is %.2 f in % s .\ n " , temp , scale , answer , oppositeScale ) ;

Program 6.4: ConvertsTemperature.java $ java C o n ve r t sT e m pe r a tu r e Scale ( Type " F " for Farenheit or " C " fo Celsius ) : f Temperature : 212 212.00 in Farenheit is 85.78 in Celsius . $

5.7

Function Overloading

In the natural and abstract world we frequently add things together. For example the procedure for adding integers diers from the one used for real numbers; If we want to make a new word by joining two old ones the rules for adding the two words depends on the language; Tailors spend their days adding pieces of cloth together; Lastly video editors and bittorrent ends will spend time splicing video and audio les. If you think about this it becomes very clear that even all these operations deal with addition the procedure for joining the two components are all very dierent. In procedural languages such as C we would create a separate adder for each datatype but with object oriented languages such as Java we will put all these diering methods into a class called Adder. 1 2 3 4 61 public class Adder { package src ;

5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45

public static Complex add ( Complex a , Complex b ) { Complex answer = new Complex () ; answer . setReal ( a . getReal () + b . getReal () ) ; answer . setImaginary ( a . getImaginary () + b . getImaginary () ) ; return answer ; } public static String add ( String a , String b ) { return ( a + b ) ; } public static double add ( double angleA , double angleB ) { double sum = degreesToRadians ( angleA ) + degreesToRadians ( angleB ) ; return ( radiansToDegrees ( sum ) ) ; } public static double degreesToRadians ( double angleInDegrees ) { return (180.0 * angleInDegrees / Math . PI ) ; } public static double radiansToDegrees ( double angleInRadians ) { return ( angleInRadians * Math . PI / 180.0) ; } public static void main ( String [] args ) { Complex a = new Complex (5 , 3) ; Complex b = new Complex (2 , 6) ; double angleOne = 280.0; double angleTwo = 73; String firstBookTitle = " Flow My Tears The Policeman Said " ; String secondBookTitle = " Burning Grass " ; double result = add ( angleOne , angleTwo ) ; Complex answer = add (a , b ) ; System . out . printf ( " %.2 f degrees to %.2 f degrees " , angleOne ,

62

angleTwo ) ; 46 47 48 49 50 51 52 53 54 } Program 6.5: Adder.java Inside Adder there are three methods named add. Whenever subroutines have the same name we call this phenomena overloading. Despite add being overloaded three times Java is able to tell all the methods apart because they all have diering return types as well as dierent types of arguments. $ javac Adder . java $ java Adder 280.00 degrees to 73.00 degrees gives a sum of 353.00 dgerees . (3.0 , 5.0) + (6.0 , 2.0) = (9.0 , 7.0) Flow My Tears The Policeman SaidBurning Grass $ While the rst add returns a Complex object the second returns a String, while the last one returns a double. As for their arguments; the rst add takes two Complex numbers, the second one two Strings, and the last add method requires to doubles. The Java interpreter rst looks at return types to see distinguish between overloaded functions. If the return types are the same then parameter list is used. printsChar ( " A Fish , a barrel , and a smoking gun . " ) ; printsChar ( H ) ; Even though both printsChar functions do not return anything the interpreter can easily tell them apart because one takes a String while the other needs a char. If the overloaded methods have diering number of arguments but of the same type Java can still tell them apart. public int max ( int x , int y ) { int result = x ; if ( y >= x ) result = y ; return result ; 63 } System . out . print ( a . toString () + " + " + b . toString () ) ; System . out . println ( " = " + answer . toString () ) ; System . out . print ( add ( firstBookTitle , secondBookTitle ) + " \ n " ) ; System . out . printf ( " gives a sum of %.2 f dgerees .\ n " , result ) ;

} public int max ( int x , int y , int z ) { if ( ( x >= y ) && ( x >= z ) ) int result = x ; else if (( y >= x ) && ( y >= z ) ) int result = y ; else int result = z ; return result ; }

5.7.1

How The Interpreter Evaluates Overloaded Functions

Since one max takes three arguments and the other takes two the Java can easily dierentiate between both subroutines. To summarize the interpreters rules for distinguishing between overloaded functions: 1. Look at the return types to see which method should be invoked. 2. If inspecting the return types does not give an answer then look at how many arguments were passed. 3. If the methods have the same return type and same number of arguments then look at the data types of the arguments from left to right. 4. If none of the preceding tests worked then the interpreter will implicitly typecast arguments to see if it can get a match. 5. When all the other steps have failed Java will invoke the one that appears earliest in the class. 6. If all the steps failed then the compilation will fail.

5.8

Documenting Methods

An unwary programmer can make the mistake of invoking an overloaded method with the wrong arguments. This is one of the reasons why its a very important to document our functions. If you look at the literature there is a great deal of information on diering function documentation styles. One popular style involves putting comments about the pre & post condition of the method as well as discussing boundary conditions. However this is not the best documentation style for Java,

64

To avoid confusion and make it easier for colleagues to read and understand what you are doing use the same documentation style that is in the Java APIs. On your system the documentation is at /javadoc/java1.6.0opendjdk/api/index.html. If you take a look at the concat method for String class the API explains what concat returns, describes its function and tells u what data types concats parameters need to be. /* g e t s V a n d e r W a a l s P r e s s u r e calculates the pressure of a gas using the Van * der Waals equation P = RT /( Vm - b ) - ( a /( Vm * Vm ) ) . * * Precondition : Gets passed Van der Waals coefficients a & b , molar * volume , & temperature . The variables are all doubles . * * Postcondition : Returns pressure as a double . */ public static double g e t s V a n d e r W a a l s P r e s s u r e ( double bCoeff , double aCoeff , double molarVol , double kelvinTemp ) { double pressure = (( GAS_CONST * kelvinTemp ) / ( molarVol - bCoeff ) ) - ( aCoeff /( molVol * molVol ) ) ; return pressure ; } getsVanderWaalsPressure is one of GasModels subroutines. It turns out that the development shop that owns this code prefers to use pre & post conditions to document their code.

5.8.1

Using Javadoc

As was mentioned before its best to follow Javas recommended best practices to write documentation. This can be done very easily with Javadoc. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 /* * * Displays a bar chart in ascending order of an array s contents . * * @param ARRAY_SIZE * * */ public class BarCharter { public static final int ARRAY_SIZE = 10; 65 the size of the array . global int array * @param anArray import java . util . Random ; package src ;

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54

private static int [] anArray ; /* * * Get the largest value in intArray . * * @param intArray * array to be searched for largest value . * @param pos * */ public static int max ( int [] intArray , int pos ) { int largest = intArray [ pos ]; for ( int i = pos + 1; i < intArray . length ; i ++) if ( intArray [ i ] > largest ) largest = intArray [ i ]; return largest ; } /* * * Prints n stars . * * @param n */ public static void printStars ( int n ) { System . out . print ( n + " | " ) ; for ( int i = 0; i < n ; i ++) System . out . print ( " * " ) ; System . out . println () ; } /* * * Fills myArray with random numbers . Then calls max () and printStars () . */ public static void main ( String [] args ) { Random rander = new Random () ; where the search starts in the array . * @return the highest value found in the array .

66

55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 } }

int number ; int [] myArray = new int [ ARRAY_SIZE ]; for ( int i = 0; i < ARRAY_SIZE ; i ++) { number = rander . nextInt (100) ; myArray [ i ] = number ; } for ( int j = 0; j < ARRAY_SIZE ; j ++) { int currentMax = max ( myArray , j ) ; printStars ( currentMax ) ; }

Program 6.6: BarCharter.java Somethings to notice are: The block comments are the same as what we have seen elsewhere. Each function parameter is described in the comment block. Each parameters description is separated from the functions description by a blank line. Para,eter descriptions must be in the format; @param parameterName description of parameter. To describe what the method returns we use the @return tag. The main method does not have any parameter description. There are many more tags available for avadoc but these will be sucient for what is necessary at this time. After putting in the documentation now we need to generate a html le similar to what we saw in the Java API. To create the html doc we run the command;

javadoc -d < documentaionDirectoryP ath > leName.java


So for BarCharter.java the command was; $ javadoc -d / home / afura / java / docs / BarCharter . java $

5.9

Tips For Using Methods

Methods can make it much easier to write and debug programs. Some things that you should think about before writing will be discussed in this section. 67

5.9.1

One Task Per Method

If you try and accomplish more than one task in a function your body will be harder to debug and understand. So do not combine two tasks into one. Remember that functions are free but the debugging them is paid in blood. Furthermore functions have one return type not two for a reason.

5.9.2

Brevity Is Best

If I spend more than 20 minutes thinking about the steps in my subroutine I tend to assume that I am doing too much and might need to spawn other functions. As a result of this most of my methods are under 15 lines. Making methods short aids in comprehending what is happening.

5.9.3

Dont Overdo Overloading

Overloading is very useful to programmers. However care must be taken since on some occasions Java will implicitly typecast a variable. If you are no paying attention to your code this implicit typecasting can introduce subtle errors.

5.9.4

Debug As You Go

To make sure that each method works properly debug and test it once its written. Later on when we cover unit testing we shall look at the benets of writing tests before implementing the methods. All methods should be debugged separately. One of the things that will make debugging easier for you is using Junit which we will discuss at a later time.

5.9.5

Provide Documentation

All your subroutines should have documentation about what they do. The documentation comments should be terseness too much information, or redundant information can be confusing and takes time to read while it does not give the programmer anything new. Apart from using javadoc make your identiers, class and variable names descriptive so that the program is self documenting.

5.9.6

When There Is Repetition Use A Function

If an operation is performed more than once in a program put the repeated code in a function.

5.10

Advantages Of Using Functions

Four of the main advantages of using functions are; i By hiding the complexity of a program its easier for a reader to follow the overall ow & logic of a program. This is even easier if the names of functions describe what they do. ii Important changes can be made and tested in a method without worrying about eects on the rest of the code. 68

iii When subroutines are used programmers can easily divide the work by each working on implementing a method. This division of labour increases the speed at which applications will be deployed.

iv Code blocks that are repeated can be put into a method which streamlines the code. This can also cut down on the amount of typing. 69

BarCharter

le:///home/griot/code/java/BarCharter/BarCharter...

Package Class Tree Deprecated Index Help PREV CLASS NEXT CLASS SUMMARY: NESTED | FIELD | CONSTR | METHOD FRAMES NO FRAMES All Classes DETAIL: FIELD | CONSTR | METHOD

Class BarCharter
java.lang.Object extended by BarCharter public class BarCharter extends java.lang.Object BarCharter.java displays a bar chart of the numbers in an integer array. The integers are displayed in descending order.

Field Summary
static int ARRAY_SIZE

Constructor Summary
BarCharter()

Method Summary
static int FindMax(int[] intArray, int pos) FindMax the maximum value in an array. static void main(java.lang.String[] args) BarCharter's main method fills the global int[] myArray with random numbers. static void PrintStars(int value) PrintsStars displays stars on the screen that correspond to a value. Methods inherited from class java.lang.Object clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Field Detail
ARRAY_SIZE
public static final int ARRAY_SIZE See Also: Constant Field Values

01/20/2011 05:58 AM

70

Chapter 6

Objects And Classes


In the rst chapter it was mentioned that an object is a description of some data and the ways pf manipulating the data. For example consider pen be a set of data points related to its weight, the colour of its ink, how much ink is left, the shape, and its owner. There are a certain number of operations that can be done with the pen. Mainly writing, but a frustrated person can also throw it, a nice pen can be relled, but no matter how hungry a person is they will never try and eat a pen. Neither can we drive one to the next town. Even though there are certain actions associated with a pen there are many that are not. We can drive a car object and eat an object called oranges though. With our intuitive understanding of what an object is we can now dene a class as a description of a data type that includes the methods for manipulating the data and accessing the data. The relationship between a class and its objects is similar to a cars engineering blueprints and the car. The blueprints simply describe what the components are and how they work. With the blueprint we can build many instances of the car. Similarly once we have dened a class we can make instances (objects) of that class.

6.1

Components Of A Class

Let us examine how classes are dened in Java by writing one for a point in the Cartesian coordinate system. Everyone is familiar with the Cartesian systems X and Y axis and how points are referenced by their coordinates in the two dimensions.

71

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40

package src ; import java . awt .*; import javax . swing . JPanel ; /* * * Point . java creates a point using doubles on the Cartesian coordinate system . * * @param x * @param y */ public class Point { private double x ; private double y ; private double z ; /* * * Point () creates a point at the origin , (0 ,0 ,0) */ public Point () { x = 0; y = 0; z = 0; } /* * * Point creates a point at xcoord , * * @param xcoord the x coordinate . * @param ycoord the y coordinate . * @param zcoord the z coordinate . */ public Point ( double xcoord , double ycoord , double zcoord ) { x = xcoord ; y = ycoord ; z = zcoord ; } /* * 72 ycoor , & zcoord .. the x coordinate . the y coordinate .

* @param z the z coordinate

41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 } } } } }

* getsX returns the value of the x coordinate . * @return x coordinate . */ public double getX () { return x ;

/* * * getsY returns the value of the y coordinate . * @return y coordinate . */ public double getY () { return y ;

/* * * getsZ returns the value of the z coordinate . * @return z coordinate . */ public double getZ () { return z ;

/* * * setsX assigns a value to x coordinate . * @param number */ public void setX ( double number ) { x = number ; value to assign too x .

/* * * setsY assigns a value to y coordinate . * @param number */ public void setY ( double number ) { y = number ; value to assign too y .

/* * * setsZ assigns a value to z coordinate .

73

82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 } } } } } }

* @param number */

value to assign too z .

public void setZ ( double number ) { z = number ;

public boolean equals ( Point p ) { boolean answer = false ; if ( this . getX () == p . getX () ) if ( this . getY () == p . getY () ) answer = true ; return answer ;

public double distance ( Point p ) { double result = 0; result = Math . pow (( this . getX () - p . getX () ) , 2) + Math . pow (( this . getY () - p . getY () ) , 2) ; result = Math . sqrt ( result ) ; return result ;

/* * * toString converts Point object into a string . * * @return a string . */ public String toString () { return ( " ( " + this . getX () + " , " + this . getY () + " , " + this . getZ () + " ) " ) ;

public void Draw () { Panel pointPanel = new Panel () ;

74

Program 7.1: Point.java There are four main dierences between Point.java and the other programs we have seen so far. These things are; i The use of the keyword private. ii The use of constructors, Constructors are methods that have the same name as their class. iii The absence of a main method. iv The use of the keyword this to refer to a calling object. So we see that the layout of a class can be broken down into ClassName { instance variables Constructors accesor methods mututor methods }

6.1.1

Instance Variables

These are the data points in the class. Instance variables have a global scope. All instance variables should be preceded by the modier private, Private prevents any function or class outside the current one from directly accessing the instance variables. Doing this helps abstract the details away from the user, which is a good programming practice. Java best practices are to have private instance methods and public methods to access the data. You also here people refer to instance variables as elds.

6.1.2

Constructors

The constructor is used to build an instance of a class. You should always create at least a default constructor which initializes all the data in the object to their null values. Unlike primitives objects and other abstract data types are not initialized. Constructors are frequently overloaded as was seen in Point Chaining Constructors since we can have more than one constructor best practices in OOP are to have all the constructors that take less options be passed to the one that that takes all the elds as arguments when creating an object.

6.1.3

Methods

The methods provide the API (Application Programming Interface) to the class data elds, hence they are public. Generally all functions either access data or modify it. 75

Mutators These change the value of data in some way, best practices call for mutators to have void as their return type. Sometimes people call mutators setters. Accessors Retrieve the value stored in an instance variable and pass it to the entity that called it. Accessors must have a nonvoid return type. A synonym for accessor is getter. Static Versus Nonstatic Methods No doubt you noticed that Point does not have a main method This is because main is a static method. Static methods it can be used without having a class. Since static procedures can only access data in their class they are sometimes called class methods. Functions that are not preceded with the static are instance methods since any chapter four had the keyword static. Lastly a class that has static functions cannot create instances of itself.

6.2

Creating An Object

To use our class we need make an object of the class type. This will be done in another class or program by using the new keyword as shown below.

ClassName variableName = new ClassName(possible args);


This is similar to the declaration of primitive types but we use the word new to let the Java interpreter know that we are going to create an object. New is always succeeded by a constructor invocation. UsesPoint.java shows us how the classes are used in Java. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 if ( a . getX () == b . getX () ) { if ( a . getY () == b . getY () ) 76 /* * * Tests points for equality . * @param a * @param b * @return a boolean , true if the points are equal . otherwise false . */ public static boolean isEqual ( Point a , Point b ) { boolean result = false ; public class UsesPoint { package src ;

16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 } } /* * }

if ( a . getZ () == b . getZ () ) result = true ; return result ;

* Prints a message about two points . * @param a * @param b * @param aString */ public static void printsTestResult ( Point a , Point b , String aString ) { System . out . println ( a . toString () + " and " + b . toString () + aString );

public static void main ( String [] args ) { Point pointOne = new Point (3 , -2 , 34) ; Point pointTwo = new Point (12 , 4.25 , -6.382) ; Point origin = new Point () ; boolean test = false ; String resultString = " are not the same " ; test = isEqual ( pointOne , pointTwo ) ; if ( test == true ) resultString = " are the same " ; printsTestResult ( pointOne , pointTwo , resultString ) ; System . out . println ( " current value of origin is " + origin . toString () ) ; origin . setX (3) ; origin . setY ( -2) ; origin . setZ (34) ; System . out . printf ( " \ norign has been set to % s \ n " , origin . toString () ) ; if ( isEqual ( pointOne , origin ) == true )

77

53 54 55 56 57 } }

resultString = " are the same " ; printsTestResult ( pointOne , origin , resultString ) ;

Program 7.3: UsesPoint.java

6.3

Static versus Nonstatic Variables

Static methods cannot be used outside their class, on the other hand any variables that have the keyword static as a modier can be used outside their class. However static variables are not duplicated. This implies that there is only ever instance of a static variable, on the other hand each instance of a class gets its own instance variables. Since all objects have access to static variables they can change the value globally. This behaviour can lead to applications behaving in an unpredictable manner. For this reason a great deal of care should be taken when using static variables.

6.4

Pass By Value Versus Pass By Reference

As was mentioned earlier a programs data and methods are stored in memory. Main memory is organized in 2-4 byte blocks and each block has an address. There are two ways that programs get their data, they either; i Pass the address of the data to each other (pass by reference). ii Pass the value stored in the location that has the datas address (pass by reference).

6.4.1

Pass By Value

With pass by value every invoker gets a copy of the data, which implies that all these copies are independent of each other. All primitive data types are pass by value in Java. In ScopeIllustrator.java and Area.java we saw pass by value being used.

6.4.2

Pass By Reference

Since this style uses the variables address all the invokers can modify the data shared in the address. All objects use pass by reference. The reason why is that unlike primitives objects have both data and methods, these can be located anywhere in main memory and they are can all be of diering sizes. So the only way an object can keep track of all its data and functions is to refer to their addresses. To see the implications of reference passing instead of value passing let us look at both ReferencePassingTest1.java and ReferencePassingTest2.java.

78

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

package src ; public class R e f e r e n c e P a s s i n g T e s t 1 { public static void main ( String [] args ) { Point aPoint = new Point (5 , 6 , -4.5) ; Point counterPoint = new Point (5 , 6 , -4.5) ; if ( aPoint == counterPoint ) System . out . println ( " They are both aPoint at " + aPoint . toString () + "."); else { System . out . printf ( " The two points are % s & " , aPoint . toString () ); System . out . printf ( " % s . } } } Program 7.4: ReferencePassingTest1.java They are not the same .\ n " , counterPoint . toString () ) ;

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

package src ; public class R e f e r e n c e P a s s i n g T e s t 2 { public static void main ( String [] args ) { Point myPoint = new Point (2 , 3 , 0) ; Point yourPoint = new Point ( -3 , 12.458 , 6) ; yourPoint = myPoint ; if ( yourPoint == myPoint ) System . out . println ( " We share the same point at " + myPoint . toString () + " . " ) ; else System . out . printf ( " Since your point is % s you do not get my point . " , yourPoint . toString () ) ; }

79

20

} Program 7.5: ReferencePassingTest2.java The output of running the two programs ins shown below. $ java R e f e r e n c e P a s s i n g T e s t 1 The two points are (5.0 , 6.0) & (5.0 , 6.0) . $ $ java R e f e r e n c e P a s s i n g T e s t 2 We share the same point at (2.0 , 3.0) . $ Even though point and counterPoint have the same values the equality test on line 7 failed because its testing to see if their addresses are the same. On the other hand yourPoint was assigned to the same address as myPoint so their equality test returned true. One implication of

objectA = objectB

is that there is no native Java method for assigning only values from one object to another because the = operator makes objects point to the same address. As a result of this its very common to implement a copy method in classes so that objects can have pass by value functionality.

6.5

Anonymous Objects

In the following code fragment a point within a certain range is being generated and compared with the origin of a signal. However the variable being passed to compareWithSignalOrigin does not have a name. This is an anonymous object. Anonymous objects are frequently used as temporary place holders. for ( int i = 0; i < 23; i ++) for ( int j = 32; j < 500; j ++) c o m p a r e W i t h S i g n a l O r i g i n ( new Point (( double i ,) , ( double j ) ) ); In the next fragment we see the same result being achieved without an anonymous object. for ( int i = 0; i < 23; i ++) for ( int j = 32; j < 500; j ++) { Point temp = new Point (( double i ) , ( double j ) ) ; c o m p a r e W i t h S i g n a l O r i g i n ( temp ) ; }

6.6

Packages & Classpath

Frequently we need to make a class available to other programs or projects. To do this we create a package and import it. In other languages such as C, C# or Scheme packages are called libraries. To use our own packages we need to add our libraries to the classpath. 80

6.6.1

Classpath

The classpath is an environment variable that tells the Java interpreter where packages are located. So in Windows if the packages are in Programs Files\Java\jdk-1.6.04\libraries then that path is the default value classpath. In Unix the classpath could be \usr\lib\jdk-1.6.04. So when we issue the command import java.util.*; we are saying that Java should incorporate the all classes that are stored in \usr\lib\java\jdk-1.6.04/lib/java/util.

Modifying The Classpath To add our packages to the classpath we simply place a semicolon at the end of the classpath then put the path to our packages there. So if in Windows the classpath currently includes these directories C\ Windows\Java\jdk-1.5.9.48\jre and D\Program Files\java1.6.0.4.22\lib\jre and we want to add our personal libraries in F\myjars we would modify the classpath variable so that it looks like this. C \ Windows \ Java \ jdki -1.5\ jre : D \ Programs \ java1604 .22\ lib \ jre : F \ myjars : Now that you know how to modify the classpath I need to tell you that its a bad idea to change it from its default. This is because it can cause dependencies in your programs. Its better to set your applications classpath at compile time. So the preferred method for setting classpath is,

javac -classpath package path ProgramName.java

6.6.2

Making Packages

If you look at the The package import syntax you can tell that the packageName is actually the name of a subdirectory that is under one of baseDirectorys subDirectories.

import baseDirectory.subDirectory.packageName.ClassName;
Package names are related to the directory path where related classes are found. This is a big reason why the import and package statements take a a hierarchical argument. When Java is looking for a package it assumes that is one of the locations specied in CLASSPATH so the package name needs to start with the directory immediately below a classpath entry. Other directories below the base are listed after that. To illustrate this my classpath has an entry \home\banji\code\java where all my Java programs are written. Each project has a folder of its own and sub folders bin, where the classes are; and src where I keep my source code. One of my projects deals with managing my music library and has the following directory structure. 81

So if I want to the class GetPicture, which is under the downloader to be available to other classes I have to put the line, package music.artwork.downloader; in the beginning of GetPictures declaration. If getWallPapers.java needs to use GetPicture then getWallPapers will import it with the statement; import music.artwork.downloader.GetPicture; Or if I want all the classes in the downloader directory I could type import music.artwork.downloader.*;. As you can see I did not have to include the base directory java in either statement since that is in my path.

6.6.3

Marking Classes As Packages

Once the class path has been set then; either by setting the environmental variable, or at compile time we mark the class as a package with the command,

package ClassName
At the top of Script.java you can see how Script has been marked as a package. Also take note that the package statement shows the path in reverse order. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public boolean isScript ( String extension ) { String [] shellExtensions = new String [] { " sh " , " pl " , " py " , " tk " , " tcl " }; 82 } public Script ( String aFile ) { this . aFile = aFile ; } public Script () { this . aFile = null ; public class Script { private String aFile = null ; package net . kumbi . file . systems ;

16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 } Program 7.6: Script.java ZR } public void setaFile ( String aFile ) { this . aFile = aFile ; } public String getaFile () { return aFile ; } } } return false ; for ( int i = 0; i < shellExtensions . length ; i ++) { if ( extension . equals ( shellExtensions [ i ]) ) { return true ;

83

84

Chapter 7

Arrays
An array is a collection of items that are all of the same type and are stored in contiguous memory locations. The items in an array are referenced by their index, the index shows the items position in the array. It is important to note that array sizes are immutable. index 0 1 2 3 4 5 a b c d e f

Table 7.1: charArray The statement, char [] charArray = { a , b , c , d , e , f }; made the array seen above. If a researcher wanted to store the ages of three hundred survey participants who live in Jimeta they could use an array for this. Another situation where an array might be used is for storing the length of time that 23,000 Glo customers spent waiting for a clear.

7.1

Declaring Arrays

Arrays are created with a statement that corresponds to one of the three forms;

dataType [] variableName; dataType [] variableName = new dataType[ARRAY SIZE]; dataType [] variableName = {value0 , value2 , . . . , valuen1 }
The size of an array cannot be changed, we reference items in the array by using their indices. The indices range goes from 0 to N 1 where N is the size of the array. From looking at the array declarations it should be obvious that main takes as its argument an array of strings. The third array declaration is rarely used 85

since its only feasible for a very small number of items. Most of the time we need to know the arrays length and this is very easy to do with since the Array class instance variable length is not marked as public, this is what should always be used to nd an arrays size. To put an item into one of the arrays cells we use the command,

arrayName[index] = item;
. And if we need to get the value stored in a cell we do

storageVariable = arrayName[ind

7.1.1

IndexOutBounds Error

One frequent cause of errors is due to people trying to read or write past the bounds of an array. To see how this works if you look at the invocation of setInt its trying to put 5 in the 8th location instead of the 7th. int intArray [] = new int [7]; intArray . setInt (7 ,5) ; char [] searchTerm = new char [20]; for ( int i = 0; i <= 20; i ++) searchTerm [ i ] = char . parseChar ( args [ i ]) ; In the for loop we are taking the string passed to main and put each string into an array of chars called searchTerm. But we will get an out of bounds error.

7.1.2

Char Versus String Arrays

We know that a String is a list of characters, however a char array is not the String object. Whenever we declare a char array there are no methods included with it since chars are a primitive data type. On the other hand Strings have methods included for handling the data. String stringer = " Blondie was good , Fletcher was bad , & Hans was ugly . " ; char [] strung = stringer ; during the compilation Java will report that the types are incompatible.

7.2

Initializing arrays

I stated earlier that manually ling and array is impracticable and so we ll them with a loop. We have seen this being done for BarCharter.java. But CreatesArray.java only focuses on the creation and initialization of anArry so it should be easier to follow whats going on. 86

1 2 3 4 5 6 7 8 9 10 11 12 13

public class CreatesArray { public static final int ARRAY_SIZE = 10; // size of the array . public static void main ( String [] args ) int index = 0; float [] anArray = new float [ ARRAY_SIZE ]; { {

for ( index = 0; index < ARRAY_SIZE ; index ++)

anArray [ index ] = (( float ) index ) - 3.0 f /(( float ) index ) ; System . out . println ( " anArray [ " + index + " ] = " + anArray [ index ]) ; } } } Program 8.1: CreatesArray.java Note that instead of using a value for array size I set that in a constant. By using a constant for array size I can change the size of my array by only a value in one place. Whereas if I had not used the constant I would have to make at least two changes to my code. When the program is compiled and run we get results seen below. $ java CreatesArray anArray [0] = - Infinity anArray [1] = -2.0 anArray [2] = 0.5 anArray [3] = 2.0 anArray [4] = 3.25 anArray [5] = 4.4 anArray [6] = 5.5 anArray [7] = 6.571429 anArray [8] = 7.625 anArray [9] = 8.666667 $ One other thing to note from the output is that unlike languages such as C or Fortran which would give a segmentation fault when a division by zero takes place the Java interpreter evaluates the expression correctly as .

7.3

Array Operations

Some of the things that are frequently done with arrays; i Compare arrays for equality. 87

ii Set arrays equal to each other, iii Sorting the arrays items. iv Get the smallest value. v Get the largest value. vi Find the frequency at which an item occurs. vii Search for an item. viii Join two arrays together. ix Find out how many of the cells contain data. With procedural languages like C programmers tended to roll their own functions and libraries that did all these things. Fortunately since arrays are a type of object there are instance methods for handling these nine, typical, array operations. Javas array methods are in java.utils.Arrays. Though we should always use the Java standard libraries knowing how to do these nine operation can make you a more procient developer. In MyArray.java I have written a class denition that does operations 1 - 8. To do the last operation we would have to add two more variables to the class, one for keeping track of how many cells had been used and the total number of cells. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 /* * * @return the array */ 88 } /* * * @param args an arbitrary number of ints . ( */ public MyArray ( int ... args ) { this . array = args ; } /* * * */ public MyArray () { this . array = null ; Default constructor public class MyArray { private int [] array ; package arraise ;

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63

public int [] getArray () { return array ; } /* * * @param array the array to set as reference */ public void setArray ( int [] array ) { this . array = array ; } /* * * Find largest value in array . * @return max */ public int max () { int result = this . array [0]; for ( int i = 0; i < this . array . length ; i ++) { int next = i + 1; if ( result < this . array [ next ]) result = this . array [ next ]; } return result ; } /* * * Find smallest value in array . * @return min */ public int min () { int result = this . array [0]; for ( int i = 0; i < this . array . length ; i ++) if ( this . array [ i ] < this . array [ i ++]) result = this . array [ i ]; return result ; }

89

64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102

/* * * Copies contents of array . adjust it . * @param array . */ public void copy ( int [] array ) { int [] temp ; if ( isLengthEqual ( this . array , array ) == false ) { int newSize = g etSize Differ ence ( this . array , array ) ; temp = resizeArray ( this . array , newSize ) ; } for ( int i = 0; i < array . length ; i ++) temp [ i ] = array [ i ]; this . array = temp ; } /* * * Checks if the arrays contain the same things in order and the same size . * @param array * @return boolean */ public boolean isEqual ( int [] array ) { boolean result = false ; if ( isLengthEqual ( this . array , array ) == false ) return result ; else { for ( int i = 0; i < array . length ; i ++) { if ( this . array [ i ] != array [ i ] ) return result ; else result = true ; } } return result ; } If the array is the wrong size it will

90

103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143

/* * * Checks the frequency of x . * @param x * @return int */ public int frequency ( int x ) { int count = 0; for ( int i = 0; i < this . array . length ; i ++) if ( this . array [ i ] == x ) count ++ ; return count ; } /* * * Adds subarray to a MyArray . * @param subarray * @return int array */ public int [] add ( int [] subArray ) { int [] newArray = resizeArray ( this . array , subArray . length ) ; for ( int i = newArray . length ; i < subArray . length ; i ++) newArray [ i ] = subArray [ i - newArray . length ]; return newArray ; } /* * * Sorts in ascending order . */ public void sort () { int temp = 0; for ( int i = 0; i < this . array . length ; i ++) for ( int j = 1; j < this . array . length ; j ++) if ( this . array [ i ] > this . array [ j ]) { temp = this . array [ i ]; this . array [ i ] = this . array [ j ]; this . array [ j ] = temp ; }

91

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184

} /* * * Gets value stored at position . * @param position * @return int */ public int getValueAt ( int position ) { return this . array [ position ]; } /* * * Checks if x is in the array . * @param x * @return boolean */ public boolean search ( int x ) { boolean result = false ; for ( int i = 0; i < this . array . length ; i ++) if ( this . array [ i ] == x ) { result = true ; return result ; } return result ; } /* * * Tests if arrays are the same length * @param x * @param y * @return boolean */ private boolean isLengthEqual ( int [] x , int [] y ) { boolean result = false ; if ( x . length == y . length ) result = true ; return result ;

92

185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 }

} /* * * Finds difference between the lengths of arrays x and y . * @param x * @param y * @return int */ private int g etSize Differ ence ( int [] x , int [] y ) { return ( x . length - y . length ) ; } /* * * Will either return a larger or smaller array depending on the value of size . * @param array * @param size * @return int array . */ private int [] resizeArray ( int [] array , int size ) { int newSize = array . length + size ; int [] newArray = new int [ newSize ]; return newArray ; }

Program 8.2: MyArray.java

7.3.1

Comparing Arrays For Equality

Since arrays are objects they use pass by reference. And like all objects comparing using the == operator will just test to see if their references are the same. To test arrays for equality we will rst check if they are of the same size. And if they are then we need to make sure that they contain the same values in their cells in the same order. That is why isEqual looks at the contents of a MyArray object.

7.3.2

Copying Objects

As was stated in the previous chapter the assignment operator only copies the references of objects so to get a separate copy of an object we need to copy the contents to a temporary object and then assign the address of the temporary object to our target. It is essential that the primitive types be duplicated otherwise we will simply have copied references. 93

7.3.3

Methods With Variable Arguments

The method, add(Object a, Object b) takes two objects and returns a third. However there are many times when we want to add more than an arbitrary number of items, so we want a function that does the equivalent of a1 + a2 + + an . In Java this can be done by using the variable argument operator, . . . as seen in one of MyArrays constructors. The syntax of varag has when they are declared is,

subRoutineName(dataType. . . variableName)
Whenever varargs are mixed with xed args the vararg must be the subroutines last parameter otherwise the interpreter will think that all the parameters are varargs furthermore, there can be only one vararg per function. max uses varargs to nd the largest double in a series. public double max ( double ... args ) { double result = arg [0]; for ( int i = 1; i < args . length ; i ++) if ( arg [ i ] > result ) result = arg [ i ]; return result ;

Builtin Array Methods As was mentioned Java has a number of builtin functions that do all of the operations in MyArray, you should use the Java standard libraries instead of rolling your own. Javas array class is in java.util.Arrays.

7.4

Referencing Arrays

Since an array is a contiguous collection of memory addresses that all hold data of the same type we can refer to an array by its rst elements address display. String [] someStrings = new String [ ARRAY_SIZE ];

System . out . println ( strings ) ; So in the two preceding lines only the rst string in someStrings will be displayed on the console.

7.5

Passing Arguments To Main

Most applications that we use rely on a number of smaller programs. All these programs tend to share information with each other. So far we have used Scanner to pass input to a program which is not scalable. In reality programs get their input from the arguments passed to main. Doing this also makes our programs much easier to standardize by creating menus that we can easily port from one application to another. For an example of this look at Trigger.java. 94

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

public class Trigger { public static double SumOfSquares ( double num1 , double num2 ) { double result = Math . pow ( num1 , 2) + Math . pow ( num2 , 2) ; return result ; } public static void Display () { System . out . print ( " \ nTrigger . java displays trig ratios of a right " ) ; System . out . println ( " triangle . To use this program type :\ n " ) ; System . out . println ( " java Trigger < number1 > < number2 > < number3 > " ) ; System . out . println ( " \ nYou can see these help messages on this program " ) ; System . out . println ( " by entering one of the three commands below . " ) ; System . out . println ( " java Trigger -h " ) ; System . out . println ( " java Trigger -- help " ) ; System . out . println ( " java Trigger \ n " ) ; System . exit (13) ; } public static double GetMax ( double x , double y , double z ) { double maximum = 0; if (( x > y ) & ( x > z ) ) maximum = x ; if (( y > x ) & ( y > z ) ) maximum = y ; if (( z > x ) & ( z > y ) ) maximum = z ; return maximum ; } public static boolean PythagoreanCheck ( double max , double a , double b ) 95

{ 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 double angleTheta = 0; double angleGamma = 0; double opposite = 0; double adjacent = 0; double hypotenuse = 0; public static void main ( String [] args ) { double side1 = 0; double side2 = 0; double side3 = 0; } public static double GetGamma ( double theta ) { return (180.0 - (90.0 + theta ) ) ; } public static double GetArcTangent ( double tangent ) { return ( Math . atan ( tangent ) * 180 / Math . PI ) ; } public static double GetTangent ( double opposite , double adjacent ) { return ( opposite / adjacent ) ; } public static double GetSine ( double opposite , double hypotenuse ) { return ( opposite / hypotenuse ) ; } public static double GetCosine ( double adjacent , double hypotenuse ) { return ( adjacent / hypotenuse ) ; } if ( Math . pow ( max , 2) == result ) answer = true ; return answer ; boolean answer = false ; double result = SumOfSquares ( a , b ) ;

96

79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119

double cosineOfTheta = 0; double sineOfTheta = 0; double tangentOfTheta = 0; boolean isRightTriangle = false ; switch ( args . length ) { case 0: Display () ; break ; case 1: if ( args [0]. equals ( " -h " ) || args [0]. equals ( " -- help " ) ) Display () ; else { System . out . println ( " Invalid option " ) ; System . exit (34) ;} break ; case 3: try { side1 = Double . parseDouble ( args [0]) ; side2 = Double . parseDouble ( args [1]) ; side3 = Double . parseDouble ( args [2]) ; } catch ( N u m b e r F o r m a t E x c e p t i o n e ) { System . out . println ( " Argument was not a number . " ) ; System . exit (7) ; } break ; default : System . out . println ( " Invalid number of arguments . " ) ; System . exit (3) ; break ; } if ( side1 == 0 || side2 == 0 || side3 == 0) { System . out . println ( " One of the sides is zero . " ) ; System . exit (4) ; }

97

120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 System . out . printf ( " For the right angled triangle with sides of length " ) ; System . out . printf ( " %.2 f , %.2 f , & %.2 f " , hypotenuse , opposite , adjacent ) ; System . out . printf ( " \ n Sine (%.2 f ) = %.2 f " , angleTheta , sineOfTheta ) } } else { System . out . println ( " Not lengths of a right angled triangle . " ) ; System . exit (9) ; angleTheta = GetArcTangent ( tangentOfTheta ) ; angleGamma = GetGamma ( angleTheta ) ; if ( isRightTriangle == true ) { cosineOfTheta = GetCosine ( adjacent , hypotenuse ) ; sineOfTheta = GetSine ( opposite , hypotenuse ) ; tangentOfTheta = GetTangent ( opposite , adjacent ) ; isRightTriangle = PythagoreanCheck ( hypotenuse , opposite , adjacent ) ; } else { hypotenuse = side3 ; opposite = side1 ; adjacent = side2 ; } } else if ( GetMax ( side1 , side2 , side3 ) == side2 ) { hypotenuse = side2 ; opposite = side1 ; adjacent = side3 ; if ( GetMax ( side1 , side2 , side3 ) == side1 ) { hypotenuse = side1 ; opposite = side2 ; adjacent = side3 ;

98

; 158 159 160 161 162 163 164 } Program 8.3: Trigger.java You can see that there is a help menu and the user simply passes the arguments on the command line as seen below. $ java Trigger Trigger . java displays trig ratios of a right triangle . program type : java Trigger < number1 > < number2 > < number3 > You can see these help messages on this program by entering one of the three commands below . java Trigger -h java Trigger -- help java Trigger saleh : bin $ java Trigger 5 6 7 Not lengths of a right angled triangle . $ By using the command line I have made my Trigger.java more versatile since now it can be piped input from another program. To use this } System . out . printf ( " \ n Cosine (%.2 f ) = %.2 f " , angleTheta , cosineOfTheta ) ; System . out . printf ( " \ n Tangent (%.2 f ) = %.2 f " , angleTheta , tangentOfTheta ) ; System . out . printf ( " \ nAnd the third angle is " ) ; System . out . printf ( " %.2 f degrees .\ n " , angleGamma ) ;

7.6

Enumerated Types

Sometimes we want to have lists of a type of item. For example look at the menu for Best Little Jolo House In Texas, Since there are six diering rice dishes at the restaurant customers are likely to say Give me a 4.when they want gumbo. For situations like this one where a list of items is associated with numbers (enumerated) we can use the enum type, the syntax for an enum is,

enum identier { IT EM1 , IT EM T2 , . . . , IT EMn }


99

Please note that all the items are in caps. Table 7.2: Best Little Jolo Rice House In Texas Menu Menu 1. 2. 3. 4. 5. 6. Jolo Rice Tuwo Fried Rice Rice With Pepper Sauce Shrimp Gumbo Curry 6.50 8.50 6.50 5.50 8.50 6.50

Therefore to create an enum for The Best Little Jolo Rice House In Texas, enum riceDishes JOLOFF, TUWO, FRIED, PLAIN, GUMBO, CURRY;. If we had used enum in ConvertsNumberToMonth.java the code would be simpler and cleaner. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 System . out . print ( aMonth . toString () + " is the time for rabbits and grass " ) ; 100 try { arg = Integer . parseInt ( args [0]) ; } catch ( N u m b e r F o r m a t E x c e p t i o n e ) { System . out . println ( " Argument was not a number . " ) ; System . exit (7) ; } if ( ( arg > 12) | ( arg < 1) ) { System . out . printf ( " % d is out of range \ n " , arg ) ; System . exit (12) ; } else System . out . println ( " Month is " + month [ arg ] + " .\ n " ) ; public static void main ( String [] args ) { Month aMonth = Month . MAR ; Month [] month = Month . values () ; int arg = 0; public class NumberToMonth { enum Month { JAN , FEB , MAR , APR , MAY , JUN , JUL , AUG , SEP , OCT , NOV , DEC };

22 23 24 } }

System . out . println ( " cutters to go mad . " ) ;

Program 8.4: NumberToMonth.java We can intuitively dene enums as an array of constants, however this is more to help us understand what they are like. Enums are a type of object and their only similarity to constants, which are a type of primitive, is that we cannot change the values in an enum. Also like constants enums come right after the class names declaration and are not part of any function body. $ java NumberToMonth 5 Month is JUN . MAR is the time for rabbits and grass cutters to go mad . $ As can be seen from NumberToMonth.javas output enums have a method called values which builds an array from the enum lists contents. Also ordinal tells us where an item is in enum. You can also see that to assign a value to an instance of enum the syntax is,

EnumInstance variableName = EnumInstance.VALUE

7.7

Multidimensional Arrays

There are situations where we wan to use multidimensional arrays. For example we have a table of pH versus molarity of a solution. The syntax to make a multidimensional array is,

dataType[][]. . . [] identier = new dataType[][]. . . []


So for a 3x3 array of boolean where each array is a diering size, boolean[][][] boolArray = new boolean [3][3][3];. For a two dimensional int array, int[][] intArray = new int[5][7];. It should be obvious that we need nested for loops to access the individual cells. Imagine that we want to make a board for chess or draughts. then we start with building an 8x8 array, char board [][] = new char[8][8]; If we want to see whats in B-5 . . . piece = board[1][4]. And to ll our board we put the 32 tokens in either the rst or last 16 slots depending on their colour. public void setPieces ( int startingRow ) { int column = 0; int row = 0; // Fill the bottom from the 6 th row , avoids writing two separate nested loops . if ( startingRow == 7) 101

row = 6; for ( row ; row < board [( stratingRow + 1) ][ column ]; row ++ ) { for ( coulmn ; column < board [ row ]. lengthlength ; column ++) board [ row ][ column ] = player . selector ( getPiece () ) ; } } You might have noticed that in a multidimensional array the individual array lengths are independent of each other so we can have what are called ragged arrays. Ragged arrays can be useful for developers but great care must be taken in implementing them since dealing with variable rows and columns is more complicated than with xed quaremultidimensional arrays. s

zr

102

Chapter 8

Inheritance
Inheritance is the process by which a class is derived from a base class. When the derived class is made it inherits the parents instance variables and methods. For an example of inheritance take a look at Vector which inherits methods and data from Point 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public Point getCoordinate () { return coordinate ; 103 } public void setCoordinate ( Point p ) { coordinate = p ; } public Vector ( Point p ) { coordinate = p ; } public Vector ( double x , double y , double z ) { super (x , y , z ) ; } public Vector () { this (0.0 , 0.0 , 0.0) ; public class Vector extends Point { private Point coordinate ; package src ; import java . lang . Math ;

26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

} public Vector add ( Vector a ) { Vector result = null ; double i = this . getX () + a . getX () ; double j = this . getY () + a . getY () ; double k = this . getZ () + a . getZ () ; result = new Vector (i , j , k ) ; return result ; } public double dotProduct ( Vector a ) { double i = this . getX () * a . getX () ; double j = this . getY () * a . getY () ; double k = this . getZ () * a . getZ () ; return ( i + j + k ) ; } public double magnitude () { double sumOfSquares = Math . pow ( this . getX () , 2) + Math . pow ( this . getY () , 2) ; sumOfSquares += Math . pow ( this . getZ () , 2) ; double result = Math . sqrt ( sumOfSquares ) ; return result ; } public Vector crossProduct ( Vector a ) { double i = ( this . getY () * a . getZ () ) - ( this . getZ () * a . getY () ) ; double j = ( this . getZ () * a . getX () ) - ( this . getX () * a . getZ () ) ; double k = ( this . getX () * a . getY () ) - ( this . getY () * a . getX () ) ; return ( new Vector (i , j , k ) ) ; } public double sine () { return ( this . getY () / this . magnitude () ) ; }

104

66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106

public double cosine () { return ( this . getX () / this . magnitude () ) ; } public double tangent () { return ( this . getX () / this . getY () ) ; } public double arcTan ( double tangent ) { return ( Math . atan ( tangent ) ) ; } public double arcSine ( double sine ) { return ( Math . asin ( sine ) ) ; } public double arcCosine ( double cosine ) { return ( Math . acos ( cosine ) ) ; } public boolean isParallel ( Vector a ) { boolean answer = false ; if ( this . dotProduct ( a ) == ( this . magnitude () * a . magnitude () ) ) answer = true ; return answer ; } public boolean isPerpendicular ( Vector a ) { boolean answer = false ; if ( this . dotProduct ( a ) == 0) answer = true ; return answer ; } public boolean equals ( Object anObject ) { boolean answer = false ; if ( getClass () != anObject . getClass () )

105

107 108 109 110 111 112 113 114 115 116 117 118 } } }

return answer ; else { Vector a = ( Vector ) anObject ; if ( this . getX () == a . getX () ) if ( this . getY () == a . getY () ) answer = true ; return answer ;

Program 9.1: Vector.java

You can see that Vector inherits data and methods from Point then it extends them. On the other hand VectorCalc is an implementation of Vector that adds two vectors together. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 double scalar = b . dotProduct ( a ) ; 106 System . out . printf ( " Vector % s has magnitude of a : %.2 f .\ n " , a . toString () , a . magnitude () ) ; System . out . printf ( " Vector % s has magnitude of b : %.2 f .\ n " , b . toString () , b . magnitude () ) ; System . out . printf ( " Cross product of % s & % s is % s " , a . toString () , b . toString () , result . toString () ) ; Vector result = a . crossProduct ( b ) ; Point p = new Point (4.34 , 6 , 0.87) ; Point p2 = new Point (3 , 6 , 7) ; String pachydermia = " Some elephants are gray and wrinkly , others were wooly and massive " ; public static void main ( String [] args ) Vector a = new Vector (6 , -2 , -1) ; Vector b = new Vector (2 , 5 , 2) ; { public class VectorCalc extends Vector { package src ; import javax . swing . JOptionPane ;

21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

System . out . printf ( " Dot Product of % s and % s is %.3 f .\ n " , a . toString () , b . toString () , scalar ) ; result = a . add ( a ) ; System . out . println ( " sum of " + a . toString () + " & " + b . toString () + " : " + result ) ;

if ( a . equals ( pachydermia ) == false ) System . out . println ( a . getClass () + " and " + pachydermia . getClass () + " are not the same . " ) ; else System . out . println ( a . toString () + " and " + pachydermia + " are the same . " ) ; if ( a . equals ( p2 ) == false ) System . out . println ( a . toString () + " and " + are not the same " ) ; else { System . out . println ( a . toString () + " and " + are the same " ) ; System . out . println ( a . getClass () + " and " + p2 . getClass () + " were the classes compared . " ) ; } if ( p instanceof Vector ) System . out . println ( " Points and vectors are the same class . " ) ; else System . out . println ( " Points and vectors are not the same class " ); if ( a . isParallel ( result ) == true ) System . out . println ( a . toString () + " & " + result . toString () + " are parallel . " ) ; else System . out . println ( a . toString () + " & " + result . toString () + " are not parallel . " ) ; if ( a . isPerpendicular ( b ) == true ) System . out . println ( a . toString () + " & " + b . toString () + " are perpendicular . " ) ; else p2 . toString () + " p2 . toString () + "

107

51 52 53 54 } }

System . out . println ( a . toString () + " & " + b . toString () + " are not perpendicular . " ) ; JOptionPane . show Messag eDialo g ( null , a . toString () + " & " + b . toString () + " are not perpendicular . " ) ;

Program 9.2: VectorCalc.java To mark a class as derived from another we need to put the following line at the beginning of the class declaration.

SubClass extends SuperClass {

Subclass body

The subclass has access to the same data types and methods that are in the parent so we do not need to recreate those. Because of this inheritance is one of the simplest ways to reuse code eciently. In Figure 8.1 it will be seen that the super class of atomic particles has a subclass of composite particles. Furthermore, even though Fermions can have only one super class as its parent it can have multiple subclasses (protons and neutrons to name a few) as its children.

108

8.1

Properties Of Subclasses

Subclasses, which are also called child, or derived classes, have a number of properties that we will spend most of this chapter discussing. The characteristics are; i They can only have one parent. Unlike C++ where there is multiple inheritance Java derived classes can only get their instance variables and methods from one super class. ii A super class constructors cannot be inherited but they can be invoked from a subclass constructor with the keyword super. iii A derived class does not have to implement all the instance methods in the super class. We only need to create instance variables specic to the child class. iv A child class can redene the implementation of a super class instance methods, this is called overriding.

8.2

Invoking Super Class Constructors

We know that constructors initialize an objects instance variables, so we can use the parents constructor to set the values of inherited variables. Whenever a subclass is created it either implicitly invokes the super constructor as is seen in the Squares default constructor. Or explicitly like what we see in the class second constructor. public class Square extends Quadrilateral { private double length ; public Square () { length = 0; } public Square ( double length ) { super ( length , length , length , length ) ; } In the second constructor the super class constructor is explicitly invoked and given the length of all the sides.

8.2.1

Reference Constructors

it might have been noticed that when we overload Constructors a great deal of the code is the same. To cut down on typing duplicate code many developers pass one constructors arguments to another. When this is done the Constructor that all the others invoke is called a reference constructor. The overloaded constructors call the reference one by using the this operator as seen in the code fragment for MyArray public MyArray () { this ( null ) ; 109

} public MyArray ( int [] a ) { this ( a ) ; } public MyArray ( int ... a ) { size = a . length ; array = a ; } When the number of options that can be used to create object is greater than three you should either us a Parameter or Builder class. However those two methods of dealing with classes with multiple constructor arguments are beyond the scope of this chapter.

8.2.2

Protected Instance Variables

One of the reasons why we need to invoke the superclass constructor is that we have to instantiate variables that are marked private. Since they are marked private no object can directly access them. We know that if the instance variables are marked public any object that uses the class can modify their properties, furthermore this can cause problems in learning what the variables state is. However there are times when we want child objects to directly access their parents instance variables. For such cases we use the protected modier. Consider that for 8 8 board games will have a declaration, public class Board { int dimension ; int [][] board ; Since under this class we have Chess, Checkers & other games if we have an instance of the Chess which has its own children, Rules, Pieces, etc, that all need to access the board we might nd it easier to make the array board protected. However using protected can make your program more complicated to debug since the superclass instance variables can be modied by its children. Furthermore, if the parent class variables are private then any changes that are made to the super class will not aect the children. So another problem associated with protected variables is more code reviews. An alternative to marking variables as protected is to make them static. With static there is one instance of the variable that is available to each object of the class.

8.3

Invoking A Superclass Methods

Consider an instance of the Proton class whose ancestor is CompositeParticles and its parent is Hadron. We use the following syntax to invoke a super class method. 110

super.methodName(arguments);
So if we want to invoke Hadrons getFieldDirection method we would do the following; Proton aProton = new Proton () ; aProton . fieldDirection = super . g etFiel dDirec tion () ; From this it can be seen that we can only directly invoke the parents methods and not its ancestors. Another example of using the parents method directly is seen in Force. Force directly invokes Vectors methods of calculating its x & y components on its method totalForce 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 } Program 9.3: Force.java } public Force ( double mass , double radians , Vector friction , Vector acceleration ) { this . mass = mass ; this . radians = radians ; this . friction = friction ; this . acceleration = acceleration ; } public Force () { this (0 , 0 , null , null ) ; public static final double GRAVITY = 9.8; public class Force extends Vector { private double mass ; private double radians ; private Vector friction ; private Vector acceleration ; package src ;

8.3.1

Overriding Methods

When a derived class changes the implementation of one of its parents methods that is called overriding. When we wrote our toString methods we were actually overriding toString that is in the Object class. An overriden methods scope only exists int he child not the parent. And it must have the same function prototype as its parents namesaked function. If you look at gure 7.2 you will see that all the subclasses posses methods with the same names. 111

Restrictions On Overriden Methods There are two main restrictions that can be placed on overriden functions. The rst deals with their return type, the second concerns access permissions. Since derived classes are still instances of their base class we can change the return type to a specic object than the parent. As for access permissions a derived class methods can always be made less restrictive than its parents but never more restrictive. Parents Access Modier public protected private Childs Access Modiers public public, protected private, protected, public

Table 8.1: Allowed Child Class Access Modiers So we can make make have the prototype public MyArray clone() or public Object clone(). But we cannot have private int hashCode().

112

If we do not place any access modiers on an instance variable or method then Java gives it the default access permissions to package. When a method or indentier has package access that means that all the classes within its package can access it. So imagine that we have the two classes Bulletphysics and CalculateWindVelocty are both in the default Eclipse package src and we do not use any the access modiers private, public, or protected on their methods or identiers, then its possible for both classes to call each others methods and access each others data directly. Its not a good idea to use the default access modier. Overriding Versus Overloading Overloaded methods can have a diering number of parameters, order of parameters, and completely differing return types. On the other hand overriden functions must have the same class of return type and parameters, as well as the same number of parameters. From this you can tell that all of our implementations of toString have been overrides. Whereas we have been using function prototypes of the form boolean equals(ObjectName, obj) in the Java API equals is supposed to have the prototype boolean equals(Object obj).So you can seen that we have been overloading the equals subroutine. Using GetClass Versus Instanceof For Comparisons You might have noticed that Vectors equals uses getClass from the Object class. This method will return true if the two classes are the same. Since children are instances of their parent class getClass will always return true. In VectorCalc.java we not only use getClass indirectly via Vectors equals method but also directly compare two objects using the instanceof keyword to compare a and p. You will notice that when instanceof is used then the result is false. Magnitude of a : 9.695 359714 832659 Magnitude of b : 5.830 951894 845301 Cross Product : (30.0 , 6.0 , -18.0) Dot Product : 44.0 sum of (3.0 , 6.0 , 7.0) & (3.0 , 0.0 , 5.0) : (6.0 , 12.0 , 14.0) class src . Vector and class java . lang . String are not the same . (3.0 , 6.0 , 7.0) and (3.0 , 6.0 , 7.0) are the same class src . Vector and class src . Point were the classes compared . Points and vectors are not the same class (3.0 , 6.0 , 7.0) & (4.34 , 6.0 , 0.87) are not parallel . (3.0 , 6.0 , 7.0) & (4.34 , 6.0 , 0.87) are not perpendicular . If you use instanceof then it might break some things in the logic and tried the following it will not work correctly given that a Force object is also a Vector and Charge derived from Force. It would be better for us to typecast to make sure that children can use their parents methods and data without any problems. Force torque = new Force ( acceleration , mass ) ;

Charge source = New Charge ( current , time ) ; 113

if ( Charge instanceof Force ) source . super . equals ( otherCharge ) ; There are good reasons to use instanceof but you need to exercise caution when using it.

8.4

The Final Modier And Its Eects

Final prevents whatever its associated with from being modied. This means that radius in the following statement cannot have its value changed. final double radius = 36.859; Now that you have seen it you know why constants must always have nal in their declaration, also using static with an identier assures that there will only be one instance of that variable to all of th objects.

8.4.1

Final Methods

If a subroutine is marked nal in a class then none of the descendant classes can override the nalized subroutine. An example of a nal method is in the code fragment below. class Ballot { . . . . . final Candidate getVote ( String office ) { return ( g et s C an d i da t e Pi c k ed ( s e l e c t C o n t e n d e r s A r r a y ( office ) ) ) ; } . . . . . As you probably guessed getVote cannot be overriden. Any of Ballots derived classes have to use getVote as is. One important use of nal subroutines is when constructors invoke subroutines all the functions invoked by the constructor should be marked nal so that a child class does not accidentally change the implementation of its parents constructor.

8.4.2
from it.

Final Classes

We can also mark a class as nal. When we do this that means that the no other children can be made

8.5

Eects of The Static Modier

Now that we have examined the impact that static has on identiers and functions in a class. Right now we will look at what eect the keywods static and have on inheritance. We will also discuss importing static members in your Java code. 114

8.5.1

Static Methods Cannot Be Inherited

As you know a function marked static cannot access data outside its class so whenever static is associated with a procedure the class that the procedure belongs to cannot be inherited. This is why we cannot create child classes whenever our base class has a main method.

8.5.2

Static Imports

You have seen that whenever we need to use a print method or items in java.lang.Math.java we have to add the package to the identier i.e. area = Math.pow(radius, 2)* Math.PI, or System.out.println(Ive been downcast so damn long that runtime errors are likely. I say Ive been downcast for so long that I need to be upcast the hierarchy tree.). The reason why we have to do is that these classes are static so when we use them we must state the full path to their methods, constants and variables. However this can sometimes create a lot of typing, to cut down on that we can explicitly import the package with a statement in the format

import static name.of.static.package;


So to statically import println I would have the import static java.lang.System.out; at the top of my program. You can see two examples of static imports being used in BadPractice.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 } Program 9.3: BadExample.java } out . printf ( " The circumfrence of the circle with radius %.2 f " , radius ) ; out . printf ( " is %.2 f .\ n " , circumfrence ) ; circumfrence = 2 * radius * PI ; public static void main ( String [] args ) { double radius = 12; double circumfrence = 0; public class BadExample { import static java . lang . Math .*; import static java . lang . System . out ;

Use Static Imports Sparingly I called the last program BadPractice because the Java documentation put out by Sun says that static imports should be used sparingly. Liberal use of static imports is frowned upon because it can cause 115

problems with inheritance. Also its important for the JVM to know what classes the static data or method comes from so that any constraints on their behaviour or access can be followed properly. To nd out more see http://download.oracle.com/javase/1,5.0/docs/guide/language/static-import.html

8.6

Accessors That Return Objects

We have already seen that elds in an object are generally marked private and we get the value stored in a eld with an accessor. Given that consider the following class. 1 2 3 } public class SuperClass { private

116

Chapter 9

Polymorphism
Consider the set of objects that make up the class of sea creatures. All the sea creatures do the following things. Reproduce Eat Defend themselves Excrete wastes Communicate Sense Move Grow Repair themselves Breathe

The only sea creature that do not move around are xed plants like some of the kelp and seaweed. Although they all can perform the tasks listed above the way each type of sea creature does its thing will be dierent. To defend itself a crab will hide in its shell, a jelly sh will use its stingers, Although tuna and blue whales swim in schools to protect themselves the tuna scatter in dierent directions to confuse predators while blue whales will form a defense cordon and try and drive the attacker away with headbutts. To move from point A to B a crab crawls on the sea oor, whales and tuna swim, while a jellysh will simply drift on the oceans currents. All this implies that if we were going to create a java simulation of all the sea creatures they would be in the superclass SeaCreature which would have the instance methods move, reproduce, defend, eat as well some others corresponding to the other tasks that were listed above. However the implementation of each method will dier based on the type of SeaCreature, and some subclasses such as as RootedPlants will not have any implementation of move. This property of each methods implementation diering based on the subclass is polymorphism. There are a number of dierent ways that polymorphism is achieved in Java, one of the them overriding has already been discussed in this chapter we shall look at three other ways of making a group of classes polymorphic. The three emthods we are going to discuss are:

117

Upcasting/Downcasting Abstract Classes

Interfaces Inner Classes

What we want to achieve with polymorphism is that whenever an object invokes a method its subclasses use its implementation of the called method and not some other class. To illustrate this if you could tell a person,a dog, a komodo dragon, and cat all to speak they would all the animals would make diering sounds. With polymorphism we are trying to have the same eect.

9.1

Method Binding In Java

There are two times when the Java Virtual Machine can decide which implementation of move it should invoke for a SeaCreature object. This can be done either at compile time or at runtime. Which ever method it uses a specic method will be bound to an object. Now we shall discuss the two binding methods.

9.1.1

Early Binding

In early binding the class and the correct method for each class instance is determined at compile time. Generally when you use overloading or are using a compiled language early binding is done. Sometimes this is called static binding. Java only uses early binding for methods that have been marked either static or nal.

9.1.2

Late Binding

If an objects immediate class and the version of the method that it calls is determined at runtime then late binding is taking place. Most interpreted languages use late binding. A synonym for late binding is dynamic binding. Though most Java developers will state that that JAva uses late binding to be exact what is going on is something OOP researchers call type introspection. IN Java dynamic binding is used for all nonstatci, nonnal classes and methods. Since dynamic binding is used in Java let us consider what happens when PacicSwimmers.java is run. 1 2 3 4 5 6 7 8 9 10 11 12 Whale mobyDick = new Whale ( " Moby - Dick " ) ; Krill krillGruppe = new Krill ( " Krill Group " , numOfKrill ) ; 118 int numOfKrill = 200000; public static void main ( String [] args ) { double speed = 0.0; double dir ec ti on In De gr ee s = 0.0; public class PacificSwimmers { package ocean ;

13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 } Program 10.1: PacicSwimmers.java Now at runtime the JVM knows that both mobyDick andkrillGruppe are SeaCreature objects, it nds this information out at lines 9 & 10. However it does not decide which implementation of move is the right one for mobyDick or krillGruppe until lines 16, 20, & 25. This mechanism of late binding of a function to a class by the JVM is the basis of polymorphism in Java. Now that you understand what polymorphism is in Java we can spend the rest of the chapter looking rstly 119 } System . out . print ( " Captain Ahab s status is " ) ; System . out . println ( ahab . getStatus () + " . " ) ; System . out . print ( " Moby - Dick s status is " ) ; System . out . println ( mobyDick . getStatus () + " . " ) ; System . out . print ( " krill Group s status is " ) ; System . out . println ( krillGruppe . getStatus () + " . " ) ; if ( ahab . getDamage () >= 0.5) ahab . setStatus ( " dead " ) ; mobyDick . attack ( ahab , attackTime ) ; ahab . defend ( attackTime ) ; Time attackTime = new Time (60) ; Person ahab = new Person ( " Captain Ahab " ) ; ahab . move (1.0 , 300) ; System . out . print ( " Captain Ahab is " + ahab . getStatus () ) ; mobyDick . eat ( krillGruppen ) ; speed = 0.3; di re ct io nI nD eg re es = 270.0; krillGruppe . move ( speed , d ir ec ti on InD eg re es ) ; speed = 10.0; di re ct io nI nD eg re es = 90.0; mobyDick . move ( speed , d ir ec tio nI nD eg re es ) ;

at the eects that late binding have on the super and sub classes, this will be the main focus of the sections covering upcasting and downcasting. After that we shall look at how the four polymorphism techniques can be used to improve software design.

9.2

Upcasting Versus Downcasting

Instance methods can be invoked either down the class hierarchy or up the class hierarchy. One invocation method is called upcasting while the other is downcasting. In both types of cast what is going on is that we are referencing an objects address. Either the subclass is referencing a superclass instance or a superclass instance is referencing a subclass object.

9.2.1

Upcasting

Here a superclass object is is assigned to a subclass instance, then it uses the subclass procedures. Since derived classes are a subset of the base class they will have all the instance elds and functions of the base class and the upcasting can be done implicitly. The ways you can do an upcast are as follows;

BaseClass instanceOfBaseClass = instanceOfDerivedClass; instanceOfBaseClass = instanceOfDerivedClass; instanceOfBaseClass = (BaseClass) instanceOfDerivedClass;


We can see upcasting being done in Piecer.java piece

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

package game . piece ; public class Piecer { public static void main ( String [] args ) { CheckerPiece redChecker = new CheckerPiece () ; Piece aPiece ; aGamePiece = ( Piece ) redChecker ; int column = 5; int row = 3; aPiece . move ( aPiece . g et Cu rr en tP os it io n () , aPiece . getNextPosition ( column , row ) ) ; } 120

16

} Program 10.2: Piecer.java redChecker is upcast to aPiece on line 9. and then on line 14 aPiece uses CheckerPieces instance methods getCurrentPosition, getNextPosition, & cnamemove instead of GamePieces instance methods. To get a better idea of upcastings impact we create a group of classes dealing with clothing sizes, GarmentSize, TrouserSize and ShowsUpCasting.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33

package clothing ; enum Gender { MALE , FEMALE , NEUTER } public class GarmentSize { private Gender aGender ; private String ageGroup ; private String size ; private int age ; public GarmentSize () { this ( null , null , null , 0) ; } public GarmentSize ( Gender aGender , String size , int age ) { this ( aGender , null , size , age ) ; this . ageGroup = ageToAgeGroup ( age ) ; } public GarmentSize ( Gender aGender , String ageGroup , String size ) { this ( aGender , ageGroup , size , 0) ; } public GarmentSize ( Gender aGender , String ageGroup , String size , int age ) { super () ; this . aGender = aGender ; this . ageGroup = ageGroup ; this . size = size ; this . age = age ; }

121

34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74

public Gender getaGender () { return aGender ; } public void setaGender ( Gender aGender ) { this . aGender = aGender ; } public String getAgeGroup () { String answer = ageGroup ; return } public String ageToAgeGroup ( int age ) { if (( age >= 0) && ( age <= 1) ) ageGroup = " baby " ; else if (( age >= 2) && ( age <= 5) ) ageGroup = " toddler " ; else if (( age >=6) && ( age <= 12 ) ) ageGroup = " preteen " ; else if (( age >= 13) && ( age <= 19) ) ageGroup = " teenager " ; else if ( age > 20 ) ageGroup = " adult " ; else ageGroup = " undetermined " ; return ageGroup ; } public void setAgeGroup ( String ageGroup ) { if (! checkAgeGroup ( ageGroup ) ) h a n d l e s I n c o r r e c t E n t r y ( " ageGroup " ) ; else this . ageGroup = ageGroup ; } public String getSize () { String answer = size ; return answer ; answer ;

122

75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112

} public void setSize ( String size ) { if (( this instanceof GarmentSize ) && ( this . getClass () . getName () . equals ( " clothing . GarmentSize " ) ) ) { if (! checkSize ( size ) ) h a n d l e s I n c o r r e c t E n t r y ( " size " ) ; } else this . size = size ; } public int getAge () { int answer = age ; return answer ; } public void setAge ( int age ) { if ( age < 0) h a n d l e s I n c o r r e c t E n t r y ( " age " ) ; else this . age = age ; } public String toString () { return " [ gender = " + aGender + " , age group = " + ageGroup + " , size = " + size + " ] " ; } public boolean checkAgeGroup ( String aString ) { String [] ageGroups = { " baby " , " toddler " , " preteen " , " teenager " , " adult " , " undetermined " }; return checksForMatch ( aString , ageGroups ) ; } public boolean checkSize ( String aString ) { String [] sizes = { " XS " , " S " , " M " , " L " , " XL " , " XXL " }; return checksForMatch ( aString , sizes ) ; }

123

113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 } Program 10.3: GarmentSize.java Below you can see TrouserSize which is derived from GarmentSize. 1 2 3 4 5 6 7 8 9 10 11 public TrouserSize ( Gender aGender , String ageGroup , int waist , int 124 } public TrouserSize () { this ( null , null , 0 , 0) ; public class TrouserSize extends GarmentSize { private int waist ; private int inSeam ; package clothing ; } System . exit (57) ; if ( fieldName . equals ( " age " ) ) System . out . println ( " Valid ages are greater than or equal to zero . " ) ; if ( fieldName . equals ( " size " ) ) System . out . print ( " Valid sizes are : XS , S , M , L , XL , and XXL " ) ; } protected void h a n d l e s I n c o r r e c t E n t r y ( String fieldName ) { if ( fieldName . equals ( " ageGroup " ) ) { System . out . print ( " Valid age groups are : baby , toddler , preteen "); System . out . println ( " , teenage , adult , and undetermined . " ) ; } private boolean checksForMatch ( String toMatch , String [] stringArray ) { for ( int i = 0; i < stringArray . length ; i ++) if ( toMatch . equalsIgnoreCase ( stringArray [ i ]) ) return true ; return false ;

inSeam ) { 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 else { System . out . println ( this . getClass () . getName () + " is not a pair of trousers . " ) ; else if ( ( this instanceof TrouserSize ) && ( checkSize ( size ) == true ) ) super . setSize ( size ) ; public void setSize ( String size ) { if ( ( this instanceof TrouserSize ) && ( checkSize ( size ) == false ) ) super . setSize ( " Unk " ) ; } public void setInSeam ( int inSeam ) { this . inSeam = inSeam ; } public int getInSeam () { return inSeam ; } public void setWaist ( int waist ) { this . waist = waist ; } public int getWaist () { return waist ; } } public TrouserSize ( Gender aGender , String ageGroup , String size ) { super ( aGender , ageGroup , null , 0) ; this . setSize ( size ) ; this . waist = getWaistFromSize ( size ) ; this . inSeam = ge tInSea mFromS ize ( size ) ; super ( aGender , ageGroup , null , 0) ; this . waist = waist ; this . inSeam = inSeam ; this . setSize ( intsToSizeString () ) ;

125

50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 } } } } } } }

System . exit (25) ; }

public String toString () { return " [ waist = " + waist + " , inseam = " + inSeam + " , gender = " + getaGender () + " ,, age group = " + getAgeGroup () + " ] " ;

@Override public boolean checkSize ( String aString ) { String middleLetter = " x " ; return ( middleLetter . regionMatches (0 , aString , 2 , 1) ) ;

private int getWaistFromSize ( String size ) { int waist = 0; if ( checkSize ( size ) ) waist = Integer . parseInt ( size . substring (0 , 1) ) ; return waist ;

private int g etInSe amFrom Size ( String size ) { int inSeam = 0; if ( checkSize ( size ) ) inSeam = Integer . parseInt ( size . substring (3 , 4) ) ; return inSeam ;

private String intsToSizeString () { String size = waist + " x " + inSeam ; return size ;

Program 10.4: TrouserSize.java 126

After creating those two classes we use ShowsUpcasting to look at what happens when an instance of TrouserSize is upcast to a GarmentSize object. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 addsPanelItems ( leftPanel , clothing ) ; addsPanelItems ( rightPanel , moreClothing ) ; addsPanelItems ( centerPanel , myDockers ) ; 127 GarmentSize clothing = new GarmentSize ( Gender . FEMALE , " teen " , " m " ) ; GarmentSize moreClothing = plaidPants ; TrouserSize plaidPants = new TrouserSize ( Gender . MALE , " adult " , 34 , 30) ; TrouserSize myDockers = new TrouserSize ( Gender . FEMALE , " preteen " , " 12 x10 " ) ; JPanel rightPanel = new JPanel ( new GridLayout (4 , 1) ) ; framer . add ( rightPanel ) ; JPanel centerPanel = new JPanel ( new GridLayout (4 , 1) ) ; framer . add ( centerPanel ) ; JPanel leftPanel = new JPanel ( new GridLayout (4 , 1) ) ; framer . add ( leftPanel ) ; public static void main ( String [] args ) { JFrame framer = new JFrame ( " Garment Size Informer " ) ; framer . s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . EXIT_ON_CLOSE ) ; framer . setLayout ( new GridLayout (1 , 3) ) ; framer . setSize (600 , 600) ; framer . setVisible ( true ) ; public class ShowsUpcasting { import javax . swing . JPanel ; import javax . swing . JFrame ; import javax . swing . JLabel ; import javax . swing . JTextField ; import java . awt . GridLayout ; package clothing ;

37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76

} public static String getLabelTitle ( GarmentSize clothing ) { String title = null ; String prefix = " clothing . " ; String suffix = " Size " ; String objectName = clothing . getClass () . getName () ; title = objectName . substring (( prefix . length () - 1) , ( objectName . length () - suffix . length () ) ) ; return title ; } public static void addsPanelItems ( JPanel panel , GarmentSize garment ) { JLabel clothingType = new JLabel ( " Garment Type " ) ; JLabel size = new JLabel ( " Size " ) ; JLabel gender = new JLabel ( " Gender " ) ; JLabel ageGroup = new JLabel ( " Age Group " ) ; JTextField showClothingType = new JTextField (20) ; showClothingType . setText ( getLabelTitle ( garment ) ) ; JTextField showSize = new JTextField (10) ; showSize . setText ( garment . getSize () ) ; JTextField showGender = new JTextField (10) ; showGender . setText ( garment . getaGender () . name () ) ; JTextField showAgeGroup = new JTextField (10) ; showAgeGroup . setText ( garment . getAgeGroup () ) ; JPanel row1 = new JPanel ( new GridLayout (1 ,2) ) ; row1 . add ( clothingType ) ; row1 . add ( showClothingType ) ; JPanel row2 = new JPanel ( new GridLayout (1 ,2) ) ; row2 . add ( gender ) ; row2 . add ( showGender ) ;

128

77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 } }

JPanel row3 = new JPanel ( new GridLayout (1 ,2) ) ; row3 . add ( ageGroup ) ; row3 . add ( showAgeGroup ) ; JPanel row4 = new JPanel ( new GridLayout (1 ,2) ) ; row4 . add ( size ) ; row4 . add ( showSize ) ; panel . add ( row1 ) ; panel . add ( row2 ) ; panel . add ( row3 ) ; panel . add ( row4 ) ;

Program 10.5: ShowsUpcasting.java

You will see that plaidPants is being upcast into moreClothing on line 32 of ShowsUpcasting.java. And then when we run the program we see whats been stored in each objects elds.

129

From this we can see that moreClothing uses TrouserSizes methods instead of GArmentSizes methods. Lastly remember that objects are pass by reference so upcasting is just having a superclass identier point to a subclass object instead.

9.2.2

Downcasting

Here a base class is being assigned to a derived one. Downcasting statements can be in one of two forms,

DerivedClass instanceOfDerivedClass = (DerivedClass) instanceOfBaseClass instanceOfDerivedClass = (DerivedClass) instanceOfBaseClass


130

Downcasting must always be done explicitly, not including the cast before assigning the base class address will generate a ClassCastException. Since a child will have extra more elds and methods than its parent downcasting can be problematic. Its very easy to get either compile or runtime errors when we use downcasting. Frequently subtle logic errors come up when downcasting is used. When downcasting use instanceof and getClass to verify that the super and sub classes are of the same type. The Java Virtual Machines interpreter checks types at runtime via a process called Run Time Type Identication (RTTI) Despite its problems we will generally see downcasts being tied to upcasts because when we assign a childs class to a parents object it is quite likely that we will need to use the childs more specic elds and procedures, hence upcasts and downcasts are tied together frequently. To illustrate downcasting we introduce two new programs, BaseBatlCapSie.java and ShowsDowncast.java. First we look at BaseBallCapSize. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 /* * * @param aGender * @param ageGroup * @param size */ public BaseBallCapSize ( Gender aGender , String ageGroup , String size , 131 } public BaseBallCapSize ( String size , String team ) { this ( null , null , size , team ) ; } public BaseBallCapSize () { this ( null , null , null , null ) ; package clothing ; /* * * BaseballCapSize has information & methods for fitted baseball caps . * @param team is the name of the team that licensed the cap . */ public class BaseBallCapSize extends GarmentSize { private String team ;

String aTeam ) { 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 /* ( non - Javadoc ) * @see java . lang . Object # toString () */ } } /* * * @param team the team to set */ public void setTeam ( String aTeam ) { team = aTeam ; /* * * @return the team */ public String getTeam () { String answer = team ; return answer ; } else super . setSize ( " Unk " ) ; if ( size . equalsIgnoreCase ( " xl " ) ) super . setSize ( " extra large " ) ; if ( size . equalsIgnoreCase ( " l " ) ) super . setSize ( " large " ) ; if ( size . equalsIgnoreCase ( " m " ) ) super . setSize ( " medium " ) ; } public void setSize ( String size ) { if ( size . equalsIgnoreCase ( " s " ) ) super . setSize ( " small " ) ; super ( Gender . NEUTER , null , null ) ; team = aTeam ; setSize ( size ) ;

132

68 69 70 71 72 73 74 }

@Override public String toString () { return " BaseBallCapSize [ team = " + team + " , toString () = " + super . toString () + " ] " ; }

Program 10.6: BaseBallCapSize.java Then the actual downcasting is done in ShowsDowncasting. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 GarmentSize clothing = new GarmentSize ( Gender . FEMALE , " baby " , " m " ) 133 BaseBallCapSize yourCap = new BaseBallCapSize ( " xl " , " Black Sox " ) ; BaseBallCapSize myCap = new BaseBallCapSize ( " m " , " Chicago Cubs " ) ; JPanel rightPanel = new JPanel ( new GridLayout (5 , 1) ) ; framer . add ( rightPanel ) ; JPanel centerPanel = new JPanel ( new GridLayout (5 , 1) ) ; framer . add ( centerPanel ) ; JPanel leftPanel = new JPanel ( new GridLayout (5 , 1) ) ; framer . add ( leftPanel ) ; public static void main ( String [] args ) { JFrame framer = new JFrame ( " Downcaster Exampler " ) ; framer . s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . EXIT_ON_CLOSE ) ; framer . setLayout ( new GridLayout (1 , 3) ) ; framer . setSize (600 , 600) ; framer . setVisible ( true ) ; public class ShowsDowncasting { import javax . swing . JPanel ; import javax . swing . JFrame ; import javax . swing . JLabel ; import javax . swing . JTextField ; import java . awt . GridLayout ; package clothing ;

; 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 JTextField showGender = new JTextField (10) ; JTextField showSize = new JTextField (10) ; showSize . setText ( cap . getSize () ) ; JTextField showClothingType = new JTextField (20) ; showClothingType . setText ( getLabelTitle ( cap ) ) ; public static void addsPanelItems ( JPanel panel , GarmentSize cap ) { JLabel clothingType = new JLabel ( " Garment Type " ) ; JLabel size = new JLabel ( " Size " ) ; JLabel gender = new JLabel ( " Gender " ) ; JLabel ageGroup = new JLabel ( " Age Group " ) ; JLabel team = new JLabel ( " Team " ) ; } title = objectName . substring (( prefix . length () - 1) , ( objectName . length () - suffix . length () ) ) ; return title ; String objectName = clothing . getClass () . getName () ; String prefix = " clothing .. " ; String suffix = " Size " ; public static String getLabelTitle ( GarmentSize clothing ) { String title = null ; } addsPanelItems ( leftPanel , clothing ) ; addsPanelItems ( rightPanel , yourCap ) ; addsPanelItems ( centerPanel , myCap ) ; addsPanelItems ( leftPanel , clothing ) ; addsPanelItems ( rightPanel , yourCap ) ; addsPanelItems ( centerPanel , myCap ) ; // clothing = yourCap ; // yourCap = ( BaseBallCapSize ) clothing ;

134

71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 } }

showGender . setText ( cap . getaGender () . name () ) ; JTextField showAgeGroup = new JTextField (10) ; showAgeGroup . setText ( cap . getAgeGroup () ) ; JTextField showTeam = new JTextField (10) ; if ( cap instanceof BaseBallCapSize ) showTeam . setText ( BaseBallCapSize . getTeam () ) ; JPanel row1 = new JPanel ( new GridLayout (1 ,2) ) ; row1 . add ( clothingType ) ; row1 . add ( showClothingType ) ; JPanel row2 = new JPanel ( new GridLayout (1 ,2) ) ; row2 . add ( gender ) ; row2 . add ( showGender ) ; JPanel row3 = new JPanel ( new GridLayout (1 ,2) ) ; row3 . add ( ageGroup ) ; row3 . add ( showAgeGroup ) ; JPanel row4 = new JPanel ( new GridLayout (1 ,2) ) ; row4 . add ( size ) ; row4 . add ( showSize ) ; JPanel row5 = new JPanel ( new GridLayout (1 ,2) ) ; row5 . add ( team ) ; row5 . add ( showTeam ) ; panel . add ( row1 ) ; panel . add ( row2 ) ; panel . add ( row3 ) ; panel . add ( row4 ) ; panel . add ( row5 ) ;

Program 10.7: ShowsDowncasting.java

You will see that for us to downcast rst we had to do an upcast. The following picture shows us what happens during the two sets of calls to addsPanelItems. Lastly notice that team is static as well 135

136

137

9.2.3

Upcasting/Downcasting Guidelines

This is one of the easiest ways to implement polymorphism in your Java applications. However if you are not careful it will introduce subtle errors and can cause major problems for both the developer and user. To use upcasts and downcasts eectively keep the following considerations in mind. 1. Create an object of the base class. 2. For each instance of the base class we need a derived class to do an upcast. 3. Upcasts lead to references to the derived class unique elds being lost. 4. When we need to deal with something in that only the derived class can do we will need to do a downcast from the more general class to the specic one. 5. Downcasts should only be done for classes that correspond to the child. To make sure that the class you are trying to cast was originally the same as the child use the instanceof operator. 6. When doing a downcast make sure that any unique elds and methods are still handled correctly.

9.3

Abstract Classes

The second way of achieving polymorphism is by using abstract classes For a class to be abstract at least one of its methods will not have a body. The syntax of an abstract class declaration is

accessModier absract ClassName {


... ...

access-modier return-type methodName(parameters); }

You will notice that both the method and the class must have the keyword abstract in their headers. Also the method header is followed by a semicolon.

9.3.1
when

Guidelines For Making A Method Abstract

We do not need to make all the functions in a class abstract, we only need to create an abstract function

All the subclasses need to have the functionality that the abstract function is supposed to provide. Each subclass implementation of the abstract method will unique. 138

9.3.2

Properties Of Abstract Methods

Whenever an abstract function is created it must be implemented in a descendant class. Since abstract functions cannot be dened in the base class but they have to be overridden in the children they cannot be marked as private. We can use protected, package, or public.

9.3.3

Properties Of Abstract Classes

A class with no abstract methods is called a concrete class. If an abstract class is marked private then none of its concrete children will be able to redene their implementations of its abstract functions. Another property of abstract classes is that they cannot be used to create other classes. However an abstract class. concrete descendants can instantiate objects. Though we cannot have instances of an abstract class we can declare it as a variable which the concrete class will be plugged into. Our rst example of an abstract class is DrawShape, then we shall try implementing GarmentSize using abstraction. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 /* * * Default constructor which creates a null GarmentSize object . 139 private int age ; // This is only used to find the age group . // Had to make size protected so that the concrete classes could set its value . protected String size ; private String clothingType ; public abstract class GarmentSize { private Gender aGender ; private AgeGroup anAgeGroup ; package clothes . sizes ; /* * * GarmentSize is an abstract class used set and display information about garments . * Its concrete subclasses must have concrete implementations of setSize () . * * * */ // Decided to use an enum for the age groups since they are fixed . enum Gender { MALE , FEMALE , NEUTER }; enum AgeGroup { BABY , TODDLER , PRETEEN , TEEN , ADULT , NONE } @param Gender is an enum whose values are MALE , FEMALE , NEUTER . @param AgeGroup an enum whose values are BABY , TODDLER , PRETEEN , TEEN , ADULT , & NONE

26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 } } }

*/ public GarmentSize () { this ( null , null , null , 0) ;

/* * * Creates a GarmentSize object and sets the value of AgeGroup based value of age * parameter . * @param aGender - An enum which represents gender . * @param age - This is only ever used to find the correct age group . * @param size - A String */ public GarmentSize ( Gender aGender , int age , String size ) { this ( aGender , null , size , age ) ; setAgeGroup ( age ) ;

/* * * Creates a GarmentSize object , with parameters below . * @param aGender * @param anAgeGroup * @param size */ public GarmentSize ( Gender aGender , { this ( aGender , anAgeGroup , size , 0) ; AgeGroup anAgeGroup , String size )

/* * * @param aGender * @param size * @param AgeGroup * @param clothingType */ public GarmentSize ( Gender aGender , int age ) { this . aGender = aGender ; this . anAgeGroup = anAgeGroup ; this . age = age ; this . size = size ; AgeGroup anAgeGroup , String size ,

140

64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 /* * * Sets the age group based on the age range that age falls under . * @param nonnegative int representing the age . */ public void setAgeGroup ( int age ) { if ( age < 0 ) } /* * Sets value of enum AgeGroup . * @param AgeGroup to set possible values to . */ public void setAgeGroup ( AgeGroup anAgeGroup ) { this . anAgeGroup = anAgeGroup ; } /* * * @return the AgeGroup */ public AgeGroup getAgeGroup () { AgeGroup answer = this . anAgeGroup ; return answer ; } /* * * @param aGender the aGender to set */ public void setaGender ( Gender aGender ) { this . aGender = aGender ; } /* * * @return the aGender */ public Gender getGender () { Gender answer = this . aGender ; return answer ; } // Need to set the clothingType once the object is created . setClothingType () ;

141

105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 /* * } /* * } /* * * */ } } else

this . anAgeGroup = AgeGroup . NONE ; else if (( age >= 0) && ( age <= 1) ) this . anAgeGroup = AgeGroup . BABY ; else if (( age >= 2) && ( age <= 5) ) this . anAgeGroup = AgeGroup . TODDLER ; else if (( age >=6) && ( age <= 12 ) ) this . anAgeGroup = AgeGroup . PRETEEN ; else if (( age >= 13) && ( age <= 19) ) this . anAgeGroup = AgeGroup . TEEN ; this . anAgeGroup = AgeGroup . ADULT ;

/* * Returns the string which corresponds to the type of garment . * @return the clothingType */ public String getClothingType () { String answer = this . clothingType ; return answer ;

Sets the cloth ingTyp eField by calling a private method .

public void setClothingType () { this . clothingType = extractsType () ;

* Abstract method that to set size of different types of clothes . * @param size of the garment . */ public abstract void setSize ( String size ) ; public String getSize () { String answer = this . size ; return answer ;

* You should not really need to call this since garments are

142

categorized by age 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 /* * } type = object . substring ( startOfTypeString , endOfTypeString ) ; return type ; int s tartOf TypeSt ring = prefix . length () ; int endOfTypeString = object . length () - suffix . length () ; /* * * Parses the string returned by getclass () & getname () fields to get the class name . * Strips the package information & suffix " Size " from the class name . * @return */ private String extractsType () { String type = null ; String suffix = " Size " ; String prefix = " clothes . sizes . " ; String object = this . getClass () . getName () ; } /* * * If the age group was set previously and age is outside of the age group range * set the age to the age group s midpoint . parameter . * @param age a nonnegative int . */ public void setAge ( int age ) { this . age = age ; Otherwise sets to age to } * groups . */ public int getAge () { int answer = age ; return answer ; Its only here for possible error checking . * @return the age

143

183 184 185 186 187 188 189 190 191 192 } }

* Overrides */ public String toString () { String aString = clothingType + " : size = " + size + " , gender = " + aGender ; aString += " , age group = " + anAgeGroup ; return aString ;

Program 10.8: GarmentSize.java

One of the things that you will notice is that even though the previous program is named GarmentSize its in package clothes.sizes unlike our rst encounter with GarmentSize which was in package clothing. You probably noticed that I also redened ageGroup to be an enum since. Lastly, the only function that really needs to be dierent for the various types of clothes we might need to get size information for is their sizes. So only setSize is abstract. Furthermore, I rewrotethe toString method to make it more general. Now that the major changes in GarmentSize have been examined we can look at how TrouserSize is reimplemented to make use of abstractions. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /* * 144 } /* * * Creates an empty trouser object . */ public TrouserSize () { this ( null , null , null , 0 , 0) ; /* * * Gets and displays information about trouser sizes . GarmentSize . * @param waist tailor s waist in inches , an int . * @param inSeam tailor s inseam in inches , an int . */ public class TrouserSize extends GarmentSize { private int waist ; private int inSeam ; Subclass of package clothes . sizes ;

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 } } }

* Creates TrouserSize object from the following fields . the trousers * are set by this constructor .

The size of

We chain this to another constructor .

* @param aGender field inherited from super class .. * @param anAgeGroup field inherited from super class . * @param waist * @param inSeam */ public TrouserSize ( Gender aGender , AgeGroup anAgeGroup , int waist , int inSeam ) { this ( aGender , anAgeGroup , null , waist , inSeam ) ; this . setSize ( intsToSizeString () ) ;

/* * * Creates a TrouserSize object and uses the size argument to set the values of * waist & inSeam . Again this is chained to another constructor .. * @param aGender field inherited from superclass * @param anAgeGroup field inherited from superclass * @param size should be of the form " waistxinseam ". otherwise . */ public TrouserSize ( Gender aGender , AgeGroup anAgeGroup , String size ) { this ( aGender , anAgeGroup , size , 0 , 0) ; this . waist = getWaistFromSize ( size ) ; this . inSeam = ge tInSea mFromS ize ( size ) ; as in 32 x30

/* * All other constructors in TrouserSize are chained to this . only call to the * the superclass constructor happens here . */

The

public TrouserSize ( Gender aGender , AgeGroup anAgeGroup , String size , int waist , int inSeam ) { super ( aGender , anAgeGroup , size ) ; this . waist = waist ; this . inSeam = inSeam ; this . size = size ;

145

55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92

/* * * Used to get the waist . * @return waist . */ public int getWaist () { return waist ; } /* * * Set the waist . * @param waist */ public void setWaist ( int waist ) { this . waist = waist ; } /* * * @return inSeam */ public int getInSeam () { return inSeam ; } /* * * Sets the in seam . * @param inSeam */ public void setInSeam ( int inSeam ) { this . inSeam = inSeam ; } /* * * Implementation of abstract method setSize . invoked by a * non TrouserSize object then it displays a message and exits . * @param size a string in the form " aaxbb " where aa are the waist and bb are * the inseam . ". */ public void setSize ( String size ) { If size is in the wrong format the its set to " Unknown If this method is

146

93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 } /* * } /* * * * */ }

if ( ( this instanceof TrouserSize ) && ( checkSize ( size ) == false ) ) this . size = " Unknown " ; else if ( ( this instanceof TrouserSize ) && ( checkSize ( size ) == true ) ) this . size = size ; else { System . out . println ( this . getClass () . getName () + " is not a pair of trousers . " ) ; System . exit (25) ; }

We only enclose the string describing a TrouserSize object between square braces

public String toString () { return " [ " + super . toString () + " ]";

* If the string is not in the correct form to be the size of a pair of pants returns * @param aString hopefully of the form aaxbb where aa - waist , bb inseam . * @return true if aString is in the format of a aaxbb where aa and bb are digits * separated by an x . */ Otherwise returns false .

private boolean checkSize ( String aString ) { String middleLetter = " x " ; return ( middleLetter . regionMatches (0 , aString , 2 , 1) ) ;

/* * After it verifies that the string is in the correct format for a trouser sizes * will strip the waist measurement from the string .

147

127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 } } } }

* @param size * @return waist */ public int getWaistFromSize ( String size ) { int waist = 0; if ( checkSize ( size ) ) waist = Integer . parseInt ( size . substring (0 , 1) ) ; return waist ;

/* * After it verifies that the string is in the correct format for a trouser sizes * will strip the in seam measurement from the string . * @param size * @return inSeam */ public int ge tInSea mFromS ize ( String size ) { int inSeam = 0; if ( checkSize ( size ) ) inSeam = Integer . parseInt ( size . substring (3 , 4) ) ; return inSeam ;

/* * * Converts the measurements for waist and inseam into a string representing the * size . * @return size */ public String intsToSizeString () { String size = this . getWaist () + " x " + this . getInSeam () ; return size ;

Program 10.9: TrouserSize.java

148

You might have noticed that the we implemented the abstract method setSize. On the other hand with our new implementation of BaseBallCapSize we see that the code is much simpler. However there are no really big changes in either subclass implementation of their functionality. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 /* * * Sets the size of baseball caps . * @param size of cap . sizes . */ public void setSize ( String size ) { 149 A value of Possible sizes are " s " for small , " m " for * medium , " l " for large , " xl " for extra large , & " Unk " for unknown * " Unk " for baseball cap size indicates there might be an error . } /* * * All the other constructors in this class are chained to this one . */ public BaseBallCapSize ( AgeGroup anAgeGroup , String size , String aTeam ) { super ( Gender . NEUTER , anAgeGroup , size ) ; team = aTeam ; } /* * * Create a BaseBallCapSize object * @param size the size of the baseball cap . * @param team the name of the team . */ public BaseBallCapSize ( String size , String team ) { this ( null , size , team ) ; An enum } public BaseBallCapSize () { this ( null , null , null ) ; package clothes . sizes ; /* * * BaseballCapSize has information & methods for fitted baseball caps . * @param team is the name of the team that licensed the cap . */ public class BaseBallCapSize extends GarmentSize { private String team ;

37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 } /* * } /* * } }

if ( size . equalsIgnoreCase ( " s " ) ) this . size = " small " ; if ( size . equalsIgnoreCase ( " m " ) ) this . size = " medium " ; if ( size . equalsIgnoreCase ( " l " ) ) this . size = " large " ; if ( size . equalsIgnoreCase ( " xl " ) ) this . size = " extra large " ; else this . size = " Unknown " ;

public String getSize () { return this . size ;

* @return the team */ public String getTeam () { return this . team ;

* @param team the team to set */ public void setTeam ( String aTeam ) { this . team = aTeam ;

/* ( non - Javadoc ) * @see java . lang . Object # toString () */ @Override public String toString () {

150

77 78 79 80 81 82 } }

String aString = " [ " + super . toString () + " , team = " + getTeam () + " ]"; return aString ;

Program 10.11: BaseBallCapSize.java But when we look at UsingAbstractClass we see that when we want to use the superclass methods and its much cleaner and simpler. Since there is no upcasting or downcasting we do not have to check if the method being invoked is the correct one for the object. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 System . out . println ( " \ n " + aCap . toString () ) ; 151 // Create two baseball caps and print their information . BaseBallCapSize aCap = new BaseBallCapSize ( " m " , " Black Sox " ) ; aCap . setAgeGroup ( AgeGroup . PRETEEN ) ; BaseBallCapSize cricketCap = new BaseBallCapSize ( AgeGroup . ADULT , " L " , " Chcago Cubs " ) ; // If inSeam & waist are set outside a constructor we need to invoke setSize () .. denimPants . setSize ( denimPants . intsToSizeString () ) ; System . out . println ( denimPants . toString () ) ; // Testing iif TrouserSize s instance methods are working correctly . TrouserSize denimPants = new TrouserSize () ; denimPants . setAgeGroup ( AgeGroup . TEEN ) ; denimPants . setaGender ( Gender . NEUTER ) ; denimPants . setInSeam (29) ; denimPants . setWaist (34) ; public static void main ( String [] args ) { TrouserSize leatherPants = new TrouserSize ( Gender . FEMALE , AgeGroup . TODDLER , " 32 x30 " ) ; System . out . println ( leatherPants . toString () ) ; public class U si ng Ab st ra ct Cl as s { package clothes . sizes ;

26 27 28 29 } }

System . out . print ( cricketCap . toString () ) ;

Program 10.12: UsingAbstractClass.java

9.4

Interfaces

An interface is a type thathas all its methods marked as abstract. The syntax for creating an interface is;

public interface InterfaceName { public returnType methodName1(. . . ) public returnType methodName2(. . . ) }


You will notice that the methods do not need the keyword abstract in their headers. Interface Names The will should all end with the sux able.

9.5

Inner Classes

See chapters 8 and 13 of Absolute Java

152

Chapter 10

Exceptions
In software development one of the biggest worries is dealing with boundary conditions and cases where the algorithms and data are not meant to handle. In the early days systems would simply fail, this behaviour was usually undesirable since i We need information about why the failure occurred. ii Applications that simply stop working at a critical time can cause a major catastrophe. To deal with exceptions and failures gracefully developers do a number of things. Many of these features that we will discuss here are in other languages. With exception handling an application is more reliable, it will fail gracefully and will alert users and developers about possible errors.

10.1

Generalized Exception Handling Mechanism

Generally to handle exceptions in a manageable way we break down the ow of of execution as follows; One portion of the code deals with produce the exception. A dierent portion of the code handles the exception.

10.1.1

Termination Versus Resumption Models Of Exception Handling

Some languages will return the ow of execution to point just after the exception was generated, they only do this wen the problem is dealt with in the error handling block though. Such languages follow a resumption model since the ow of control returns to the next statement after the error is handled. On the other hand other languages will have the ow of execution start after the error handling block. Since the old ow of control that would have existed before the error is terminated such languages follow an termination model. In Java ow of execution never goes back to the point before the exception happened so Java follows a termination model of exception handling. 153

10.2

Handling Exceptions With If-Else

So far we have used if-else constructs to deal with boundary conditions and errors. The problem with this style is that there is no standard way of documenting how the errors are reported, detected and handled. So each coder will do exception handling in their own idiosyncratic way. For an example of the complexity that can be involved with using if-else for handling exceptions look at AssuresEntryIsDouble1.java.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

import java . text . NumberFormat ; import java . text . ParsePosition ; import javax . swing . JOptionPane ;

/* * * Displays a number entered into a dialog window as double in a message window . * All the boundary conditions are handled with if - else . */ public class A s s u r e s E n t r y I s D o u b l e 1 { /* * * Converts a double to a Double object and displays it in a message window . * @param number a double . */ public static void displayOutput ( double number ) { Double temp = new Double ( number ) ; String message = " You entered " + temp . toString () + " . " ; JOptionPane . show Messag eDialo g ( null , message ) ; } // end displayOutput /* * * If nonnumeric input was given displays an error message and makes the * program exit . */ public static void h a n d l e s N o n N u m e r i c E n t r y () { String message = " Nonnumeric entry passed to di spl ay In pu tD ia lo g . " ; message += " Exiting with status 44 " ;

JOptionPane . show Messag eDialo g ( null , message ) ; 154

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 /* * /* *

System . exit (44) ; } // end h a n d l e s N o n N u m e r i c E n t r y

* Displays pane asking for a number . * handlesNonNumericEntry . * * @return a Double object . */

For nonnumeric entries invokes

public static Double dis pl ay In pu tD ia lo g () { Double aDoubleObj = null ; String entry = JOptionPane . showInputDialog ( " Enter a number . " ) ; // If the entry is not a number then call h a n d l e s N o n N u m e r i c E n t r y . // Otherwise return the entry as Double . if ( false == isNumber ( entry ) ) h a n d l e s N o n N u m e r i c E n t r y () ; aDoubleObj = Double . parseDouble ( entry ) ; return aDoubleObj ; } // end d is pl ay In pu tD ia lo g

* Converts a Double object to a double primitive . * @return a double . */ public static double c o n v e r t s F r o m D o u b l e O b j () { double value = dis pl ay In pu tD ia lo g () . doubleValue () ; return value ; } // end c on ve rt sF ro mD ou bl e /* * * Tests if a string is numeric . * @return a boolean . */ public static boolean isNumber ( String aString ) { // We use the NumberFormat object since it works for decimals as well as // integers . NumberFormat formatter = NumberFormat . getInstance () ;

155

73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 } // end A s s u r e s E n t r y I s D o u b l e 1 Program 11.1: AssuresEntryIsDouble1.java value = c o n v e r t s F r o m D o u b l e O b j () ; displayOutput ( value ) ; } // end main /* * * Calls other functions . */ public static void main ( String [] args ) { double value = 0; // Here we actually parse aString . If any of the entries do not correspond // to a number then position . getIndex () will be different from aString s // length . formatter . parse ( aString , position ) ; return aString . length () == position . getIndex () ; } // end isNumber // Set the position we will start to the parse aString from . ParsePosition position = new ParsePosition (0) ;

10.3

Handling Exceptions With Try-Catch

Though what we did works its fairly cumbersome fortunately we can use Javas try-catch blocks to do the same thing much more simply and with less code.

10.3.1

Try Block

In the try block we place the instructions that we hope will run without generating an error or failure due to boundary conditions. From looking at our exception handling mechanism we see that the try block is where the code that generates the exception is placed. The syntax of a try block is;

try {

statements to execute that might generate an error;

156

10.3.2

Catch Block

If the code in the try block generated an error or boundary condition then the error is thrown to the catch block by the Java interpreter to be handled. Catch blocks implement the second part of the exception handling mechanism. The syntax of a catch block is shown below.

catch (ExceptionClass parameterName) { Statements to handle instance of ExceptionClass }


You will notice that catch takes an object of type Exception as its parameter. To see all the types of Exceptions that are standard in Java consult the APIs. Since there are many possible exceptions that can be generated by a try block we will have a catch block for each one. Some exceptions are more specic than others being that some are children of more generic exceptions. The most specic catches should be placed rst because the interpreter will pick the rst catch block it nds. So if the rst conditions are too broad then the more specic ones will always be skipped. AssuresentryIsDouble1s functionality is implemented in AssuresEntryIsDouble2.java with try & catch blocks. AssuresEntryIsDouble2s code could have been made even simpler by getting rid of convertsFromDoubleObj but that would obscure the eect of exception handling with try and catch blocks.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

import /* *

javax . swing . JOptionPane ;

* Displays a number entered into a dialog window as double in a message window . * We use try - catch blocks for dealing with the boundary conditions . */ public class A s s u r e s E n t r y I s D o u b l e 2 { /* * * Converts a double to a Double object and displays it in a message window . * @param number a double . */ public static void displayOutput ( double number ) { Double temp = new Double ( number ) ; String message = " You entered " + temp . toString () + " . " ; JOptionPane . show Messag eDialo g ( null , message ) ; } // end displayOutput /* * * Displays pane asking for a number . * @return a Double object . */ 157 For nonnumeric entries invokes

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61

public static Double dis pl ay In pu tD ia lo g () { Double aDoubleObj = null ; String entry = JOptionPane . showInputDialog ( " Enter a number . " ) ; // Here we try to convert entry from a string to a double Object . try { aDoubleObj = Double . parseDouble ( entry ) ; } // Replaced h a n d l e s N o n N u m e r i c E n t r y with this catch block . catch ( N u m b e r F o r m a t E x c e p t i o n e ) { String message = " Nonnumeric entry passed to di sp la yI np ut Di al og . " ; message += " Exiting status = 44. " ; JOptionPane . show Messag eDial og ( null , message ) ; System . exit (44) ; } // end d is pl ay In pu tD ia lo g // If the try is successful then the flow of execution drops to the // return statement . return aDoubleObj ; } /* * * Converts a Double object to a double primitive . * @return a double . */ public static double c o n v e r t s F r o m D o u b l e O b j () { double value = dis pl ay In pu tD ia lo g () . doubleValue () ; return value ; } // end c on ve rt sF ro mD ou bl e /* * * Calls other functions . */ public static void main ( String [] args ) { double value = 0; value = c o n v e r t s F r o m D o u b l e O b j () ;

158

62 63 64 65

displayOutput ( value ) ; } // end main } // end A s s u r e s E n t r y I s D o u b l e 2 Program 11.2: AssuresEntryIsDouble2.java

10.4

Handling Exceptions With Try-Catch-Finally

We have already seen how try-catch blocks can be used to handle exceptions and we noticed the improvements it made to our code. Now we see how the nally operator can assist us with exception handling.

10.4.1

Finally Block

A nally block is executed weather an exception is thrown or not. The nally block is a good place to release resources that were used or called in the try block. The nally blockss syntax is;

nally { statements to execute outside the try-catch blocks }


It is essential that no exceptions are thrown in the nally block. AssuresEntryIsDouble3 implements the same functionality as the previous two programs but is much shorter and easier to follow. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 String message = null ; String entry = JOptionPane . showInputDialog ( " Enter a number . " ) ; 159 /* * * Displays a message in the panel depending on if there is an error or if the * entry can be converted to a double . */ public static void entryProcessor () { int exitValue = 0; Double aDoubleObj = null ; /* * * Displays a number entered into a dialog window as double in a message window . * We use try - catch - finally blocks for dealing with the boundary conditions . */ public class A s s u r e s E n t r y I s D o u b l e 3 { import javax . swing . JOptionPane ;

19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 /* * * Invokes entryProcessor . */ public static void main ( String [] args ) { entryProcessor () ; } // end main } // end A s s u r e s E n t r y I s D o u b l e 3 Program 11.3: AssuresEntryIsDouble3.java } } // End entryProcessor // The statements that will always be executed go here . finally { JOptionPane . show Messag eDial og ( null , message ) ; System . exit ( exitValue ) ; } // The super class Exception is handled after the subclass . catch ( Exception e ) { message = " General input error in di sp lay In pu tD ia lo g . " ; message += " Exiting with status 12 " ; exitValue = 12; } // N u m b e r F o r m a t E x c e p t i o n is a child of Exception so it goes first . catch ( N u m b e r F o r m a t E x c e p t i o n e ) { message = " Nonnumeric entry passed to di sp lay In pu tD ia lo g . " ; message += " Exiting status = 44. " ; exitValue = 44; } // Here we try to convert entry from a string to a double Object . try { aDoubleObj = Double . parseDouble ( entry ) ; message = " You entered " + aDoubleObj . toString () + " . " ; message += " Exiting with status 0. " ;

You will notice that the output dialog is not displayed until the nally block is reached. Also using nally allows us to keep the program running and exit in a much more clean and general fashion than in either of the two previous programs. 160

10.4.2

The Dierence Between A Try Block & A Try Statement

You will sometimes read or hear people referring to a try statement instead of a try block. A try statement includes not only the try block but any catch blocks associated with the try block as well as its possible nally block. The dierence between a try block and statement is shown in the Venn diagram.

10.5

Overview Of The Throwable Class

Errors in a program can be classied as either synchronous or asynchronous. Asynchronous errors are due to things that are outside the programs direct control. Asynchronous errors are due to other programs, network problems or resources such as discs, les, memory that are not directly under the control of the program that uses them. Synchronous errors on the other hand occur when a fault occurs with resources, memory, les, functions that are under the direct control of the application that experiences the failure. You could say that synchronous errors are caused by things directly under the programs control. Since all errors are caused by boundary conditions of some sort we can consider all errors as things that throw an error condition. With this behaviour in common both synchronous and asynchronous errors are handled by the Throwable class. Throwable exists under java.lang.Object package so we see that its parent class is Object. The synchronous and asynchronous errors have the following subclasses under Throwable Error deals with asynchronous errors. 161

Exception deals with synchronous errors.i The next gure shows the hierarchy of these four classes.

Everything other than the Exception class in the above hierarchy is outside the scope of this chapter.

10.6

The Exception Class

Exception has a lot of subclasses, one its most important subclasses is RuntimeException which we shall discuss in a bit more detail later. One way that all exceptions in Java are categorized is based on how the interpreter deals with them. Exceptions are either checked or unchecked. Checked Exceptions If these are not handled by a try statement the program will not compile. All exceptions outside of RuntimeException fall under this category. Unchecked Exceptions Since the complier does not check to see if they are handled a program can compile without handling this class of exceptions.

10.6.1

Exceptions Constructors

Exception has four constructors. The default takes no arguments, One takes string as its parameter, a second an object of type Throwable, and the last one takes both a string and a Throwable as its arguments. All of Exceptions constructors will be used in the future examples.

10.6.2

Exceptions Mutators

Most of Exceptions setters that we are interested in are inherited from Throwable. The setters are setStacktrace, initStackTrace, & initCause. The rst two setters deal with conguring the values of the stack while the last is used to initialize the a Throwable to some value. Again we shall see these used in future examples. 162

10.6.3

Exceptions Accessors

The getters return either the stack or a message describing the exception. However, unlike getMessage, getLocalizedMessage, getStackTrace, & printStackTrace getCause will return the Throwable that caused the exception to occur.

10.6.4

Exceptions Commonly Used Subclasses

It was mentioned before that Exceptions subclasses are either checked or unchecked. In this section we are simply presenting the most commonly used subclasses in each category. For more details on their propeties consult the Java APIs. ArithmeticException NegativeArraySizeException IllegalStateException ClassCastException EmptyStackException UnknownTypeException NullPointerException BuerOverowException UnsupportedOperationException ArrayStoreException IllegalArgumentException IllegalPathStateException EnumConstantNotPresentException IndexOutOfBoundsException UnknownElementException NoSuchElementException SystemException SecurityException

Table 10.1: Unchecked Exceptions Found in RuntimeException

ClassNotFound CloneNotSupportedException IllegalAccessException InstantiationException InterruptedException NoSuchFieldException NoSuchMethodException

Table 10.2: Checked Exceptions

10.7

throw

So far we have seen cases where the interpreter throws an exception without any intervention from the developer. Such exception throwing is implicit. However there are times when we want to explicitly throw an exception, and for that we use the throw operator. The syntax for throw is. . .

throw ExcepectionClassConstructor()
163

By using throw we can toss exceptions anywhere in our code and we can also have a try block toss multiple exceptions to diering catch blocks explicitly. In AssignSoccerPlayer you can see throw being used twice. Lastly if the condition that causes throw statement to be exceuted then the programs ow of execution passes to the catch invoked by the throw statement. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 } Program 11.4: AssignSoccerPlayer.java } } catch ( I n v a l i d J e r s e y N u m b e r E x c e p t i o n e ) { aPlayer . h a n d l e s I n v a l i d J e r s e y N u m b e r E x c e p t i o n () ; } catch ( E x c e s s i v e I n j u r y E x c e p t i o n e ) { aPlayer . h a n d l e s E x c e s s i v e I n j u r y E x c e p t i o n () ; } else a . Player . assignToField () ; if ( aPlayer . getJerseyNumber () <= 0 ) throw new I n v a l i d J e r s e y N u m b e r E x c e p t i o n ( " improper number " ) ; if ( currentInjuries >= 5 ) throw new E x c e s s i v e I n j u r y E x c e p t i o n () ; public static void main ( String [] args ) { TeamPlayer aPlayer = new TeamPlayer () ; try { PlayerSetter aSetter = new PlayerSetter ( aPlayer ) ; currentInjuries = aPlayer . getNumOfInjuries () ; public class A ss ig nS oc ce rP la ye r {

10.7.1

Scope Of Thrown Exceptions

Whenever an exception is thrown there is a hierarchy of places where it can be handled. i The rst catch block associated with the try block handles the thrown exception. 164

ii If the rst catch block does not handle the class of exception thrown then its passed to the next catch in the try statement. iii If none of the try statements blocks can catch the exception then its passed on to any nested try statements. iv If there are no nested catch block that can handle the exception then its passed to any catch blocks in other try statements. v In the event that no try statements are associated with the exception then the Java interpreter will deal with the exception. A throw operator is used to exit a try block immediately and pass the ow of execution to a catch block. Consider the case where you need to sorts out how to deal with the exception. The two ways of dealing with exceptions are either to use try blocks or assertions.

10.8

Using Throws In Methods

To make error handling in functions easier we can use the throws keyword. Its syntax is. . .

methodModifers returnType methodName( parameters) throws ExceptionClass {

methodBody; }
By using throws in our methods we are able to cut down on writing error handling code yet still get useful information about possible causes or errors. Whenever a function throws an exception the thrown exception must be handled by the invoker.

10.9

Exception Output

Frequently users for not need to see error messages. Also error messages should not interrupt the ow of output. Generally we want to know the what exception was thrown, what les and other resources the application was using when the error was thrown along with what was in the stack. You can see that the programmer might want to get a lot of information. Since the information required to discover why an exception was thrown can be quite large this is frequently written to a log le. If we used System.out everything will be written or directed to standard output, which is the console. On the other hand using System.err will send all error messages to standard error where it really should be directed to. Instead of using println or printf from System.out we will use System.err We can put all of our code in a try block so that it throws an exception to the interpreter i.e. 165

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

public class UsingExceptions { public static void throwsException () throws A ri t h me t i cE x c ep t i on { try { int x = 5/0; } catch ( Securi tyExc eption e ) { e . printStackTrace () ; } finally { System . err . println ( " Leaving throwsException : " ) ; } } public static void main ( String [] args ) { try { throwsException () ; } catch ( A r i th m e ti c E xc e p ti o n e ) { System . err . println ( e + " caught in main . " ) ; } } } Program 11.3: UsingExceptions.java

10.9.1

Excepetions Message Utilities

The most commonly used functions for displaying or getting error messages in Java are shown below. Though there are a great deal more than the four shown here these are the most commonly used ones. All of them except for System.err.println are methods in Throwable. Being that Throwable is a child of Object its in Java.lang so we do not use use an import statement to use the last three functions. System.err.println Displays a string in standard error. printStackTrace Displays the stack trace and the exception that was thrown. printStackTrace nicely formats the output. getStackTrace Returns an array that contains the stack elements. We can use this to send the stack to some other location other than standard error, a log le perhaps. 166

getMessage Returns a string associated with the exceptions message. To see what other methods are in available in Throwable for showing and getting exceptions and errors look at either http://download.oracle.com/javase/7/docs/api/ or your local Javas documentation.

10.10

Rethrowing Errors

Sometimes a method might not know how to handle an exception. For example look at the makeFile below. 1 2 3 4 5 6 7 } Since makeFile does not know what to do it throws the exception back to its invoker for it to be handled. Exceptions are rethrown if; The method cannot process the exception. The function can only partially process the exception. An exception must be thrown before the nally block. public void makeFile ( String path , String fileName ) { try { } catch ( NoWri tePerm ission e ) { System . err . println ( Method makeFile cannot handle + e + exception . ) ; throw e ; }

10.11

Stack Unwinding

If an uncaught exception is thrown by a function then all of the function;s data and instructions are removed from the stack and then the exception is passed to the invoker. If the invoker also refuses to handle to exception then its also removed from the stack. If this cycle continues to the main method the application will exit with an error number.

10.12

Chained Exceptions

You saw earlier that some methods can throw an exception to their inovker and have the caller handle it. This can cause problems if the invovker does it own exception handling in a try block. If the invoker does not report that some other method throws an exception this can make it hard to debug so Java uses chained exceptions. To chain the exception we simply put a throw statement in the invokers catch block as shown in the Chainer.java. 167

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28

public class Chainer { public static void main ( String [] args ) { try { thrower () ; } catch ( U n s u p p o r t e d O p e r a t i o n E x c e p t i o n e ) { e . printStackTrace () ; } } public static void thrower () throws U n s u p p o r t e d O p e r a t i o n E x c e p t i o n { try { madMethod () ; } catch ( N e g a t i v e A r r a y S i z e E x c e p t i o n e ) { System . out . println ( " Original cause : " + e . getCause () ) ; } } public static void madMethod () { U n s u p p o r t e d O p e r a t i o n E x c e p t i o n e = new U n s u p p o r t e d O p e r a t i o n E x c e p t i o n ( " not allowed " ) ; e . initCause ( new N e g a t i v e A r r a y S i z e E x c e p t i o n ( " size is -13 " ) ) ; throw e ; } } Program 11.4: Chainer.java So with the throw in thrower we will be able to get the reason why madMethod threw an exception.

10.13

Rolling Your Own Exceptions

If your classes do specic thingd its a good idea to make exceptions for them. If you decide to roll your own exceptions you can only have two constructors in the class. The default no-argument constructor will pass default messages to the super constructor. The second constructor takes a message as its argument, and this message is passed to the super constructor. 168

10.14

Assertions

When a function is executed there might be things about its stack that should be true. If the its state is not what we expect then this is an indication of possible errors. This fact is used in debugging programs by using the assert keyword. The syntax i which we use assert is. . .

{ method-body assert(condition that should evaluate to true) }


To enable assertions at the command line do java -ea ProgramName Once debugging is done assertions should be disabled.

169

170

Chapter 11

Debugging
Generally the rst time we run a program it will generate some logic errors that the programmer must x. I would say debugging is dierent from testing because generally dierent people run the tests. Also debugging is done by the programs designer while testing is handled by a dierent team. Hopefully by the time you are done with this chapter you will be aware of good strategies for detecting logic errors in your code.

11.1

The Debugging Process

Generally when debugging we are trying to nd the source of an error and this can be quite time consuming however if its done in a structured process we can detect and remove bugs much more easily.

11.2 11.3
11.3.1 11.3.2

Doing Code Walk Throughs Using Print To Debug


Advantages Of Print Statement Debugging Disadvantages Of Print Statement Debugging

11.4 11.5

Using Assert To Debug Debuggers

A debugger is very useful since we are able to view the running programs state in memory. They can make debugging very easy. Though some of the popular debuggers are gdb, jdb, Visual Studio Debugger. They all have some things in common. 171

11.5.1 11.5.2

Stack Tracer Breakpoints

Watch Points Class Breakpoints Exception Breakpoints Method Breakpoints

11.5.3 11.5.4

Prolers Code Analysis Engine

11.6
11.6.1 11.6.2 11.6.3 11.6.4

Using The Eclipse Debugger


Setting Breakpoints Running The Debugger Viewing The Stack Watching Values Of Variables

172

Chapter 12

Unit Testing

173

174

Chapter 13

Files
In Java les are seen as a stream of bytes. The end of a le is shown either by an end of le marker or by a byte count that shows where the le ends.

175

176

Chapter 14

I/O Streams

177

178

Chapter 15

Generics
You have seen that in many of our classes we do all kinds of checks and use exceptions to make sure that it will work with the correct data types and class. A classic example of this is in sorting algorithms. With our current knowledge even for arrays we would have to create a dierent sort of method for ints, oats, doubles, chars, and Strings. Doing this is very tedious, and since the same implementation has to be written for each data type its easy to introduce inconsistencies and errors into each sort implementation. One solution to the problem is to have one general class that takes as its input any nonprimitive type as its argument. Because of this generics are also called parameterized types.

Advantages Of Using Generics The advantages of using generic classes are as follows;

i We can use methods on various data types without having to do so much type checking and casting. ii Cutting down on type checks and casts will decrease the amount of errors due to type mismatches. iii More errors are caught at compile time versus execution time when parameterized types are used. iv Generics make code reuse much easier. v Generics make our code type safe since we cut down on type casts and type checks. vi More bugs are found at compile time instead of run time when we use generics.

The syntax needed to dene a parameterized type in Java is; 179

access modif ier class GenericN ame < P arameters > { P arameters Constructors f unctions } To see get a better idea of what the layout of a generic class is look at 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 } Program 15.1: Data.java } public T getA () { T answer = this . a ; return answer ; public void setA ( T a ) { this . a = a ; } } public Data ( T a ) { this . a = a ; public class Data <T > { private T a ; (15.1)

180

Chapter 16

Collectors & Iterators

181

182

Chapter 17

Threads

183

184

Chapter 18

Basic GUI Input/Output

185

186

Chapter 19

UML Basics

187

You might also like