96
Object Oriented Programming - Lecture Notes MehmetGen¸cer Istanbul Bilgi University Department of Computer Science

OOP LectureNotes

Embed Size (px)

Citation preview

Page 1: OOP LectureNotes

Object Oriented Programming - Lecture Notes

Mehmet GencerIstanbul Bilgi University

Department of Computer Science

Page 2: OOP LectureNotes

Contents

Preface ii

1 Introduction 11.1 Functional/declarative vs imperative programming . . . . . . 11.2 Strictly typed languages . . . . . . . . . . . . . . . . . . . . . 21.3 Object orientation . . . . . . . . . . . . . . . . . . . . . . . . 31.4 Compiled vs interpreted languages . . . . . . . . . . . . . . . 41.5 Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

2 Introduction to imperative and strictly typed programmingin Java with Processing 62.1 Iteration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72.2 A note about data types . . . . . . . . . . . . . . . . . . . . . 82.3 Variable scopes . . . . . . . . . . . . . . . . . . . . . . . . . . 82.4 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92.5 Creating animations with Processing . . . . . . . . . . . . . . 92.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

3 Data types, variables, expressions and arithmetic, arrays,and iteration 113.1 Data types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113.2 Operators, expressions, and arithmetic . . . . . . . . . . . . . 123.3 Arrays and iteration . . . . . . . . . . . . . . . . . . . . . . . 133.4 Variables and reference types . . . . . . . . . . . . . . . . . . 153.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

4 Classes and Objects 174.1 Creating classes: types, objects, instances, and references . . . 18

4.1.1 Accessing state variables of an object: the . notation . 204.1.2 Using constructors . . . . . . . . . . . . . . . . . . . . 20

i

Page 3: OOP LectureNotes

CONTENTS ii

4.1.3 Using instance methods . . . . . . . . . . . . . . . . . 224.1.4 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . 23

4.2 Using class diagrams in class design . . . . . . . . . . . . . . . 234.3 Using DrScheme/ProfessorJ for non-graphical exercises . . . . 244.4 Garbage collection and object destructors . . . . . . . . . . . . 254.5 Creating three dimensional animations in Processing . . . . . 25

5 Classes, types, and objects 285.1 Class members versus object members . . . . . . . . . . . . . 29

5.1.1 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . 305.2 Reflection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

6 Using Industrial Grade Java Environments 326.0.1 Why the ‘static main()’ method? . . . . . . . . . . . . 34

6.1 Using Java libraries . . . . . . . . . . . . . . . . . . . . . . . . 356.2 Everpresent objects in JVM . . . . . . . . . . . . . . . . . . . 366.3 Interacting with the user . . . . . . . . . . . . . . . . . . . . . 366.4 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376.5 Handling errors in Java programs . . . . . . . . . . . . . . . . 376.6 Self documenting programs . . . . . . . . . . . . . . . . . . . . 39

6.6.1 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . 396.7 Profiling Java processes . . . . . . . . . . . . . . . . . . . . . . 39

7 Sub-classing and Inheritence 407.0.1 A note about the types . . . . . . . . . . . . . . . . . . 43

7.1 Scopes, disambiguation, and overloading . . . . . . . . . . . . 447.1.1 Overloading and overriding methods, method signatures 45

7.2 Abstract classes and methods . . . . . . . . . . . . . . . . . . 467.2.1 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . 47

7.3 An example of extending JDK classes: Graphical user interfaces 477.3.1 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . 49

8 Interfaces 518.1 Multiple interfaces (or why interfaces are better than abstract

classes) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 538.2 Mixing the mechanisms . . . . . . . . . . . . . . . . . . . . . . 53

8.2.1 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . 548.3 Example: Responsive GUI application . . . . . . . . . . . . . 54

Page 4: OOP LectureNotes

CONTENTS iii

9 Encapsulation and data safety in classes 589.0.1 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . 59

9.1 Nested and anonymous classes . . . . . . . . . . . . . . . . . . 59

10 Implementing data structures 6110.1 Self-references, mutual-references . . . . . . . . . . . . . . . . 61

10.1.1 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . 6310.2 Variable size data: implementing mutable lists . . . . . . . . . 64

11 Object serialization and persistence 6911.0.1 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . 71

11.1 Using Databases . . . . . . . . . . . . . . . . . . . . . . . . . 7111.1.1 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . 74

12 Java packages 7512.0.2 Distributing multi-file Java applications: jar archives . 81

A A guide for coding style 83A.1 Demarcation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83A.2 Organization . . . . . . . . . . . . . . . . . . . . . . . . . . . 85A.3 Explanation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86A.4 Explication . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87A.5 Naming conventions . . . . . . . . . . . . . . . . . . . . . . . . 88

Notes 89

References 89

Subject Index 89

Page 5: OOP LectureNotes

Preface

These lecture notes are unfinished work that is a collection of materials usedin Object Oriented Programming (OOP) undergraduate courses given tosecond year students at Istanbul Bilgi University’s Department of ComputerScience. Target audience were students who have learned essential functionalprogramming principles and practice using Scheme language. The OOPcourse aims to teach these students various aspects and practices of OOPusing the Java language. Due to such positioning the course aims to firstintroduce students to writing programs in an imperative and strictly typedlanguage like java, then proceeds to object oriented paradigm. Through theway we introducing them to tools and practices usable in industrial appli-cations, and underline relative strength and weaknesses of imperative/OOPfor different fields of applications.

The course syllabus for the actual courses these lecture notes are used forcan be found at http://cs.bilgi.edu.tr/~mgencer/coursemat/OOPsyllabus.pdf which provides information on detailed objectives and administrativematter. These notes are provided as a standalone introductory level docu-ment on object oriented programming for anyone interested.

iv

Page 6: OOP LectureNotes

Chapter 1

Introduction

The programming language, Java, which will be used for practicing con-cepts taught in this course shares some common features with other indus-trial grade programming technologies that are very popular today such asC/C++. The key features that distinguish these programming languagesfrom those such as Scheme and Lisp are that (1) they are typed or strictlytyped languages, (2) they are object oriented, (3) they are mostly used inimperative style programming, and (4) they are compiled rather than inter-preted. Before we start off with full blown examples of Java programs wemust explore these features.

1.1 Functional/declarative vs imperative pro-

gramming

Introducing computer science to programming using a functional program-ming language like Scheme is gaining popularity among instructors, and welljustified considering my experience with performance of those students inlater subjects during their education.

Functional programming falls under a generic category of approach whichis called the declarative approach in programming. In this style of program-ming, it is more natural for the programmer to code a computation into aprogram, once it is mathematically well established. Consider, for exam-ple, the problem of computing Fibonacci numbers1. The series of Fibonaccinumbers can be expressed as follows:

Fn =

{n if n = 0 or n = 1Fn−1 + Fn−2 if n > 1

1

Page 7: OOP LectureNotes

CHAPTER 1. INTRODUCTION 2

With the above mathematical definition in hand, it is quite straightforwardto express the computation as a Scheme program as follows:

Example: Fibonacci numbers in Scheme

(define (fibo n)

(cond [(<= n 1) n]

[else (+ (fibo (- n 1)) (fibo (- n 2)))]))

This approach is labeled as declarative programming since the program-mer expresses what needs to be computed (usually in a recursive manneras in the above example), rather than how to compute it (the imperativeway). As a result functional/declarative programs are easier to check forcorrectness.

While ease of code expression is and important advantage, especially inearly stages of programming education, there are certain motivations to seekother approaches. First is the fact that achieving computational efficiencymay not be possible with the most natural formulation of a computationwhen expressed as a declarative program. The Fibonacci numbers exampleabove is one example of inefficient code (see Exercise 1). While it is possibleto write an efficient program using declarative style and recursive algorithms(see Exercise 2), the mathematical formulation of this new program willno longer be trivial as the first one, hence undermining the advantage ofdeclarative programming in cases like this.

A second motivation for imperative programming is the fact that it is howcomputer hardware actually works. CPUs (Central Processing Units) simplyfollow a series of instructions. Languages such as C offer the advantage ofresembling more closely the underlying system they intend to control.

Programming languages like Java and C/C++ are not imperative them-selves. However, the programming practice of using these languages havebeen mostly in imperative style and the languages themselves has many fa-cilities that are targeted for such use, such as statements for iterations.

1.2 Strictly typed languages

In the above example of Fibonacci program there’s no indication that thefunction parameter must be an integer, nor is its return value. Thereforethe correct functioning of the system relies on passing of correct values tothe function. Many other languages are more sensitive to types of functionarguments and return values, and called ’strictly typed’ languages for this

Page 8: OOP LectureNotes

CHAPTER 1. INTRODUCTION 3

reason1. The following function definition is an example implementation ofrecursive -and inefficient- Fibonacci program in a strictly typed language:

Example: Fibonacci numbers in Java/C

int fibo(int n) {

if (n<=1)

return 1;

else

return fibo(n-1)+fibo(n-2);

}

The above code can pass as a function definition in both C and Javalanguages (as the latter was inspired by from the former heavily and usessimilar syntax). There are several differences compared to Scheme program:

• Functions are called with a syntax like ’fibo(5)’, not ’(fibo 5)’.

• ’cond’ is replaced by ’if’.

• Infix notation is preferred to prefix notation. i.e. ’n-1’, not (- n 1)’.

• Parantheses in Scheme is replaced by curly brackets.

• Each program statement ends with a ’;’.

• Instead of Scheme comments starting with ’;’, there are long (multi-line) comments between /* and */, and single line comments startingwith //.

• Most importantly both the function name and parameter is preceededwith ’int’ which indicates that they are of type integer.

Despite the syntactic differences the function outline resembles that of theScheme version.

1.3 Object orientation

Traditional computer programs look much like the computer itself. Theyare composed of ’functions’, which take some inputs and produce an output;much like basic circuit elements like AND,OR gates. The larger softwaresystem is an interconnection of inputs and outputs of such elements.

1Some languages like C are not as strict concerning types. However, this is generally adangerous preference and only remains to allow low level hacking of computer systems.

Page 9: OOP LectureNotes

CHAPTER 1. INTRODUCTION 4

While this aproach works for smaller systems, it caused many problemsas the applications of computer programs grow in variety and scale (See (?)for a good reading on these issues). Just like circuits, failure of one elementhas rendered the whole system malfunction. OOP came out as a practicalsolution to these problems. OOP is based on the concept of ’object’ , whichcorrespond to an actual entity in the problem one tries to program for. Theobject in OOP encapsulates all data of a certain type of object and functionsapplied to that data in programming units called ’classes’. Such way ofconceptually collecting data and functions related to that data is found toreduce programming errors in large software systems, in addition to beingeasier to design as things correspond to real entities.

Therefore in order to apply OOP, one needs programming languages thatsupport such mechanisms. Most modern programming languages today sup-port objects in one way or another. Various software tools are referred to inthe incremental treatment of the matter in this document.

1.4 Compiled vs interpreted languages

Some popular programming languages like Scheme, Lisp, Python, PHP, andPerl are all interpreted languages. One needs a special program called in-terpreter which runs the program written by the programmer. This has theadvantage that if one has an interpreter for different systems (e.g. Linux,Python, a cell phone) the same program can be used without any changes.

On the other hand this approach has some disadvantages. The interpreterprogram must spend a certain time parsing the program before it can be run(hence the word interpret). This brings a certain overhead to the system andinterpreted programming languages are generally slower than compiled lan-guages. In compiled languages the program is first passed through a specialprogram called the compiler which translates it to machine code which canbe directly executed by the hardware (i.e. the CPU). For example we can-not use an interpreted language to write an OS(operating system), becausethe OS is the first program to run on the hardware, hence there cannot bean interpreter already available there. Furthermore, compilers can have cer-tain advantages in terms of optimizing the outcome with respect to specificfeatures of the target hardware. Finally, compiled languages are preferredfor commercial programs since the original program cannot be recovered bylooking at the machine code which is delivered to the customers. Thereforean organization or person who seeks profit from a computer program cankeep the original code hidden as a private asset.

Java is somewhat distinct in the sense that it is both compiled and inter-

Page 10: OOP LectureNotes

CHAPTER 1. INTRODUCTION 5

preted. The Java compiler produces machine code for execution on not a spe-cific hardware but something called Java Virtual Machine (JVM). DifferentJVMs of varying capabilities are available for regular PCs, larger computers,cell phones, or chips used in credit cards. In this way Java retains the dualadvantages of portability and performance.

1.5 Resources

There are various Java programming and object oriented programming booksaround. However, this lecture notes are intended to go with a general purposeJava reference (such as ?) in addition to other material referenced in the text.

1.6 Exercises

1. Find the complexity, O(), of the Fibonacci program.

2. Write a Scheme program to compute Fibonacci numbers efficiently.

Page 11: OOP LectureNotes

Chapter 2

Introduction to imperative andstrictly typed programming inJava with Processing

Before we attempt writing Java programs for inductrial grade Java program-ming environments, in this chapter we will start by using Processing (seehtt://www.processing.org) to write simple programs that produce visualoutput. You can install Processing by downloading it from its website. Whenit is run you will see a screen where you can type your program, much similarto the way DrScheme works. Processing programs are Java programs, butProcessing allow us to postpone some cumbersome aspects of industrial gradejava environments and instead focus on imperative style programming in astrictly typed language. The Processing environment also have the advan-tage of having good quality reference and tutorial documentation in additionto examples.

In the screen of Processing system enter your first program as follows:Example: A first Processing program

/*Program to draw two lines of different thichnesses*/

void draw() {

strokeWeight(1); //set line thickness

line(0,0,50,100);// draw a line, eg. line(x1,y1,x2,y2)

strokeWeight(5);

line(50,100,100,50);

}

The special function name draw is used by the entry point to drawing bythe Processing system. Note that the return type of this function is void, ie.

6

Page 12: OOP LectureNotes

CHAPTER 2. INTRODUCTION TO IMPERATIVE AND STRICTLY TYPED PROGRAMMING IN JAVA WITH PROCESSING7

it does not return anything! This is typical of imperative style programmingthat the function is intended for its side effect, not its return value. What isdrawn by the function remains on the screen (and memory of the Processingsystem) but no return value is meaningful in this case. The remainder of linesstarting with a //, in addition to all text between /* and */ are commentsin the Java program.

It is possible to write Processing/Java programs using recursion. Thefollowing example draws a simple fractal shape:

Example: Recursive pattern

void draw() {

drawRecursive(0,0,0,90);

}

void drawRecursive(float x, float y, float angle, float length) {

if (length<=5) //stop drawing

return; //return from function, with nothing since return type is void

else{

float x2;

float y2;

x2=x+length*cos(angle);

y2=y+length*sin(angle);

line(x,y,x2,y2);

drawRecursive(x2,y2,angle+PI/2,length*0.9);

}

}

The above example demonstrates declaration of variables (e.g. “float x2”)and assignment of values to variables (using “=” operator), in addition tousing some trigonometric functions available in Processing. It also demon-strates use of conditional execution (the “if .. else” statement). In thisprogram the sequence of statements in the drawRecursive() function is exe-cuted one after the other. This is why such programs are called imperativebecause they impose how and through which steps a task must be executed,contrary to the Scheme Fibonacci program before.

2.1 Iteration

The contrast between declarative and imperative programming becomes morestriking if one uses iteration facilities to replace recursive calls. Following isa program to draw a similar fractal:

Page 13: OOP LectureNotes

CHAPTER 2. INTRODUCTION TO IMPERATIVE AND STRICTLY TYPED PROGRAMMING IN JAVA WITH PROCESSING8

Example: Using iteration

void draw() {

drawIterative(0,0,0,90);

}

void drawIterative(float x, float y, float angle, float length) {

float x1=x;

float y1=y;

float currentAngle=angle;

float currentLength=length;

while (currentLength>=5) {

float x2=x1+currentLength*cos(currentAngle);

float y2=y1+currentLength*sin(currentAngle);

line(x1,y1,x2,y2);

currentAngle=currentAngle+PI/2;

currentLength=currentLength*0.9;

x1=x2;

y1=y2;

}

}

The program uses the “while” statement which keeps executing the code(i.e. loops) in its brackets as far as the condition in the parenthesis is satisfied.In this example the importance of side effects for the working of the programare more apparent. The program relies on the fact that previous drawingpoint, angle and line segment length are stored in certain variables.

2.2 A note about data types

So far we have used two data types in Java: void and float. There arevarious other data types such as double, long, boolean, String, etc. You arerecommended to consult a reference documentation whenever necessary. Inthe future chapters we will have a closer look into data types.

2.3 Variable scopes

Note that among several variables declared in our iterative program some areinside the brackets that belong to the “while” statement. In Java variablescontinue to exists and keep whatever value you store in them until their

Page 14: OOP LectureNotes

CHAPTER 2. INTRODUCTION TO IMPERATIVE AND STRICTLY TYPED PROGRAMMING IN JAVA WITH PROCESSING9

scope vanishes/exits, and the scope is essentially determined by the enclosingbrackets. For example if there were any other statements after the whilestatement, it would not be possible to use x2 or y2 in those statementsbecause their scope has been exited and they have been sent to trash by theJava system. On the other hand variables x1 and x2 can be used in the scopeof the while loop in addition to the drawIterative() function, because theirscope (the brackets of the function) contains the scope of while loop.

2.4 Exercises

E-1 Write a Processing program to draw a Koch snowflake (search Googlefor this simple pattern).

E-2 Write a Processing program to draw a tree using a fractal approxima-tion.

2.5 Creating animations with Processing

What Processing system actually does is calling the draw() function you writerepetitively. Processing first calls a function named setup(), if available,and then calls the draw() function at a certain frequency. Let us write aProcessing program which declares a setup() function to setup screen sizeand animation rate, in addition to using global scope variables:

Example: Animated random lines

float x=0;

float y=0;

void setup() {

size(500,700);

frameRate(5);

}

void draw() {

//background(255);

float tmpx=x+random(10);

float tmpy=y+random(10);

line(x,y,tmpx,tmpy);

x=tmpx;

Page 15: OOP LectureNotes

CHAPTER 2. INTRODUCTION TO IMPERATIVE AND STRICTLY TYPED PROGRAMMING IN JAVA WITH PROCESSING10

y=tmpy;

}

In the above program the variables, x and y, are at the global scope,wheras tmpx and tmpy are within the scope of draw() function.

2.6 Exercises

E-3 Write a Processing program which animates a growing circle.

E-4 Write a Processing program to draw an analog clock on the screen. Youcan use hour(), minute(), and second() functions in Processing to learnthe time.

E-5 Write a Processing program to draw a fractal tree with random varia-tions for more realistic results.

Page 16: OOP LectureNotes

Chapter 3

Data types, variables,expressions and arithmetic,arrays, and iteration

As Java is a typed language, one needs to make informed use of data typesand know related operations, as different from programming in a languagelike Scheme where types are not explicit (although they exist). In this chapterwe will discover essential data types first, then learn how to create and uselists (so called arrays). An important technique in using arrays is iteration,which is a common and practical replacement for recursion when the numberof repetitions are known beforehand.

WE have already defined and used some variables. Java uses two kindsof variables where the difference is somewhat hidden from the programmer:primitive and reference type variables. WE will also explore the difference,which is an important topic you may encounter when using other program-ming languages.

3.1 Data types

An important motivation behind the use of types (in addition to type check-ing for programming errors) is to use memory efficiently. For this reasonJava has several data types that are used when creating variables or declar-ing function parameters and return types. We will first list the data typeswhich are called primitive data types in Java. :

• int: A 32-bit signed integer. This is the common choice for storingintegers unless there’s a reason not to do so.

11

Page 17: OOP LectureNotes

CHAPTER 3. DATA TYPES, VARIABLES, EXPRESSIONS AND ARITHMETIC, ARRAYS, AND ITERATION12

• byte: An 8-bit signed integer.

• short: A 16-bit signed integer.

• long: A 64-bit signed integer.

• float: A 32-bit floating point real number. Although this precision maybe sufficient for most purposes, you must consider using other types forfurther precision.

• double: A 64-bit floating point real number.

• boolean: A variable to store one of two values: true and false. Its sizein terms of bits is not specified in Java specifications.

• char: A single 16-bit Unicode character.

Please note that all primitive data type names start with a small case letter.This is an important convenience you need to remember to deal with theissues of reference type which we will cover later.

Declaring and using a primitive data type is quite straightforward. Forexample:

int n1;

int n_2;

n1 = 1;

n_2 = 25;

A variable name must start with a letter and can contain letters, digits, andthe underscore in its name. Other than these syntactic rules there are certainconventions in programming profession you should consider following. Theseare covered in Appendix A.

3.2 Operators, expressions, and arithmetic

It is possible to declare multiple variables of the same type on a single lineor assign a value during declaration as follows:

int n1=5;

float x1,x2=6,x3=7;

A variable can be assigned to the value of another variable or to result ofan arithmetic expression:

Page 18: OOP LectureNotes

CHAPTER 3. DATA TYPES, VARIABLES, EXPRESSIONS AND ARITHMETIC, ARRAYS, AND ITERATION13

int n1=5;

int n2=n1/2;

float x1=5.1;

float x2=(x1/2+1)/5;

In the above example note that the value 5/2 is not an integer. In such casesthe result is trucated. In certain cases you may want to cast type of a valueto something else using the new type in parenthesis. For example:

float x=5.1;

int n= (int)x/2;

In addition to arithmetic operator (+-/*), there is also a modulo operator(%) which evaluates to remainder.

Apart from numeric expressions, logical expressions can be constructed(for example in “if” statements) as in the following example:

if ( (x>5) && (x<=10) ) //true if x is greater than 5 AND less than or equal to 10

if ( (x<5) || !(x>10) ) // true if x is greater than 5 OR not greater than 10

if ( x%2 == 0) //true if x is even

if ( x%3 != 0) //true if x module 3 is not equal to zero

3.3 Arrays and iteration

A consequence of the fact that Java is strictly typed and tries to optimizememory usage is that lists in Java are also restricted in their size. If we wantto use a storage for many numbers (or other type of things) we must defineit to be of certain size. Such immutable, fized size lists are called ’arrays’ inJava (and in other strictly typed languages). Following syntax demonstrateshow an array to contain ten integer values is created and accessed:

int[] array;

array=new int[10];

array[0]=1;

..

array[9]=10;

As seen in the example, arrays are indexed started from 0, i.e the first elementof the array is at position 0. An array’s length can be learned by appending“.length” to its name, e.g. array.length evaluates to 10 in the above example.

Arrays of more than one dimension can be defined to store matrices asfollows:

Page 19: OOP LectureNotes

CHAPTER 3. DATA TYPES, VARIABLES, EXPRESSIONS AND ARITHMETIC, ARRAYS, AND ITERATION14

int[][] matrix=new int[5][10];

matrix[0][0]=1;

...

matrix[4][9]=50;

The size of such arrays are referenced similarly: e.g. matrix[0].length is10, whereas matrix.length is 5. In other words each of matrix[i] is actuallyan array of length 10. As a result following assignment is valid:

int[] row=matrix[0];

When using Scheme, you are accustomed to using recursive functions tospan a list of values. For example by recursing into tail of a list to find themaximum value in a list. Although the same is possible in Java, a convenientmechanism, called iteration, is commonly used to span a list whose size isknow (which is commonly the case). This is particularly true for arrays.

Following is an example function which returns the maximum of numbersin an integer array (note: array.length returns the size of array):

/*

* A function to find maximum of integers in an array

*/

int max(int[] array) {

int max=array[0];

for(int i=1; i<array.length; i=i+1) {

if (array[i]>max)

max=array[i];

}

return max;

}

The so called ’for’ loop syntax is as follows:

for (initialization; control; increment)

BODY

The initialization is done first. Then if the control expression is validatedthe BODY is executed. At the end increment part is done and control ex-pression is checked again. This loop continues until control expression is notvalid anymore. The BODY part of a for loop can be a single command as inthe above example, or a group of commands enclosed within brackets { and}. Although brackets are unnecessary for a single command, it neverthelessincreases readability of your programs and hence recommended.

Page 20: OOP LectureNotes

CHAPTER 3. DATA TYPES, VARIABLES, EXPRESSIONS AND ARITHMETIC, ARRAYS, AND ITERATION15

3.4 Variables and reference types

A second group of types in Java are so called Reference types. These areclosely related to classes and object as we will explore in the further chapters.A common reference type is “String”, which is used for storing pieces of text:

String message = "Hello Omer!";

System.out.println(message); //prints the string to terminal output

The important difference between reference and primitive data types re-lates to assignment and comparison operations. The key to understandingthe difference is that reference type variables are addresses (or so called refer-ences) of the actual value stored in memory, whereas primitive type variablesstore the actual value. For example:

int n1,n2;

n1=1;

n2=n1;

n1=2;

When the second statement above is executed the value of n1 is copied inton2. After the third statement the value of n1 is set to 2, however the valueof n2 remains the same and not affected. However when a similar thing isdone with a reference type like String:

String s1="abcdef";

String s2=s1;

s1="fedcba";

After the above statements are executed you will find that the values ofboth s1 and s2 are the same (e.g. try printing them as above). The reasonis that s1 and s2 are just two different names for the same variable in thememory. The assignment operator in the second statement above copies theaddress/reference of the first one to the second, not its value. You will finda similar result for all reference type variables in Java (such types all startwith a capital letter). For the same reason the following comparison will notyield to a true value:

String s1="abc";

String s2="abc";

if (s1=s2) // evaluates to false, because what is

// compared is the references, not values

We will learn how to compare strings after exploring classes, objects, andtheir methods.

Page 21: OOP LectureNotes

CHAPTER 3. DATA TYPES, VARIABLES, EXPRESSIONS AND ARITHMETIC, ARRAYS, AND ITERATION16

3.5 Exercises

E-1 Write a Processing program which animates 10 filled circles of differentcolor, each of which are centered on a random position, starts from a di-ameter of 10, grows into diameter of 100 as they are drawn repetitively,then returns to diameter 10 again.

E-2 Write a Processing program to draw the plot of a function, for examplef(x) = 20 + 2x− x2/10 + x3/100.

E-3 Write a Processing program to draw a Fibonacci spiral or Fibonaccitiling.

E-4 Write a Processing program which animates a growing fractal tree.

Page 22: OOP LectureNotes

Chapter 4

Classes and Objects

Consider an example problem to solve in Processing: We want to animate agroup of moving colored balls (i.e. circles in two dimensions for simplicity).Each ball has a different color, starting position and speed. In order to solvethis problem one will need to store colors, positions, and speeds of balls inthree different lists (in the same order so that information about a ball canbe reliably identified). After drawing balls in their current position in eachanimation frame, we will need to modify their positions according to theirspeed.

Following is a solution of the problem using techniques we have learnedso far:

Example: Growing balls problem

int numberOfCircles=10;

int sizeX=500, sizeY=700;

color[] colors=new color[numberOfCircles];

float[] posx=new float[numberOfCircles];

float[] posy=new float[numberOfCircles];

float[] radius=new float[numberOfCircles];

void setup() {

size(sizeX,sizeY);

for(int i=0;i<numberOfCircles;i=i+1) {

colors[i]=color(random(255));

posx[i]=random(sizeX);

posy[i]=random(sizeY);

radius[i]=10;

}

}

17

Page 23: OOP LectureNotes

CHAPTER 4. CLASSES AND OBJECTS 18

void draw() {

background(255); //white

for(int i=0;i<numberOfCircles;i=i+1) {

fill(colors[i]);

ellipse(posx[i], posy[i], radius[i]*2, radius[i]*2);

radius[i]=radius[i]+1;

if (radius[i]>100)

radius[i]=10;

}

}

The solution looks fine and works, although it is not very easy to read, sincethe data for balls and operations on the data are defined is different places.If one wants to make the circles start from a different radius, or change thegrowth threashold, one can see how the above approach becames less readable(and writeable!).

4.1 Creating classes: types, objects, instances,

and references

In OOP terminology objects are concrete examples of the class of things theybelong. The motivation for using classes and object oriented programminghas been to keep the data about an object and operations on that data closeto one another. A class consists of (1) state variables that define a particularobject (instance of the class), and (2) the behavior of the object expressedas methods (functions in a class) next to state variables.

Now we will start progressively defining our first class to represent agrowing ball in our problem. First we define t he class with state variablesonly:

class Ball {

float positionX;

float positionY;

float radius;

color ballColor;

}

The class definition collects properties of a ball (its position in two dimen-sional display, its radius, and color). You must remember that having a classdoes not mean that we have any objects. Defining a class in our programs

Page 24: OOP LectureNotes

CHAPTER 4. CLASSES AND OBJECTS 19

means creating a new variable type (which is similar to int, or float). Creat-ing objects mean that we need to create instances of the class. An instanceis a particular ball, not the general concept of ball, which has its particularvalues of the state variables.

Creating objects (which is also called as ‘instantiating a class’) is some-what different from creating variables of type int or float. Following is anexample of defining an object of a particular class type, and instantiating it:

Ball ball;

ball=new Ball();

The first line above defines a new variable of type ‘Ball’. However it isdifferent from defining a variable of type int. For int and other primitivetypes we can start using the variable (e.g. assigning a value to it) immediatelyafter defining the variable. On the contrary, for objects one needs to createan instance of the class using “new ClassName()” as we have seen in theabove example. This is due to the fact that objects are reference variables(like Strings) and are different from primitive types. For example considerthe Java statements below below:

Ball ball1,ball2;

ball1 = new Ball();

ball2= ball1;

In this example we have defined two variables of type Ball (in the first line),but we have created only one object (in the second line). The second variableis assigned to the value of first one (in the third line), but this assignmentdoes not create a copy of the object, as it does for int or float (or all primitivetypes). Instead it copies the reference to the object. As a consequence ball1and ball2 are just two names for the same object in Java’s memory. Youmust remember this distinction between primitive and reference types whenprogramming in Java.

As with primitive types, one can create arrays to store multiple objects.With our growing balls problem we can create the ten balls we need as inthe following Processing program:

class Ball {

...

}

Ball[] balls=new Ball[10];

void setup() {

Page 25: OOP LectureNotes

CHAPTER 4. CLASSES AND OBJECTS 20

for (int i=0; i<balls.length; i=i+1) {

balls[i] = new Ball();

}

}

4.1.1 Accessing state variables of an object: the . no-tation

Note in the above example that the state variables of the Ball object, ball1,has not been assigned any values. Variables of an object can be accessedusing a special notation as in the following example:

Ball ball;

ball=new Ball();

ball.positionX=120;

ball.positionY=ball.positionX;

In our particualar example of the growing balls problem, we will need toassign initial values to each ball as follows:

class Ball {

...

}

Ball[] balls=new Ball[10];

void setup() {

for (int i=0; i<balls.length; i=i+1) {

balls[i] = new Ball();

balls[i].positionX = random(500);

balls[i].positionY = random(700);

...

}

}

4.1.2 Using constructors

As we have mentioned earlier, the key advantage of using classes and objectsis to keep object’s state variables and actions that pertain to these variablesclose to one another. Therefore the above example of initializing a Ball’sstate variables is inadequate. In all object oriented languages it is possibleto define a special method called ’constructor’ which is used for initializing

Page 26: OOP LectureNotes

CHAPTER 4. CLASSES AND OBJECTS 21

state variables. Constructor method must have the same name with theclass, and is different from other Java functions in one sense that they do nothave a return type. If a class has a constructor then the cosntructor methodis executed automatically when an instance of the class is created using astatement like “new ClassName()”.

In our particular example our constructor will need to know the size ofthe display so that ball position can be selected randomly within the screen.The modified class definition will look like the following:

class Ball {

float positionX;

float positionY;

float radius;

color ballColor;

Ball(int screenSizeX, int screenSizeY) {

positionX=random(screenSizeX);

positionY=random(screenSizeY);

radius=10;

ballColor=color(random(255),random(255),random(255));

}

}

Now if we want to create objects of this class, we will need to provide therequired parameters during its instantiation, as follows:

Ball ball=new Ball(500,700);

With the latest version of our class, it is possible to write parts of theProcessing program in a more simple and understandable way:

class Ball {

...

}

Ball[] balls=new Ball[10];

void setup() {

for (int i=0; i<balls.length; i=i+1) {

balls[i] = new Ball(sizeX, sizeY);

}

}

Page 27: OOP LectureNotes

CHAPTER 4. CLASSES AND OBJECTS 22

4.1.3 Using instance methods

We are only halfway through our definition of the Ball class. Unless the classhave methods to control its behavior (ie. growing), it is incomplete.

Class methods are function defined inside the scope of the class. Theyare like any other function in the sense that they have a return type and aparameter list. The only difference is that since they are in the same scopewith state variables of the object, these variables are accessible from theinstance methods. Similarly the methods can access one another as they arein the same scope. Following is a complete version of our Ball class:

class Ball {

float positionX;

float positionY;

float radius;

color ballColor;

Ball(int screenSizeX, int screenSizeY) {

positionX=random(screenSizeX);

positionY=random(screenSizeY);

radius=10;

ballColor=color(random(255),random(255),random(255));

}

void growAndPaint() {

radius=radius+1;

if (radius>100)

radius=10;

fill(ballColor);

ellipse(positionX, positionY, radius*2, radius*2);

}

float area() {

return PI*radius*radius;

}

}

Note that we have added a class method to compute area of the Ball as anexample of methods with return type, although it was not necessary for ourparticualr problem in hand.

With this class definition in hand, our Processing program becomes muchsimpler and understandable:

Page 28: OOP LectureNotes

CHAPTER 4. CLASSES AND OBJECTS 23

class Ball {

...

}

Ball[] balls=new Ball[10];

void setup() {

size(sizeX, sizeY);

for (int i=0; i<balls.length; i=i+1) {

balls[i] = new Ball(sizeX, sizeY);

}

}

void draw() {

background(255);

for (int i=0; i<balls.length; i=i+1) {

balls[i].growAndPaint();

}

}

4.1.4 Exercises

E-1 Write a Processing program which animates several rectangles (theirnumber is random between 5 and 15), of random position and color,which grow/shrink in width/height alternatively.

E-2 Write a Processing program which animates moving balls, which startwith random positions, radius, and speed, then move around the screenand bounce from the sides.

E-3 Write a class to represent a complex number. The class must have aconstructor method, and a method to compute magnitude (or so calledabsolute value) of the complex number. Assume that a method named’sqrt()’ is available for taking square root of a number.

4.2 Using class diagrams in class design

The real potential of using objects in large scale software applications comesfrom the fact that objects in OOP correspond to real objects, and theirinteraction resemble actual interaction of entities in the system, rather than

Page 29: OOP LectureNotes

CHAPTER 4. CLASSES AND OBJECTS 24

a clockwork modeling of reality that functional programming dictates (whichis actually useful in small scale).

This potential can be turned to actual advantage if OOP mechanisms areused within object oriented design (OOD) principles. The key element indesign is deciding what properties and behavior of objects in a system willbe like before actually writing the code for them. This practice provides what’contracts’ do in PLT style Scheme programming.

A common practice in object oriented design is starting off with so calledclass diagrams. Following is an example class diagram for what is expectedto be a representation of Complex numbers:

----------------------------------------

| Complex |

----------------------------------------

| float real |

| float imaginary |

|---------------------------------------

| Complex(float real, float imaginary) |

| float magnitude() |

| float getReal() |

| float getImag() |

----------------------------------------

The class diagram is a very concise summary of properties and methodsof the class. Now if we want to write a method to multiply two complex num-bers we know how to access its properties, before even the class is actuallycoded! This is an important advantage in industrial software development,because once it is decided how several classes will allow access to their meth-ods and properties to create a useful system, different programmers can takeeach class and implement them. The collection of class diagrams provide aconceptual guide for those involved in creating the software system.

4.3 Using DrScheme/ProfessorJ for non-graphical

exercises

Processing system is useful for graphical exercises, but is limiting for othertypes of programming. DrScheme program, to which students may be famil-iar from Scheme programming, has recently released with facilities to use itfor Java programming. This extension called ProfessorJ takes us one stepcloser to using industrial grade Java environments.

Page 30: OOP LectureNotes

CHAPTER 4. CLASSES AND OBJECTS 25

After running DrScheme, choose Java+dynamic as the language of study.Then in the DrScheme’s main area you can enter your class definition. Theconsole below the main area can be used to create instances of your class,and then to invoke its methods for testing. For the purposes of this course,we will not cover the testing facilities for Java programs.

Try using DrScheme for solving the Complex number implementationexercise above.

4.4 Garbage collection and object destruc-

tors

Notice that we have not done anything to destroy objects we have created.When there is no reference available for an object or when its scope is de-stroyed, the Java garbage collector takes care of cleaning them. For examplethe code below:

Circle c1=new Circle(100);

c1=new Circle(200);

leaves the first circle inaccessible. Java keeps track of the references to ob-jects, and takes care of cleaning the memory for objects which there’s noway of referencing them again. In general we have no control over when orhow often the garbage collection takes place. This have some consequencesfor real time programming using Java, but in general it is of no concern toprogrammers except such cases where instantenous performance is critical.

When an object is destroyed by the garbage collector, the instance methodcalled finalize(), if available, is called. This method is called the destructor,as it is the opposite of constructor.

4.5 Creating three dimensional animations in

Processing

3D animation is an advanced topic in Processing. Nevertheless we provide asmall example of it below, which uses a modified version of the Ball class andsetup() function. Pleas enote that a library is necessary to use 3d drawing(see following chapters for importing libraries). Furthermore one needs toturn on the lights and use trandformations for 3D drawing. Please referto Processing reference documentation to explore the 3D drawing facilitiesfurther.

The key elements of drawing can be simplified as follows:

Page 31: OOP LectureNotes

CHAPTER 4. CLASSES AND OBJECTS 26

• It is easier to draw 3D shapes as if one draws them at the center ofcoordinate axes. For this reason one needs to transform the coordinatesystems as desired. This consists of pushMatrix() and transform() op-erations. Once a 3D shape (e.g. sphere) is drawn, one can resume thecoordinate system using popMatrix().

• Ligths needs to be reset at every drawing, thus the lights() commandmust be placed in the draw() function.

Following program draws growing spheres at random locations in the 3Dspace, uses default ambient lighting.

import processing.opengl.*;

class Ball {

float positionX;

float positionY;

float positionZ;

float radius;

color ballColor;

Ball(int screenSizeX, int screenSizeY, int screenSizeZ) {

positionX=random(screenSizeX);

positionY=random(screenSizeY);

positionZ=random(screenSizeZ);

radius=10;

ballColor=color(random(255),random(255),random(255));

}

void growAndPaint() {

radius=radius+1;

if (radius>100)

radius=10;

fill(ballColor);

pushMatrix();

translate(positionX, positionY,positionZ);

//ellipse(positionX, positionY, radius*2, radius*2);

sphere(radius*2);

popMatrix();

}

float area() {

Page 32: OOP LectureNotes

CHAPTER 4. CLASSES AND OBJECTS 27

return PI*radius*radius;

}

}

int sizeX=500, sizeY=700, sizeZ=500;

Ball[] balls=new Ball[10];

void setup() {

size(sizeX, sizeY,P3D);

for (int i=0; i<balls.length; i=i+1) {

balls[i] = new Ball(sizeX, sizeY,sizeZ);

}

}

void draw() {

background(255);

lights();

for (int i=0; i<balls.length; i=i+1) {

balls[i].growAndPaint();

}

}

Page 33: OOP LectureNotes

Chapter 5

Classes, types, and objects

You may have already noticed that variables which are objects (class in-stances) are defined similar to primitive type variables. For example:

int x=2;

Ball b=new Ball();

Also remember that the two variables are different: the first is a primitivetype variable which holds the value we assign to it, whereas the second is areference type variable which holds the reference of the class instance.

Despite these differences the declaration syntax demonstrates that thenew class we have defined, Ball, becomes a data type in Java. The newvariable, b, in the above example is of this new type. Therefore, creatingclasses in Java means adding new data types to the language.

The types are important in a strictly typed language like Java, becausea variable of certain type can be assigned a value of the same type only. Forexample the following statement will cause an error in Java:

Ball b=3;

if ("abc">4) ...

Because we are trying to assign an integer value to a variable of type Ball, orcompare a string to a number! Java is quite strict about matching types inassignment or comparison operations. Nevertheless, it will allow automaticconversion between numeric types (e.g. from float to int) in most cases.

What is more interesting when using classes is that a class itself is avariable, of type class! Remember that a class definition starts as “class Ball...”. This has important consequences when programming in Java, becauseone must learn the difference between a class (which is an entity of type‘class’), and its instances (which are of type the class itself). Therefore a

28

Page 34: OOP LectureNotes

CHAPTER 5. CLASSES, TYPES, AND OBJECTS 29

class is an entity of type class, but it is special in the sense that it creates anew type in Java.

More important in this matter is that one must learn to differentiatethings which belong to a class, and things which belong to instances. Thisis perhaps one of the most stumbling points for students learning Java.

5.1 Class members versus object members

So far we have only used instances of classes. Therefore classes provided asa template for creating objects. However Java provides certain mechanismsfor classes to have variables of methods of their own. This is done to savememory or speed up method invocation.

For example consider a class to represent Circles, and to provide methodsto compute its area and circumference.

class Circle {

double radius;

double PI=3.14;

Circle(double radius) {

this.radius=radius;

}

double area() {

return PI*radius*radius;

}

}

With the above code, a copy of PI constant will be stored in computer mem-ory for each instance of the class. Instead of doing so, we can define thePI variable as a class variable using ’static’ keyword : public static doublePI=3.14; This reduces the amount of memory to store variables by 50%! Thestatic members of a class can be accessed without creating an object instancefrom class: eg. just Circle.PI.

In some cases, the static mechanism can be used for methods also. Forexample if we want to implement a group of functions to operate on naturalnumbers:

class NaturalNumberMethods {

static int factorial(int n) {

if (n<=1)

return 1;

else

Page 35: OOP LectureNotes

CHAPTER 5. CLASSES, TYPES, AND OBJECTS 30

return n*factorial(n-1);

}

static int fibonacci(int n) {...}

}

Note that the class has no constructor, because it will neve be instantiated!It is just used as a container of methods and has no object specific state.Therefore the methods are accessed directly via classes: eg. NaturalNum-berMethods.factorial(5).

You must keep in mind that although static and non-static membersare mixed in the class code, they are worlds apart. Static methods cannotreference object variables or use this keyword. For example if we opt to makearea() method of the Circle class above as static, it would not work, since itreferences the object variable ’radius’.

Mixing static and non-static methods is rather counter-intuitive in objectorientation (unlike rare cases as in the example above with static PI variable),although it is syntactically possible.

5.1.1 Exercises

E-4 Create a class which has collection of methods for complex numberarithmetic, in addition to being able to represent a complex number.The class must have methods for addition, substraction, and multipli-cation of complex numbers. Note that each of these methods consumetwo arguments of type Complex (e.g. you class in part (i)), and returnsa new instance of Complex.

E-5 Improve the Complex class in DrScheme/ProfessorJ, so that it keepstrack of how many instances of the Complex is created, and how manyinstances are alive. Use a static counter to count instances, and usethe destructor to detect how many instances are alive.

5.2 Reflection

Since a class is like any other object in Java it is possible to inspect itsmembers, such as class methods. This is called reflection in Java. Since itis an advanced topic we do not cover reflection in this course. The curiousreaders are recomended to consult Reference documentation of the Classclass, and consult relevant tutorial lessons at java.sun.com website.

Classes and methods can be passed around and inspected as other Javaentities. It is possible to inspect classes and objects using a group of reflection

Page 36: OOP LectureNotes

CHAPTER 5. CLASSES, TYPES, AND OBJECTS 31

tools in Sun JDK. Following is a demonstration of these mechanisms. Pleaserefer to http://java.sun.com/developer/technicalArticles/ALT/Reflection/index.htmlfor an extensive review.

class A{

A() {}

String summary() {

return String.format("This is an instance of %s",

this.getClass().getName());

}

}

class B{

B() {}

String summary() {

return String.format("This is an instance of %s\n And it has a different summary.",

this.getClass().getName());

}

}

class CFN {

static void main(String[] args) {

String input=System.console().readLine("Enter class name : ");

try {

Class c=Class.forName(input);

I x=(I)(c.getConstructors()[0].newInstance());

System.out.println(x.summary());

} catch (Exception e) { System.out.println(e);}

}

}

Page 37: OOP LectureNotes

Chapter 6

Using Industrial Grade JavaEnvironments

Among descriptions of programming languages you will hear the terms ‘com-piled’ and ‘interpreted’. Compiled languages are those such as C and assem-bler, which take the program code you write and run it through a programcalled the compiler to produce the so called ’executable’ which can be di-rectly understood (i.e. interpreted) by the computer’s CPU. On the otherhand ‘interpreted’ languages has no such intermediate conversion, but insteadthe program code is interpreted by the program called interpreter.

Each system has its advantages. In compiled languages the end user willneed the executable suitable for the hardware architecture(type of CPU andoperating system) they have, in order to run your program. However withthe advantage that the executable is optimized for the CPU. In the caseof interpreted languages, on the other hand, end users need an interpreterfor their architecture, but besides that can run the same program code onany architecture. Interpreted languages are somewhat more convenient, butcompiled languages usually result in faster running programs1.

Java was designed to have best of both worlds. It is both a compiledand an interpreted language. To run a Java program one must first run itthrough the Java compiler to produce the Java bytecode (the equivalent ofexecutable). However, unlike C executable, Java bytecode is not intendedto be interpreted directly by the CPU+operating system, but rather by aninterpreter called the Java Virtual Machine (JVM). Although this may seemunnecessarily complicated, this design of Java resulted in excellent portabil-ity2 which Java owes its success. The JVM isolates Java software from the

1For two reasons: (i)that since the code is already parsed, and (ii)compilers have theadvantage of using CPU specific optimizations.

2Portability is the ability of a computer program to work on different types of hardware

32

Page 38: OOP LectureNotes

CHAPTER 6. USING INDUSTRIAL GRADE JAVA ENVIRONMENTS33

specifics of hardware and operating system. Because of this isolation Javais extremely ‘safe’. For example a JVM that works inside your web browserprovides the system for programs called Java applets. Since this JVM iso-lates the applet from the rest of your computer, they are safe to run and doesnot carry any risks. Also it has been possible to create JVMs -with reducedcapabilities- for very small devices such as cell phones or credit card chips sothat they can run Java programs.

One of the most commonly used Java systems comes from Sun Microsys-tems, the designers of Java language. It is free to download Sun JavaSDK(system development kit) which includes the compiler, the JVM, andmany libraries you can use when writing programs. Many other systemsare available such as commercial systems from Borland and IBM, or pub-lic licensed ones from GNU. If you are using a GNU/Linux system such asUbuntu, you should be able to install Sun Java SDK on your system byrunning the following commands to install necessary packages:

aptitude install sun-java6-jdk

aptitude install sun-java6-jre

aptitude install sun-java6-plugin

First package installs Java compiler and libraries. The second installs theJVM. And the third enables your web browser to run Java applets.

A simple type of Java program that we create using such systems isconsole based applications which does not have a graphical user interface.The industrial grade Java systems mentioned above use the same templateto create such an application. Following is a piece of code that resemblesJava Hello World applcation you will see in the first pages of many Javabooks and online tutorials:

/**

* A simple Java console based application

* @author Mehmet Gencer

*/

public class HelloWorld {

public static void main (String[] arguments) {

System.out.println("Hello user!");

if (arguments.length>0) {

System.out.println("You have run this program with the following arguments:");

for(int i=0; i< arguments.length; i=i+1)

System.out.println(arguments[i]);

and operating systems.

Page 39: OOP LectureNotes

CHAPTER 6. USING INDUSTRIAL GRADE JAVA ENVIRONMENTS34

}

}

}

Save the code above in a file named “HelloWorld.java”. The file and theclass must have the same name! Then compile as below:

javac HelloWorld.java

If you see no error messages, you must have a new file named HelloWorld.class. That is the file containing compiled bytecode. You can now run it as follows:

java HelloWorld

If you give command line arguments\mymark{command line arguments}, you will see the program reporting them back:

java HelloWorld a1 a2 a3

Hello user!

You have run this program with the following arguments:

a1

a2

a3

In summary, the requirements for having a console based Java application istherefore having a public class which has the same name with the file, andhaving a public and static method named main within that class. This is verymuch like setup() and draw() methods in Processing, the main() method iswhere Java will start executing your program. Please note that we have notcreated an instance of the HelloWorld class! Instead JVM invokes its staticmethod to execute our application. The command line arguments we giveto the program are passed by the JVM as an array of strings to the main()method.

The statement which starts with System.out demonstrates an exampleof interacting with the user, which we will explore further in the followingsections.

6.0.1 Why the ‘static main()’ method?

When a Java program first starts, all it knows are the classes imported fromlibraries (the next section) and classes defined by the user. There are noobjects (except some everpresent obejcts, see the next section below). Forthis reason it is imperative that the entry method for the Java programsmust be a static method! It is just a common convenience that all JVMimplementations look for a class method (i.e. static method) named mainas the starting point of the programs. This is much like the convenience ofhaving setup() and draw() methods in PRocessing system.

Page 40: OOP LectureNotes

CHAPTER 6. USING INDUSTRIAL GRADE JAVA ENVIRONMENTS35

6.1 Using Java libraries

Sun Java SDK comes in with a rich set of libraries you can use in yourproograms. These range from mathematical facilities, to libraries for process-ing image or sound files. A reference documentation of all Sun JDK libraries(generated using javadoc) can be found at http://java.sun.com/javase/6/docs/api/.

In order to use a library in your program, you must first tell Java to’import’ the library. To demonstrate these mechanisms we will now tryto create a program which ask the user to enter numbers and finds theirsquareroot. For this application we will need the Math library to computesquareroots. Following is the program code:

import java.lang.Math;

public class RootFinder {

public static void main(String[] arguments) {

String input;

do {

input=System.console().readLine("Enter a number : ");

if (input.length()>0) {

double number=Double.parseDouble(input);

double numberRoot=Math.sqrt(number);

System.out.println(numberRoot);

}

} while (input.length()>0);

System.out.println("Goodbye!");

}

}

The first line imports the Math library. After that we can use the methodsin the library with a syntax such as ‘Math.sqrt()’. You can imagine that thislibrary is like the complex number class we have created, which is composed ofstatic methods. For getting input from user we call System.console() whichreturns an object suitable for reading from the console by its readLine()method. But this method returns a string type value, so we must convert itto a real number using Double.parseDouble() method.

Some classes we have used in the above program such as Double are built-in, we did not need to import anything to use them. However for the Mathclass we needed to import it.

The import mechanism is necessary in Java to control capabilities of thesystem and bytecode size. For example in Java Mobile, which is a JVM that

Page 41: OOP LectureNotes

CHAPTER 6. USING INDUSTRIAL GRADE JAVA ENVIRONMENTS36

works on cellular phones, or Java Micro, which works on much smaller devicessuch as credit card chips, some (most!) libraries wouldn’t be available.

java.sun.com provides the reference documentation for all essential ob-jects in Java SDK, and for those that come in its standard libraries. Whenwriting programs you will often need to consult the reference documenta-tion. Make sure you use the appropriate version of the documentation. Youcan learn the version of the Java SDK you are using by invoking the javaccommand with ‘-version’ option.

6.2 Everpresent objects in JVM

One special object, named System, exists when a Java program is startedexecution in tje JVM. The System object represents the operating systemenvironment surrounding the JVM and allows one to access system propertiesor interact with the user using the system console in which the program runs.

You are advised to read Java reference documentation of the System classto learn full features it provides.

6.3 Interacting with the user

One of the uses of System object is to print messages to the user console,or read input from it. The programs above have already demonstrated someuses such as ‘System.out.println(...)’ statement. The ‘in’ and ‘out’ membersof the System object are rather crude channels representing input from andoutput to user console. A more convenient way of interacting with userthrough the console is to obtain and use the Console object from the System,which has more convenient methods to do these things. The console can beused as in the following examples:

import java.io.Console;

...

String s=System.console().readLine("Enter some string please:");

...

String name="Mehmet";

int grade=50;

System.console().format("Hello Mr. %s, your grade is %d", name, grade);

Page 42: OOP LectureNotes

CHAPTER 6. USING INDUSTRIAL GRADE JAVA ENVIRONMENTS37

6.4 Exercises

E-1 Write a Java program which prints all System properties on the consoleoutput.

E-2 Write a Java console application which takes an integer number ascommand line argument and reports its factorial. (Hint: use Inte-ger.parseInt(some string) to convert a command line argument to aninteger number.)

E-3 Write a Java console application reads strings from the user and printsthem in reversed form. (Hint: read the Java reference documentationof the String class)

E-4 Write a Java program which computes Fibonacci number for large n,using BigInteger class from java.util library.

6.5 Handling errors in Java programs

Many unexpected errors may occur, especially when your program uses uncheckedinput from user of files. In many cases where an error (‘exception’ in Javaparlance) is possible, Java compiler will warn you. But proper error han-dling, still relies on programmer skills. Following program demonstrates howexception handling mechanisms can be used in a program which expects anumber from the user and reports its factorial. If the number cannot beproperly converted to integer, program will report the error.

public class Exceptions {

static int factorial (int n) {

if (n==1)

return 1;

else

return n*factorial(n-1);

}

public static void main(String[] args) {

String input=System.console().readLine("Enter a number : ");

int n;

try {

n=Integer.parseInt(input);

System.out.println(factorial(n));

} catch (NumberFormatException e) {

System.out.println("You have mistyped the number.");

Page 43: OOP LectureNotes

CHAPTER 6. USING INDUSTRIAL GRADE JAVA ENVIRONMENTS38

}

}

}

The new mechanism in the program is the “try .. catch..” block. Whichwill try to execute the command block and if an exception occurs, it willtake prescribed steps in the catch block corresponding to the exception type.There are several predefined exceptions in Java, and ’NumberFormatExcep-tion’ is one of them. For a list of Java predefined exceptions, and a detailed re-view of exception mechanisms see http://java.sun.com/docs/books/tutorial/essential/exceptions/index.html.

Try running the above program, first provide a valid positive integer,then type something dummy to see NumberFormatException. And finallygive it a negative number, which will cause a runtime problem which cannotbe captured by any catch block. To prevent this last problem, we have toredefine our factorial method so that it will deny carrying out the calculationfor an invalid value:

public class Exceptions {

static int factorial (int n) throws Exception {

if (n<=0)

throw new Exception("Negative value given!");

if (n==1)

return 1;

else

return n*factorial(n-1);

}

public static void main(String[] args) {

String input=System.console().readLine("Enter a number : ");

int n;

try {

n=Integer.parseInt(input);

System.out.println(factorial(n));

} catch (NumberFormatException e) {

System.out.println("You have mistyped the number");

} catch (Exception e) {

System.out.println("Unexpected error:");

System.out.println(e);

e.printStackTrace();

}

}

Page 44: OOP LectureNotes

CHAPTER 6. USING INDUSTRIAL GRADE JAVA ENVIRONMENTS39

}

In this version, the function definition declares that it potentially causes(throws)an exception of a certain type. The generic ’Exception’ type is the root ofall exceptions. Also in this version we have used more than one catch block,which are chosen by Java according to the type of exception that occurs.The second catch block will catch any exception which is not catched bythe previous one, and also uses the exception instance to print out detailedinformation about the error.

6.6 Self documenting programs

Java SDK comes with several useful tools. One of them, javadoc, is used forcreating HTML documentation from your code comments. Try the followingcommand:

javadoc HelloWorld.java

It will produce a file named index.html. Open the file in a web browser andsee how it allows you to browse your classes and methods. For each class,method, or class variable, javadoc uses your comments which immediatelyprecede the definition of class or method, or variable.

6.6.1 Exercises

E-5 Explore the javadoc manual page and find out how to include authorinformation in the generated documentation.

6.7 Profiling Java processes

Even if one is very careful, certain programming mistakes can lead to pro-grams which suffer from bad performance. In such situations use of a profilingtool can prove very useful. Recent versions of the Sun Java SDK comes withone such tool called jvisualvm. Using this tool, one can examine proper-ties of live Java processes and JVMs, such as their memory usage, or where(which methods) the program spends its time. You are recommended to usethis or similar tools to solve performance problems which you cannot figureout the reason by looking at your -potentially large- program code.

Page 45: OOP LectureNotes

Chapter 7

Sub-classing and Inheritence

So far all the classes we have created stand on their own (except for mutualreferences). In many cases, however, we need mechanisms to avoid coderepetition, and facilitate class access. A typical such case is when multiplesub-classes are needed to represent classes of objects that have many similaraspects, yet have their own peculiarities.

Consider the case of different type of resources in the library. Differentinformation needs to be kept for books and journals, yet some other infor-mation such as whether the resource is in the library or borrowed, its callnumber, etc., are common to two types. For such cases, Java (and other ob-ject oriented languages) offers the inheritence mechanism to solve the prob-lem, so that all class members (variables and methods) can be inherited andextended by sub-classes. In the library example we first define the Resourceclass to represent aspects common to all resource types:

|--------------------------------------|

| Resource |

|--------------------------------------|

| String callID |

| String title |

| boolean isBorrowed |

|--------------------------------------|

| Resource(String callID, String title)|

| String summary() |

| void borrowed() |

| void returned() |

|--------------------------------------|

We have included a summary() method in our class so that it can report theitem to users, and two other methods to use when the resource is borrowed

40

Page 46: OOP LectureNotes

CHAPTER 7. SUB-CLASSING AND INHERITENCE 41

and returned. Following is a Java console program which implements theclass and creates a few instances to experiment with it:

class Resource {

String callID;

String title;

boolean isBorrowed;

Resource(String callID, String title) {

this.callID=callID;

this.title=title;

isBorrowed=false;

}

String summary() {

String summary;

if (isBorrowed)

summary=String.format("Call ID: %s \nTitle: %s\n not in library.",callID,title);

else

summary=String.format("Call ID: %s \nTitle: %s\n in library.",callID,title);

return summary;

}

void borrowed() { isBorrowed=true;}

void returned() { isBorrowed=false;}

}

public class Library {

public static void main(String[] arguments) {

Resource[] resources=new Resource[3];

resources[0]=new Resource("QA76.1","Euclid’s geometry");

resources[1]=new Resource("QA73.2","Literate programming");

resources[2]=new Resource("QA73.3","Origin of the species");

resources[0].borrowed();

for (int i=0; i<resources.length; i=i+1)

System.out.println(resources[i].summary());

}

}

When we want specific types of resources such as books and journals, adifficulty arises. For books we need the author information in addition tovariables of the Resource class. For the journals on the other hand we don’thave author information, but instead we need the issue number. At thispoint we will use the sub-classing mechanism. The Book and Journal classeswill be sub-classes of the Resource class. They ‘inherit’ all variables and

Page 47: OOP LectureNotes

CHAPTER 7. SUB-CLASSING AND INHERITENCE 42

methods, and extend it instead of re-implementing everything. Following isa Java console program using this method:

class Resource {

String callID;

String title;

boolean isBorrowed;

Resource(String callID, String title) {

this.callID=callID;

this.title=title;

isBorrowed=false;

}

String summary() {

String summary;

if (isBorrowed)

summary=String.format("Call ID: %s \n Title: %s\n not in library.",callID,title);

else

summary=String.format("Call ID: %s \n Title: %s\n in library.",callID,title);

return summary;

}

void borrowed() { isBorrowed=true;}

void returned() { isBorrowed=false;}

}

class Book extends Resource {

String author;

Book(String callID, String title, String author) {

super(callID,title);

this.author=author;

}

String summary() {

return super.summary()+String.format("\n Author: %s",author);

}

}

class Journal extends Resource {

String issue;

Journal(String callID, String title, String issue) {

super(callID,title);

this.issue=issue;

}

Page 48: OOP LectureNotes

CHAPTER 7. SUB-CLASSING AND INHERITENCE 43

String summary() {

return super.summary()+String.format("\n Issue: %s",issue);

}

}

public class Library {

public static void main(String[] arguments) {

Resource[] resources=new Resource[3];

resources[0]=new Resource("QA76.1","Euclid’s geometry");

resources[1]=new Journal("QA73.2","ACM Transactions","March 2007");

resources[2]=new Book("QA73.3","Origin of the species","Charles Darwin");

resources[0].borrowed();

for (int i=0; i<resources.length; i=i+1)

System.out.println(resources[i].summary());

}

}

Let’s go over the new mechanisms in this program one by one:

• The Book and Journal classes are declared to ’extends’ the Resourceclass. They add new object variables such as author or issue.

• In the constructors of sub-classes, the constructor of the super-class(Resource) is invoked using ’super()’

• Both classes ’override’ the summary() method, but when implementingit use the summary method of the superclass using super.summary().

• In the main() method of the program, instances of Book and Journalclasses are accepted as instances of Resource class. Book and Journalclasses are considered as types that are compatible with the Resourcetype.

7.0.1 A note about the types

Note that the array in the example program above is an array of Resourcetype, although its contents are instances of different classes (Journal, Book,etc.). In Java (and most object oriented languages), an instance of a sub-class passes as an instance of its super-class. THis is because the sub-classhas everything the super-class has. We will see a similar type compatibilitywhen we use interfaces in the following chapters.

Page 49: OOP LectureNotes

CHAPTER 7. SUB-CLASSING AND INHERITENCE 44

7.1 Scopes, disambiguation, and overloading

As we have mentioned in Chapter 3 each variable or method defined hasa scope within which it can be used. In Processing it was possible to usevariables at the global scope (i.e. not inside any brackets). However whenusing industrial grade java environments, each variable or method must beinside a class, or its methods.

When a variable is defined at the class level, it is accessible from everymember method of the class. However you must remember that static mem-bers of a class are different fron those that are not. Since non-stati membersbelong to objects (class instances) and not to the class itself, you cannot,for example, use non-static variables or methods from within static methods.For example paarts of the the following code will cause an error:

class C {

int n=0;

static int s=0;

void getn() {

return n; //OK

}

void gets() {

return s; //OK

}

static void get2n() {

return n; //ERROR!!

}

}

Remember that although it is syntactically correct to access static variablesfrom non-static methods, one must be very careful when doing so, becausewhat is changed is the single copy of variable that is inside the class, notsome variable that is peculiar to the instance.

In certain situations a variable can become unreachable although it is inthe scope. Consider the following example:

class C {

int n;

C(int n) {

n=n; // ??? WHICH n WE ARE TALKING ABOUT ?

}

}

Page 50: OOP LectureNotes

CHAPTER 7. SUB-CLASSING AND INHERITENCE 45

Since the method parameter is in an inner scope, it shadows the variable inthe higher scope. In the above situation, one can use the special variable,‘this’, to refer to the class instance (ie. disambiguate the reference) as follows:

class C {

int n;

C(int n) {

this.n=n; // ??? WHICH n WE ARE TALKING ABOUT ?

}

}

A similar problem is possible when a sub-class defines a variable ormethod which shadows the member of super-class in a similar manner. Thisis also the same problem when one needs to call the constructor of a super-class. One can use the special variable ‘super’ to refer to the super-class insuch situations. For example.

class C {

int n;

...

}

class C2 extends C {

int n; //SHADOWS THE SUPER-CLASS VARIABLE

void f() {

n=super.n;

}

C2() {

super(); //CALLS SUPER-CLASS’ CONSTRUCTOR

...

}

}

7.1.1 Overloading and overriding methods, method sig-natures

In the example above the meaning of having a constructor for a sub-class isactually overriding the construtor of the super-class. Because when the classis instantiated, the constuctor method invoked will be that of the sub-class,hence the constuctor of the super-class is overridden. Similar would be thecase if a sub-class re-defines any of the super-class methods.

In some cases it is necessary to allow different types of constuctors fora class. For example consider that we want to create a class to represent

Page 51: OOP LectureNotes

CHAPTER 7. SUB-CLASSING AND INHERITENCE 46

a circle. We may want to allow the user to choose the coordinates and/orsize of the circle, or if he/shee chooses they will be randomly assigned. Thefollowing class which defines multiple constructors does this:

-----------------------------------------|

| Circle |

-----------------------------------------|

| float r, x, y; |

-----------------------------------------|

| Circle(); |

| Circle(float radius); |

| Circle(float radius, float x, float y);|

|----------------------------------------

class Circle {

float r, x, y;

Circle() {

r=random(100);

x=random(300);

y=random(400);

}

Circle(float radius) {

r=radius;

x=random(300);

y=random(400);

}

...

}

Although the three constructor methods all have the same name, Java willhave no problem in choosing which one to invoke, because the given param-eters to constuctor can help choosing which method to invoke. This is saidas that the methods have different signatures (i.e. different parameter lists).This method of defining multiple methods with the same name but differentparameter lists is called method overloading. It is particularly useful for classconstructors, but nevertheless can be used for any class method.

7.2 Abstract classes and methods

A mechanism that can be used when implementing a group of related classesis the abstract classes and abstract methods. For example consider that we

Page 52: OOP LectureNotes

CHAPTER 7. SUB-CLASSING AND INHERITENCE 47

want to implement uni-dimensional shapes such as circles, squares, and equi-lateral triangles. We know that all have a single dimension to be specifiedwhen constructed, but methods for drawing them or computing their circum-ferences are different. In such a case we can use a semi-implemented classwhich has some abstract methods as follows:

abstract class Shape {

float size;

Shape(float size) { this.size=size;}

abstract float circumference();

}

Since some methods are abstract (and thus the class is incomplete), it isnot allowed to create instances of this class. Instead we have to create classeswhich extend it and implement these methods:

class Circle extends Shape {

float circumference() { return PI*size*size;}

}

class Square extends Shape {

float circumference() { return 4*size;}

}

Note that we had to implement only the abstract methods in our sub-classes

7.2.1 Exercises

E-1 Consider that we want to implement different types of shapes in Pro-cessing. Use the abstract class mechanism to implement circles andsquares in the program.

7.3 An example of extending JDK classes:

Graphical user interfaces

Java’s original popularity was largely due to graphical capabilities of JavaApplets, which are Java programs that can run within a web page. Sun JavaSDK not only have tools for creating applets but also provides libraries tocreate industrial grade graphical user interfaces. This section provides only ashort peek into these capabilities. Please visit http://java.sun.com/applets/for extensive tutorials.

Page 53: OOP LectureNotes

CHAPTER 7. SUB-CLASSING AND INHERITENCE 48

An applet is designed to be displayed within an HTML page. Followingis a simple applet and the HTML page to display it:

import javax.swing.JApplet;

import java.awt.*;

import java.util.*;

public class SimpleApplet extends JApplet {

Date timestamp;

public void init() {

timestamp=new Date(); //current time

}

public void paint(Graphics g) {

g.drawLine(0,0,this.getSize().width,this.getSize().height);

g.drawString(timestamp.toString(), 5, 15);

g.drawString(new Date().toString(), 5, 35);

}

}

The class in the applet program extends the Applet class of JDK. The HTMLpage for displaying the applet is as follows:

<html>

<body>

<p> My little applet:</p>

<applet code="SimpleApplet" width=400 height=400>

</body>

</html>

If you first compile the Java program and then display the HTML page ina browser you will see the applet simply drawing a diagonal line. note thatthe HTML page and the Java class file must be in the same directory sincethe HTML ‘applet’ tag indicates the code resides in the same directory.

Applets have a limited use these days, but GUI applications are com-monplace. Following is a standalone Java application which demonstrateshow similar GUI libraries is used in standalone applications. It dows exactlywhat the applet above does, but this time in a window of its own:

import javax.swing.*;

import java.awt.*;

class BasicApplication {

static GUI gui;

static JFrame mywindow;

public static void main(String[] args) {

Page 54: OOP LectureNotes

CHAPTER 7. SUB-CLASSING AND INHERITENCE 49

gui=new GUI();

mywindow = new JFrame("My window");

mywindow.setSize(200, 300);

mywindow.add(gui);

mywindow.setVisible(true);

}

}

class GUI extends JPanel {

JButton button;

GUI () {

button=new JButton("Click here");

add(button);

}

public void paintComponent(Graphics g) {

g.drawLine(0,0,100,100);

}

}

You can run the above application like any other JDk application, withthe difference that it will display a GUI window. The application uses libraryclasses from Java Advanced Windowing Toolkit (AWT) and its newer, andricher cousing Swing. A Java GUI application has a JFrame as its window. Awindow frame may include a Panel (the main area), toolbars, and menus. Ourlittle application uses only a panel, and places a clickable button on the panel.The panel itself is a drawable area much like the applet window. Our class,GUI, which extends the JPanel class has a method names paintComponent()which is called at the beginning to populate the content of the applicationwindow.

7.3.1 Exercises

E-2 Interesting fractal shapes can be produced using quadratic Julia setson the complex numbers plane. A quadratic function is one whichis iterated as zn+1 = z2

n + c, where c is a complex constant. TheJulia set corresponding to c is the set of points z0 which when theiteration does not approach infinity. Write a JDK application whichcan read c from the user and draws the Julia set on the screen (e.g.by visualizing which points around the center of the complex planebelong to Julia set). Usually choosing a color based on how fast thefunction converges at a given point gives nicer looking results than

Page 55: OOP LectureNotes

CHAPTER 7. SUB-CLASSING AND INHERITENCE 50

monochromatic visualizations.

Page 56: OOP LectureNotes

Chapter 8

Interfaces

A different type of problem arises when several classes are only similar interms of behavior. For example consider shapes such as circles and rectanglesin a drawing. All shapes will need to have methods to draw them, or computetheir area. But other than this commonality, they share nothing. Drawing acircle or computing its area is not similar to doing the same for a rectangle.Therefore having a basic Shape class and extending it will not help us at all.On the other hand we certainly need to convenience of treating all shapes inthe drawing similarly, as we have done in the main() method of our libarayapplication above. Books and Journals could both be treated as resources,and stored in the same array. In this chapter we will learn a mechanism whichis a better alternative to abstract classes and methods we have learned before.

A new mechanism, based on interfaces, is used for solving problems likethe one in the shapes example. What we need to do is to design an interfacewhich declares what methods an abiding class must have. Afterwards whenwe create different classes, we declare them as implementing the interface, sothat they can be treated similarly (i.e. they are compatible types).

We will implement this example in Processing. Following is our program:

Shape[] shapes=new Shape[3];

void setup() {

size(500,500);

shapes[0]=new Circle(50,100,100);

shapes[1]=new Rectangle(50,70,200,300);

shapes[2]=new Rectangle(100,70,300,400);

}

void draw() {

51

Page 57: OOP LectureNotes

CHAPTER 8. INTERFACES 52

for (int i=0; i<shapes.length; i=i+1)

shapes[i].draw();

}

interface Shape{

void draw();

float area();

}

class Circle implements Shape {

float radius;

float posX,posY;

Circle(float radius, float posX, float posY) {

this.radius=radius;

this.posX=posX;

this.posY=posY;

}

void draw() {

ellipse(posX,posY,radius*2,radius*2);

}

float area() { return PI*radius*radius;}

}

class Rectangle implements Shape {

float a,b;

float posX,posY;

Rectangle(float a, float b, float posX, float posY) {

this.a=a;

this.b=b;

this.posX=posX;

this.posY=posY;

}

void draw(){

rect(posX,posY,a,b);

}

float area() { return a*b;}

}

Note that similar to the sub-classing method, classes that implementShape interface are accepted as instances of Shape. Thus we are able tostore shapes that are instances of different classes in an array of type Shape.

Page 58: OOP LectureNotes

CHAPTER 8. INTERFACES 53

8.1 Multiple interfaces (or why interfaces are

better than abstract classes)

A shortcoming -or rather a design preference- in Java is lack of polymorphism,i.e. a class can not be a sub-class of more than one class. However, intrfacesdoes not have this limitation. A class can extend only one claass but canimplement as many interfaces as desired.

For example consider in the shapes example above that there are shapesthat can move. We can represent the behavioral blueprint of moving shapesin the following interface:

interface MovingShape {

void moveTo(float newX, float newY);

}

Now we can redefine our Circle class to implement both interfaces:

class Circle implements Shape, MovingShape {

...

void moveTo(float newX, float newY) {

this.posX=newX;

this.posY=newY;

}

}

This new class can pass as an instance of both Shape and MovingShape.

8.2 Mixing the mechanisms

It is perfectly possible to use a mix of sub-classing, interfaces and abstractclasses to implement a problem. Consider that we want to implement someuni-dimensional shapes which can also be moved in a coordinate system.Following is one possible solution to the problem:

interface MovingShape {

void moveTo(float newX, float newY);

}

abstract class UnidimensionalMovingShape implements MovingShape {

float size, posX, posY;

UnidimensionalMovingShape(float size, float posX, float posX) {

this.size=size;

this.posX=posX;

this.posY=posY;

Page 59: OOP LectureNotes

CHAPTER 8. INTERFACES 54

}

void moveTo(float newX, float newY) {

this.posX=newX;

this.posY=newY;

}

abstract float circumference();

}

class Circle extends UnidimensionalMovingShape {

float circumference() {

return PI*size*size;

}

}

8.2.1 Exercises

E-1 Consider the different types of resources in a University library. Writean interface to represent the behavior of these resources.

E-2 Consider a size limited buffer to store integers. Write an interface torepresent operations on such a buffer. Make two implementations forfirst-in-first-out and last-in-last-out buffers.

8.3 Example: Responsive GUI application

Note that the button in our previous GUI application application was notresponsive, nor it was shut down when the window is closed. To add thiscapability we need to use several additional libraries. Following is an ap-plication which does a more complex work and also can sense button clicksand mouse location. The application will keep drawing a connnected seriesof lines as you click on its screen:

import javax.swing.*;

import java.awt.*;

import java.awt.geom.*;

import java.awt.event.*;

import java.util.*;

import javax.swing.event.*;

class BasicApplicationReactive {

static GUI gui;

static JFrame mywindow;

Page 60: OOP LectureNotes

CHAPTER 8. INTERFACES 55

public static void main(String[] args) {

gui=new GUI();

mywindow = new JFrame("My Application");

mywindow.setSize(200, 300);

mywindow.add(gui);

mywindow.setVisible(true);

mywindow.addWindowListener(new MyWindowAdapter());

}

}

class GUI extends JPanel {

JButton button;

int x,y;

LinkedList<Line2D.Double> lines;

GUI () {

x=0;

y=0;

lines=new LinkedList();

button=new JButton("Click here to reset");

button.setActionCommand("click");

button.addActionListener(new MyActionListener(this));

add(button);

addMouseListener(new MyMouseListener(this));

}

public void paintComponent(Graphics g) {

g.clearRect(0,0,getSize().width,getSize().height);

for (int i=0;i<lines.size();i+=1)

((Graphics2D)g).draw(lines.get(i));

}

void moveTo(int newx, int newy) {

lines.add(new Line2D.Double(this.x,this.y,newx,newy));

this.x=newx;

this.y=newy;

this.repaint();

}

void reset(){

lines=new LinkedList();

getGraphics().clearRect(0,0,getSize().width,getSize().height);

}

}

Page 61: OOP LectureNotes

CHAPTER 8. INTERFACES 56

class MyWindowAdapter extends WindowAdapter {

public void windowClosing(WindowEvent event) {

System.exit(0);

}

}

class MyActionListener implements ActionListener {

GUI gui;

MyActionListener(GUI gui) {

this.gui=gui;

}

public void actionPerformed(ActionEvent e) {

if (e.getActionCommand().equals("click"))

gui.reset();

}

}

class MyMouseListener extends MouseInputAdapter {

GUI gui;

MyMouseListener(GUI gui) {

this.gui=gui;

}

public void mouseClicked(MouseEvent e) {

int newx=e.getX();

int newy=e.getY();

gui.moveTo(newx,newy);

}

}

The application introduces several additions to handle different kinds ofevents:

Window events Events caused by user actions such as minimizing, maxi-mizing, or closing the window (JFrame).

Actions Events caused by clicking buttons, menu or toolbar items.

Mouse events Any other mouse click inside the application window (panel).

In this modified version, the GUI class implements ActionListener inter-face (from java.awt.event library) itself, so that it can respond to buttonclick. On the other hand, seperate classes are used for the other two eventtypes. The MyWindowAdapter is needed by the window (Frame) level only,thus it is added to the main window by addWindowListener() method of

Page 62: OOP LectureNotes

CHAPTER 8. INTERFACES 57

JFrame. On the other hand mouse clicks in the drawing area are capturedby MyMouseListener class, which is attached to the Panel as its mouse eventlistener, by addMouseListener() method of JPanel. The button click is iden-tified by first setting the action command at the beginning after JButtoninstance is created, then looking for the identification string as action eventsarrive.

This version of the application maintains a list of lines (Line2d.Doubleclass instances) and adds new lines extending to the point where user clicksthe mouse. The button click will reset the lines list. Use of Line2d.Doubleclass imposed the necessity to type cast Graphics to Graphics2D which canmanage instances of this class. The mix of these classes is a result of historicaldevelopment of JDK GUI libraries. At some point AWT development wasceased, and new classed were started to be developed as a part of Swinglibrary.

There are -seemingly- less painful ways of designing Java GUIs. The Net-Beans IDE (Integrated Development Environment) from Sun Microsystemsis one free software which can be used for designing GUIs by dragging anddropping visual elements to application window.

Page 63: OOP LectureNotes

Chapter 9

Encapsulation and data safetyin classes

You have probably noticed that the classes in the previous section containedvariable and method modifiers such as ‘public’. This access modifier is oneof several that allows us to control how a class member can be accessed.

Let’s first see the motivations for access control in classes. Consider aclass as follows to represent a circle:

class Circle{

float radius;

Circle(float radius) {

this.radius=radius;

}

}

Now we can create a circle and later set its radius:

Circle c=new Circle(5);

c.radius=-5;

The assignment above is a mistake, but not a syntax error. The programwill work and it is upon us to figure out something is wrong with the circlewhich has a negative radius! We must take control of how radius is set anddoes not allow invalid values. This requirement is an essential motivation forso called Model-View-Control (MVC) concept in many programming tasks.

Java provides a mechanism to disallow access to class variables (and ac-tually methods, as we will see later). The private and public modifiersallow us to describe the level of access. By default everything is non-private,but it is a good exercise to make things explicit. The new class is as follows:

58

Page 64: OOP LectureNotes

CHAPTER 9. ENCAPSULATION AND DATA SAFETY IN CLASSES59

class Circle{

private float radius;

public Circle(float radius) {

this.radius=radius;

}

public getRadius() { return radius; }

public setRadius(float newRadius) {

if (newRadius>0)

radius=newRadius;

}

}

With the definition above, any attempt to access radius of a circle directlyis prohibited. The following line will produce an error:

c.radius=5; //ERROR at compilation

Following is a summary of the consequences of using access modifiers onaccessibility of elements:

Modifier Class Package Subclass Worldpublic Y Y Y Yprotected Y Y Y Nno modifier Y Y N Nprivate Y N N N

NOTE: Where making encapsulation explicit whereever possible is therecommended practice, we omit doing so in most examples below to makethem easier to read.

9.0.1 Exercises

E-1 Write a class to represent a bank account. The account should havevariables to store account holder’s name, access password, and amountof money in the account, and have methods to withdraw money if thecorrect password is given.

9.1 Nested and anonymous classes

Not all classes need to be at the global scope, it is possible to define a classwithin anothre class, for example to avoid its use beyond that:

class Outer {

...

Page 65: OOP LectureNotes

CHAPTER 9. ENCAPSULATION AND DATA SAFETY IN CLASSES60

private class Inner {

...

}

Inner i;

In a different way, one may wish to use a class which is not used anywhereexcept one point in the program. In such cases it is possible to define ananoynymous class as follows:

class C {

void someMethod(java.util.Enumeration) {

...

}

...

someMethod(new java.util.Enumeration() {

public boolean hasMoreElements() { ... }

public Object nextElement() { ... }

});

Note that an anonymous class has not name and it can only be defined asextending a class or implementing an interface.

Page 66: OOP LectureNotes

Chapter 10

Implementing data structures

10.1 Self-references, mutual-references

We have seen that classes have variables to keep data about objects. Thereis no limitation that prevents us having a variable whose type is a classwe create, or even the class it is defined within. For example consider theproblem of representing the sales in a shop. There will be many sales duringthe day and we don’t know how many. Thus using a fixed size array is nota suitable solution. A way of overcoming the problem is to store a chain ofsales (a linked list), in which each sale points to the next, and the last onepoints to nothing:

class Sale{

float amount;

Sale next;

Sale(float amount) {

this.amount=amount;

next=null;

}

}

What we have done is called ’self-referencing’ since on of class variablesis of the type class itself. We left the variable having a value of null since wedo not know its value before another sale is created. However we can have asecond constructor for cases we want to support values for both variables:

class Sale{

float amount;

Sale next;

Sale(float amount) {

61

Page 67: OOP LectureNotes

CHAPTER 10. IMPLEMENTING DATA STRUCTURES 62

this.amount=amount;

next=null;

}

Sale(float amount, Sale next) {

this.amount=amount;

this.next=next;

}

}

What we have done is called method overloading, as we have multiple def-initions for the same method. Since two definitions have different argumentlists, Java can choose one depending on how we instantiate the class.

Following is an example piece of code to enter a few sale operations intoa system using the class above:

Sale lastSale=null;

lastSale=new Sale(100);

lastSale=new Sale(200,lastSale);

In other situations we may have more than one class in our programs whichare somehow related. For example consider that we want to store who soldwhat when we keep sale records in the above example. It is apparent thatwe will have a class to represent salesman. Let’s first draw

the class diagram for this system:

|-----------------------------| |---------------------------|

| Sale | |Salesman |

|-----------------------------| |---------------------------|

|float amount |<--|Sale saleChain |

|Sale next | |String name |

|Salesman sm |-->|---------------------------|

|-----------------------------| |Salesman(String name) |

|Sale(float amount) | |void addSale(float amount) |

|Sale(float amount,Salesman sm) |---------------------------|

|Sale(float amount,Salesman sm,

| Sale next) |

|-----------------------------|

Note how we used arrows to indicate mutual referencing between the twoclasses. The class diagrams present a complete view which allows manipu-lating the system. Now we can proceed to write the two classes.

class Sale{

Page 68: OOP LectureNotes

CHAPTER 10. IMPLEMENTING DATA STRUCTURES 63

float amount;

Sale next;

Salesman sm;

Sale(float amount) {

this.amount=amount;

next=null;

sm=null;

}

Sale(float amount, Salesman sm) {

this.amount=amount;

this.sm=sm;

next=null;

}

Sale(float amount, Sale next, Salesman sm) {

this.amount=amount;

this.sm=sm;

this.next=next;

}

}

class Salesman {

Sale saleChain;

String name;

Salesman(String name) {

this.name=name;

}

void addSale(float amount){

saleChain=new Sale(amount,saleChain,this);

}

}

Now we can enter sales for different salesperson:

Salesman sp1=new Salesman("ali");

Salesman sp2=new Salesman("ayse");

sp1.addSale(100);

sp2.addSale(200);

(See ? for a more detailed discussion on self and mutual references)

10.1.1 Exercises

E-1 Add a method to Salesman class which finds total amount of sales bythe salesperson.

Page 69: OOP LectureNotes

CHAPTER 10. IMPLEMENTING DATA STRUCTURES 64

E-2 We want to represent books in the library and their authors using Javaclasses. For books we want to store book title and author of the book.For authors we want to store their name. Create class diagrams forboth classes.

E-3 Implement a stack of integers which provide methods for pushing andpopping values from the stack, and returning the size of stack. If thestack is empty, simply return 0 when one attempts to pop a value.

10.2 Variable size data: implementing muta-

ble lists

When the amount of entities to be stored are not known in advance, im-mutable lists (Java arrays) are not much useful. A common remedy is usinga linked list, in which each item knows the reference of the next item, thusforming a chain. Such a self-referential class for storing integers would be asfollows:

class IntegerList {

int n;

IntegerList next;

...

}

Obviously one would need methods to add, remove, or access elements ofthe list. Linked lists vary according to how elements are added and removed(e.g. stacks, queues, sorted lists, etc.). Following program demonstrates howa stack can be implemented:

class ListItem {

int n;

ListItem next;

ListItem(int n) {

this.n=n;

next=null;

}

ListItem(int n, ListItem next) {

this.n=n;

this.next=next;

}

}

Page 70: OOP LectureNotes

CHAPTER 10. IMPLEMENTING DATA STRUCTURES 65

class IntegerStack {

ListItem header;

IntegerStack() {

header=null;

}

void push(int n) {

header=new ListItem(n, header);

}

int pop() {

ListItem retval=header;

header=header.next;

return retval.n;

}

boolean isEmpty() {

if (header==null)

return true;

else

return false;

}

}

public class Stack {

public static void main (String[] args) {

IntegerStack stack=new IntegerStack();

stack.push(1);

stack.push(2);

while (!stack.isEmpty())

System.out.println(stack.pop());

}

}

Linked lists are very commonly used and Java SDK provides librariesto avoid implementing the above functionality each time a mutable list isneeded. Following program has the same functionality with the above oneusing LinkedList class from java.util library:

import java.util.*;

public class JavaList {

public static void main(String[] args) {

LinkedList stack=new LinkedList();

stack.push(1);

stack.push(2);

Page 71: OOP LectureNotes

CHAPTER 10. IMPLEMENTING DATA STRUCTURES 66

while (!stack.isEmpty())

System.out.println(stack.pop());

}

}

The LinkedList implementation aditionally offers exporting the data asan array, which comes handy in some cases.

Since the LinkedList stored the generic Object type, its use may in-volve typecasting in most cases beyond our simple integer list. To avoidthis LinkedList variables can be declared to hold a specific type as in thefollowing example: LinkedList¡String¿ list;

Example: Books and authors Consider an application to store informa-tion about books in a library and their authors. Each book will have morethan author, and each author is releated to several books. Also the amountof books in the library is subject to change. Following is a solution to theproblem:

import java.util.*;

class Author {

String name;

LinkedList<Book> books;

Author(String name) {

this.name=name;

books=new LinkedList();

}

void addBook(Book book) {

books.add(book);

}

void printSummary() {

System.out.println(name);

for (int i=0; i<books.size();i=i+1)

System.out.println(String.format(" %s",books.get(i).title));

}

}

class Book {

String title;

LinkedList<Author> authors;

Book(String title) {

this.title=title;

authors=new LinkedList();

Page 72: OOP LectureNotes

CHAPTER 10. IMPLEMENTING DATA STRUCTURES 67

}

void addAuthor(Author author) {

authors.add(author);

}

void printSummary() {

System.out.println(title);

for (int i=0; i<authors.size();i=i+1)

System.out.println(

String.format(" author: %s",authors.get(i).name));

}

}

public class Library {

/**

* Find author in the authors list and return. Return null if

* author is not in the list.

*/

static Author findAuthor(LinkedList<Author> authors, String name) {

for (int i=0; i<authors.size(); i=i+1)

//Note that string comparison is different from primitive types

if (authors.get(i).name.equals(name))

return authors.get(i);

return null;

}

public static void main(String[] args) {

LinkedList<Author> authors=new LinkedList();

LinkedList<Book> books=new LinkedList();

String title;

do { //loop to enter books

title=System.console().readLine(

"Enter the book title (or empty to finish) : ");

if (!title.equals("")) {

Book book=new Book(title);

String authorName;

do { // loop to enter authors of a book

authorName=System.console().readLine(

"Enter the author name (or empty to finish) : ");

if (!authorName.equals("")) {

//first check if author already exists

Author author=findAuthor(authors, authorName);

if (author==null){ //author does not exist, create it

author=new Author(authorName);

Page 73: OOP LectureNotes

CHAPTER 10. IMPLEMENTING DATA STRUCTURES 68

authors.add(author);

}

book.addAuthor(author);

author.addBook(book);

}

}while(!authorName.equals(""));

books.add(book);

}

} while (!title.equals(""));

System.out.println("BOOKS IN THE LIBRARY");

for(int i=0; i<books.size();i=i+1)

books.get(i).printSummary();

System.out.println("AUTHORS IN THE LIBRARY");

for(int i=0; i<authors.size();i=i+1)

authors.get(i).printSummary();

}

}

Page 74: OOP LectureNotes

Chapter 11

Object serialization andpersistence

An object that resides in the memory of JVM can be serialized, i.e. turnedinto a sequence of bytes from which the object can be recovered in its stateat the time of serialization. The possibility of serializing objects have manyadvantages such as the ability to store them in a file to be later recovered,or transferring them over the Internet to another JVM in another computer(e.g. in e-business). The only requirement for a Java class to be serializableis to implement the interface called ‘Serializable’, which requires no methodsto be implemented. Any object which is an instance of a class implementingSerializable interface can be given to an ObjectOutputStream instance (fromjava.io library) to be written out. The following example demonstrates howthe serialization can be invoked on a LinkedList which already implementsSerializable interface:

import java.io.*;

import java.util.*;

class Serialize {

public static void main(String[] args) {

LinkedList list=new LinkedList();

list.add(1);

list.add(2);

try {

ObjectOutputStream so = new ObjectOutputStream(System.out);

so.writeObject(list);

} catch (IOException e) {

System.out.println("Problem writing object");

System.out.println(e);

69

Page 75: OOP LectureNotes

CHAPTER 11. OBJECT SERIALIZATION AND PERSISTENCE 70

}

}

}

The serialized form printed on the screen by the above program is notreadable. However it is only intented to be read by Java de-serialization.

The following demonstrates how to persist serialized objects which areinstances of our classes into a file. When the program is first run, it willstore an object in the file “myobj”, and in later runs of the program it willrecover the object instead of creating a new one. Try running the programmore than once.

import java.io.*;

class TimeChecker implements Serializable{

long time;

TimeChecker () {

this.time=System.currentTimeMillis();

}

long getTime() {

return this.time;

}

}

class PersistenceExample {

public static void main(String[] args) {

TimeChecker tc;

//de-serialize object if the file exists, create new one otherwise

try {

FileInputStream file = new FileInputStream("myobj");

ObjectInputStream si = new ObjectInputStream(file);

tc = (TimeChecker) si.readObject();

file.close();

} catch(Exception e) {

System.out.println("No file is found. I will use a new object");

tc = new TimeChecker();

}

System.console().format("Object time is %d%n",tc.getTime());

try {

FileOutputStream fileout = new FileOutputStream("myobj");

Page 76: OOP LectureNotes

CHAPTER 11. OBJECT SERIALIZATION AND PERSISTENCE 71

ObjectOutputStream so = new ObjectOutputStream(fileout);

so.writeObject(tc);

so.close();

} catch(Exception e) {

System.out.println("Cannot write out");

}

}

}

We must note that the Java program which de-serializes the object musthave the class definition of the object which is being deserialized, otherwisethe class of the object cannot be identified. This is not a problem when theobject is an instance of a standard Java class such as the LinkedList, but itmatters for our own classes.

11.0.1 Exercises

E-1 Improve the library example above so that the books and authors listswill be persisted before program exits.

11.1 Using Databases

Many database engines provide Java libraries. Here we cover the SQLiteembedded database as an example since it requires little configuration over-head. However for large scale, high performance applications more capabledatabase engines, such as PostGreSQL or Oracle, are recommended.

Information on SQLite can be found at http://www.sqlite.org/. The Javalibrary used for this tutorial comes from http://www.zentus.com/sqlitejdbc/.Download the .jar file containing the library and keep it where either (i) yourwant to keep your source files, or (ii) inside the lib subdirectory of your JavaJDK.

From an application programmer’s perspective all relational databasesare somewhat similar since -almost- all use the Standard Query Language(SQL) for access and manipulation. When using a database one may cre-ate/destroy tables, add/delete/update or select records from these tables. Itis possible to do all these operations using either (i) user interface programsthat comes with the database which access the database directly (or indi-rectly or remotely, depending on the multi-tier structure and complexity ofthe database engine), or (ii) by writing programs which access the databaseusing available libraries.

Page 77: OOP LectureNotes

CHAPTER 11. OBJECT SERIALIZATION AND PERSISTENCE 72

In the case of most high-performance, industrial grade database engines,access to database is controlled by a running process called the databaseengine. The engine makes sure that all access to database is properly autho-rized (usually using a fine grained access control mechanism) and also thatno accidents happen when there are multiple concurrent accesses. HoweverSQLite is simply an embedded database, and it does not have such an enginethat is always up and running and keeping the gates. Instead an SQLitedatabase is simply a file and any process who have access to this file havefull access to the database. When one application is using the database itis locked and cannot be modified by another application. Therefore, as anembedded database, SQLite lacks many features in both fronts. But it isnevertheless practical and have a good performance, making it a simple andeffective solution for some type of applications.

Despite these differences writing database programs are similar and JavaSDK provides certain common aspects of database access already, except theimplementations themselves. As other database systems, SQLite also usesthe standard Java DataBase Connectivity layer (JDBC) and java standardedition SDK’s java.sql library. Following program demonstrates SQLite usagefrom Java:

/**

* SQLite Java library usage example. Adopted from http://www.zentus.com/sqlitejdbc/

*/

import java.sql.*;

import org.sqlite.JDBC;

class SQLiteExample {

public static void main(String[] args) throws Exception {

new JDBC(); //initialize the SQLite JDBC system so that the database

// descriptor in the next line is usable

Connection conn = DriverManager.getConnection("jdbc:sqlite:test.db");

Statement stat = conn.createStatement();

stat.executeUpdate("drop table if exists people;");

stat.executeUpdate("create table people (name, occupation);");

PreparedStatement prep = conn.prepareStatement(

"insert into people values (?, ?);");

prep.setString(1, "Gandhi");

prep.setString(2, "politics");

prep.addBatch();

prep.setString(1, "Turing");

prep.setString(2, "computers");

prep.addBatch();

Page 78: OOP LectureNotes

CHAPTER 11. OBJECT SERIALIZATION AND PERSISTENCE 73

prep.setString(1, "Wittgenstein");

prep.setString(2, "smartypants");

prep.addBatch();

conn.setAutoCommit(false);

prep.executeBatch();

conn.setAutoCommit(true);

ResultSet rs = stat.executeQuery("select * from people;");

while (rs.next()) {

System.out.println("name = " + rs.getString("name"));

System.out.println("job = " + rs.getString("occupation"));

}

rs.close();

conn.close();

}

}

To compile the above program you need to specify where the SQLite Javalibrary is located. For example if the library (.jar file) is in the same directorywith the program, compile it as follows: javac -cp sqlitejdbc-v054.jar SQLi-teExample.java Similarly you will need to specify classpath when executingthe program: java -cp .:sqlitejdbc-v054.jar SQLiteExample

If you read the program you will see that four classes are used for databaseaccess: Connection, Statement, PreparedStatement, and ResultSet. Connec-tion represents a connection to the database. Location and type of databaseis indicated when a connection is opened. Statement and PreparedStatementclasses are used to execute SQL statements. The latter is used in cases wherea statement will be executed multiple times with different parameters. TheResultSet represents a list of records selected with a statement.

When using SQLite databases you must make sure that you close theconnections as soon, otherwise it will be blocked for write access by otherprocesses that use the same database.

Normally SQLite driver is set for auto commit, so that statements willbe executed when they are issued. However in many cases it is faster andpractical to execute a batch of related statements at once, so that they will ei-ther succeed or fail alltogether. Such transaction management is an essentialpractice in database programming to reduce errors, in addition to increasingperformance in many cases.

Page 79: OOP LectureNotes

CHAPTER 11. OBJECT SERIALIZATION AND PERSISTENCE 74

11.1.1 Exercises

E-2 Redo the library example in Exercise E-1 using an SQLite database forpersisting library data.

Page 80: OOP LectureNotes

Chapter 12

Java packages

So far we have put all classes needed for our applications in a single sourcefile. This method does not scale well when applications get more complex.Java packages provide the mechanism for organizing code. Packages alsoprovide an additional layer of isolation using the protected members as wewill see.

We have been already using Java packages, whenever we have used the‘import’ statement in out programs. When we want to create a package likethose, we need to do two things:

1. Put a package declaration at the top of the source file such as ‘packagexxx’. There is a certain package naming convention in the Java pro-gramming community. Packages that start with ’java.xxx’ comes fromSun Microsystems. Those taht start with ‘org’ and ‘com’ come fromnon-profit and for-profit organizations, respectively, usually denotingthe organization or project name, such as ‘org.apache.xml’, etc.

2. Place the source files for the same package under a directory struc-ture that resembles its name. For example files for a package named‘org.bilgi.complex’ must go under directory ‘org’ and in that a subdi-rectory named ‘bilgi’ etc.

We have previously used only ‘public’ or ‘private’ modifiers for classesand their members, or used none. With the additional level of organizationusing Java packages we can cover one more modifier: the ‘protected’ modifier.Table 12.1 summarized where can a class or its members be accessed fromwhen each modifier is used or no modifier (so called package-private) is used:In addition to these, the ‘final’ modifier prevents a class from being extendedor a method from being overridden. The major type of situation where thismight be useful is when part(s) of software is in an experimental state and

75

Page 81: OOP LectureNotes

CHAPTER 12. JAVA PACKAGES 76

Table 12.1: Access allowed by Java modifiersModifier Class Package Subclass Worldpublic Y Y Y Yprotected Y Y Y Nno modifier Y Y N Nprivate Y N N N

sub-classing can cause a series of troubles. In such cases the final modifiercan be used to prevent sub-classing until the package reaches some level ofmaturation.

As an example package we will put a complex number implementation andJulia set visualization GUI code (see below) into a package named ‘org.bilgi’.In order to do that we will create a directory named ‘org’ and a subdirectoryunder it named ‘bilgi’. Inside that directory create a file, preferably named‘Complex.java’ for convenience (but it does not really matter as far as its ex-tension is .java!). That file will contain the complex number implementationas follows:

package org.bilgi;

/**

* A Complex number implementation for use in quadratic Julia set

* computations

*/

class Complex {

double r,i;

Complex(double r, double i) {

this.r=r;

this.i=i;

}

double getReal() {return r;}

double getImag() {return i;}

Complex square() {

double newr=r*r-i*i;

double newi=r*i*2;

return new Complex(newr,newi);

}

Complex add(Complex with) {

return new Complex(r+with.getReal(),i+with.getImag());

}

Page 82: OOP LectureNotes

CHAPTER 12. JAVA PACKAGES 77

double length() {

return Math.sqrt(r*r+i*i);

}

/**

* Return how fast the quadratic function converges

*/

int julia(Complex c, int numIterations, double cutoff) {

Complex next=new Complex(r,i);

for(int i=0; i<=numIterations; i++) {

next=next.square().add(c);

if (next.length()>=cutoff)

return i;

}

return numIterations;

}

/**

* Return the quadratic function value for coloring

*/

Complex juliaValue(Complex c, int numIterations) {

Complex next=new Complex(r,i);

for(int i=0; i<=numIterations; i++) {

next=next.square().add(c);

}

return next;

}

}

The source code starts with a declaration ‘package org.bilgi;’ to indicatethat it is part of a package with given name. Also some of the methods aredeclared as protected since they are only experimental and I do not want tomake them available outside the package.

In a separate source file in the same directory I will place the Julia setvisualization GUI, which makes use of the Complex class above. The file isalmost the same with the file given at the end of the tutorial as an answerto the exercise, except that (i) Complex class is removed and placed in an-other file as we have seen above, and (ii) the code starts with a ‘package’declaration and and the application class is declared ‘public’ so that it canbe used when the package is imported elsewhere. I have chosen the nameJuliaSetFractals.java for my file which goes as follows:

/**

Page 83: OOP LectureNotes

CHAPTER 12. JAVA PACKAGES 78

* Implementation of quadratic Julia sets.

* Author: Mehmet Gencer, [email protected], 2008

*

* Try to redraw the Julia fractal using values:

* (-0.4,0.6), (0.285,0.01), (-0.835,-0.2321)

* clicking on a point on the display area will recenter the drawing

*/

package org.bilgi;

import javax.swing.*;

import java.awt.*;

import java.awt.geom.*;

import java.awt.event.*;

import java.util.*;

import javax.swing.event.*;

class JuliaSetFractals {

static FractalGUI gui;

static JFrame mywindow;

public static void main(String[] args) {

gui=new FractalGUI();

mywindow = new JFrame("Julia Set Fractal Renderer");

mywindow.setSize(400, 400);

mywindow.add(gui);

mywindow.setVisible(true);

mywindow.addWindowListener(new MyWindowAdapter());

}

}

class FractalGUI extends JPanel{

JButton button;

JTextField r,i;

int centerX,centerY;

double scale=150; //scaling

Complex c;

FractalGUI () {

button=new JButton("Click here to draw fractal");

button.setActionCommand("click");

button.addActionListener(new MyActionListener(this));

Page 84: OOP LectureNotes

CHAPTER 12. JAVA PACKAGES 79

r=new JTextField("-0.4",10);

i=new JTextField("0.6",10);

add(r);

add(i);

add(button);

addMouseListener(new MyMouseListener(this));

centerX=200;

centerY=200;

c=new Complex(-0.4,0.6);

}

public void paintComponent(Graphics g) {

g.clearRect(0,0,getSize().width,getSize().height);

int numiter=20;

double cutoff=scale;

for (int x=0;x<getSize().width;x=x+1)

for (int y=0;y<getSize().height;y=y+1) {

double real=(x-centerX)/scale;

double imag=(y-centerY)/scale;

Complex p=new Complex(real,imag);

int pj=p.julia(c,numiter,cutoff);

Color color;

if (pj>=numiter) {

Complex pjv=p.juliaValue(c,numiter);

color=Color.getHSBColor((float)(pjv.length()/scale),(float)pjv.length(),(float)pjv.length());

}

else

color = new Color((float)pj/numiter,(float)pj/numiter,(float)pj/numiter);

g.setColor(color);

g.fillRect(x, y, 1,1);

}

//draw the axes

g.setXORMode(Color.white);

g.drawLine(centerX,0,centerX,getSize().height);

g.drawLine(0,centerY,getSize().width,centerY);

g.setPaintMode();

}

void recenter(int newx, int newy) {

System.out.println("Recentering");

centerX=newx;

centerY=newy;

repaint();

Page 85: OOP LectureNotes

CHAPTER 12. JAVA PACKAGES 80

}

void redraw() {

try {

double newr=Double.parseDouble(r.getText());

double newc=Double.parseDouble(i.getText());

c=new Complex(newr,newc);

} catch(NumberFormatException e) {

System.out.println("Invalid value given!");

}

repaint();

}

void revalue(int newx, int newy) {

double real=(newx-centerX)/scale;

double imag=(newy-centerY)/scale;

c=new Complex(real,imag);

r.setText(String.format("%f",real));

i.setText(String.format("%f",imag));

repaint();

}

}

class MyWindowAdapter extends WindowAdapter {

public void windowClosing(WindowEvent event) {

System.exit(0);

}

}

class MyActionListener implements ActionListener {

FractalGUI gui;

MyActionListener(FractalGUI gui) {

this.gui=gui;

}

public void actionPerformed(ActionEvent e) {

if (e.getActionCommand().equals("click"))

gui.redraw();

}

}

class MyMouseListener extends MouseInputAdapter {

FractalGUI gui;

MyMouseListener(FractalGUI gui) {

Page 86: OOP LectureNotes

CHAPTER 12. JAVA PACKAGES 81

this.gui=gui;

}

public void mouseClicked(MouseEvent e) {

int newx=e.getX();

int newy=e.getY();

if (e.getButton()==MouseEvent.BUTTON3) //if right-click, choose ’c’ from mouse position

gui.revalue(newx,newy);

else

gui.recenter(newx,newy); //if left-click, recenter drawing

}

}

Note that we do not need to import the Complex class although it is in aseparate file. This is because the two source files are part of the same package.The trick, however, lies in the fact that the two files must be compiled atonce, as follows:

javac Complex.java JuliaSetFractals.java

Any attempts to compile the first, then the second will fail!As I have a new package, I can now write applications which use the

package:

import org.bilgi.*;

public class PackageUser {

public static void main(String[] args) {

JuliaSetFractals jsf=new JuliaSetFractals();

jsf.main(args);

}

}

When compiling the message make sure that either the ‘org’ directorywhere our package resides is in the same directory with the program, oryou modify the Java classpath (using -cp option of javac command) whencompiling and running the program.

12.0.2 Distributing multi-file Java applications: jar archives

When your application consists of one or more packages and some otherfiles that use those packages, it becomes hard to distribute them. You willneed to provide detailed instructions for users to create the proper directory

Page 87: OOP LectureNotes

CHAPTER 12. JAVA PACKAGES 82

structure, which creates quite an error prone situation. A solution for thesetype od situations is to use Java archives, or simply jar’s.

Sun JDK comes with a program named ‘jar’ to create or extract sucharchives. For example you can create an archive containing our package andthe application that uses the package as follows:

jar cvf bundle.jar org PackageUser.java

However jar is more powerful than, for example, zip archives. It is possibleto use jar files as executables. In order to do that we must tell Java whichclass is the one to be loaded as an application. The way to do this is tocreate a file named ‘manifest.mft’ which contains the following:

Manifest-Version: 1.0

Main-Class: PackageUser

Class-path: .

then use the jar command as follows:

jar cvfm bundle.jar manifest.mft org PackageUser.java

Now you can execute the created archive as follows:

java -jar bundle.jar

This makes distribution of multi-file Java software more practical.

Page 88: OOP LectureNotes

Appendix A

A guide for coding style

Computer programs are not merely for compilers and interpreters. On thecontrary, a more frequent type of access happens when we open the programfor improving, or finding bugs, or when a team-mate does the same. There-fore, a program needs to be understandable when we need to recollect whatwe have done previously, or when it is the object of collective work. In thisregard, programming is an art form, not only because it is an applied craftof mathematical abstraction, but also as the presentation of this abstractionin the form of a program is a piece of writing which should demonstrate apleasant and readable style.

A first condition for coding style is consistency in using symbols anddelimiting parts of program. When one writes literature, one follows certainestablished rules in using punctuation marks (i.e. periods at the end ofsentence), capital letters (i.e. first letter of sentence, or private names startwith capital letters), or demarcating text (i.e. starting new paragraphs orpages). Similar rules emerged through the programming practice in halfa century of its existence. These rules are not universal, just as differentnational languages vary in their rules of writing them. Different programminglanguages, or some programmer communities can differ in the style rules theyfollow. In this guide we try to present most common rules used in the worldof programming.

A.1 Demarcation

One of these established rules regards demarcation of different scopes in aprogram. This is established by using consistent indentation for programstatements that are at the same level, and increasing indentation level asscopes are nested within one another. Following piece of Java code demon-

83

Page 89: OOP LectureNotes

APPENDIX A. A GUIDE FOR CODING STYLE 84

strates how this is applied:

int factorial (int n) {

if (n<=1)

return 1;

else

return n * (n-1);

}

In the above program the function scope is indented with four spaces.The nested scope of ’if’ statement is indented further:

int factorial (int n) {

--->if (n<=1)

------->return 1;

--->else

------->return n * (n-1);

}

The program also demarcates parts of statements with spaces. For ex-ample if is written as below:

int factorial(int n){

if (n<=1) return 1; else return n*(n-1);}

it becomes considerably less appealing to its reader and very hard tounderstand.

There are minor variations in how this rule is applied. For example someprefer to place brackets encapsulating scopes as follows:

int factorial (int n)

{

if (n<=1)

return 1;

else

return n * (n-1);

}

Although this variant of the rule seems more logical, we will follow thefirst version of the rule, merely due to the fact that it is more common in theprogramming community.

Page 90: OOP LectureNotes

APPENDIX A. A GUIDE FOR CODING STYLE 85

A.2 Organization

Generally the data has precedence over the process. This is reflected in oursecond rule of placing variable declaration statements before other statementsin the programs. For example in defining a Java class as follows:

class Complex {

double real;

double imaginary;

Complex (double real, double imaginary) {

this.real = real;

this.imaginary = imaginary;

}

double getMagnitude () {

return Math.sqrt(real*real + imaginary*imaginary);

}

...

Different programming languages may follow further refinements in codeorganization. For example in Java programming, it is a common practice toplace static members before non-static members, and constructor methodsbefore any other method. Therefore on top of variables preceding methods,static variables must precede non-static ones, and static methods precedenon-static ones but come after constructors. For example:

class Circle {

static double PI = 3.14;

double radius;

Circle (double radius) {

this.radius = radius;

}

static double area (Circle c) {

return PI * c.radius * c.radius;

}

double area () {

return area(this);

}

...

Page 91: OOP LectureNotes

APPENDIX A. A GUIDE FOR CODING STYLE 86

A.3 Explanation

Each programmer have a different and unique approach, and even ones ap-proach will be different in two year’s time. Although how you do thingsmay in many cases seem trivial to you, it is a good practice to explain keyelements of your program in plain natural language. For this reason all pro-gramming languages provide a means of placing ‘comments’, lines or blocksof text which is marked to be excluded from program compilation or inter-pretation, but rather put for the human readers. Today it became a commonpractice to place short or long comments at top of program files, near classes,functions, or variables, and even within intermediate points inside functionsto explain what is going on. The following example uses such commentsextensively (some lines are split to fit on the page):

/** A program to draw Julia set fractals.

* Author: Mehmet Gencer, [email protected]

* Created: 24 Nov 2008

*

* This program is free software and provided without any guarantees.

* You can redistribute this program in original or modified form

* provided that this copyright notice is preserved.

*/

/**

* Complex class represents a complex number, and provides additional

* methods for convergence checking in quadratic Julia sets.

*/

class Complex {

double real; // real part of the complex number

double imaginary; // imaginary part of the complex number

...

/**

* Return square of the complex number

*/

Complex square () {

double newr = real*real - imaginary*imaginary;

double newi = real*imaginary*2;

return new Complex(newr,newi);

}

Page 92: OOP LectureNotes

APPENDIX A. A GUIDE FOR CODING STYLE 87

/**

* Check whether a quadratic function in the form z_(i+1)=z_i^2+c

* diverges for given z when iterated. If the magnitude of z

* exceeds ’threshold’ after at most ’maxIterations’ number of iterations

* it returns true, otherwise it returns false.

*/

static boolean checkDivergence

(Complex z, Complex c, double treshold, int maxIterations) {

Complex znext; //variable to store next value in iteration

//iterate up to maxIterations,

// but if threshold is exceeded in the meantime, return true immediately

znext=z;

for (int i=0; i < maxIterations; i = i+1) {

znext=znext.square().add(c);

if (znext.getMagnitude() > treshold)

return true;

}

return false;

}

...

In the above example the comments at the top of the program briefswhat program does, who wrote it and when, and what one can do with it.Each class and method is preceded with a long comment. All variables aresucceeded with short comments. And the relatively longer method, checkDi-vergence(), has comments within the method body.

The above example demonstrates a very common way of code documen-tation, used in java and C/C++. Indeed there are various programs writtento produce software reference documentation automatically from such codecomments. However this rule also has variations. For example Python pro-grammers place code comments after method or class definitions, an Pythonenvironment has documentation tools based on this.

A.4 Explication

Excessive use of comments may become a handicap to readability of theprogram. One remedy for this problem is to choose explicit, self-explanatorynames for your methods or variables which eliminates further explanation incode comments. For example if the factorial function was declared as follows,it would definitely require code comments:

Page 93: OOP LectureNotes

APPENDIX A. A GUIDE FOR CODING STYLE 88

int f (int i) {

...

}

as the function name is nowhere near being self-explanatory. Long namesmay feel cumbersome at the beginning, but you’ll come to appreciate theirvirtue as you re-visit your programs.

A.5 Naming conventions

There are various names in a program: for classes, for variables, for methods,etc. Also in related to explication, you may have to have variable or methodnames that are longer than a single word. There are competing trends inhow one should choose names. Here we describe the most common methodsin the Java programming world:

• Class or Interface names start with a capital letter, and interfaces arecommonly prefixed with an ‘I’. For example: Complex, IIteratorInter-face, LogicException, etc.

• Variable or method names start with a small case, but if it consists ofmultiple words first letter of each word is capitalized for ease of reading.For example: i, x, real, nextValue, getSize(), etc.

• Constants are in capital letters, and if they consist of multiple words thewords are separated by underscores. For example: PI, MAX LENGTH,etc.

Page 94: OOP LectureNotes

Bibliography

Brooks, F. P. (1995). The mythical man-month : essays on software engi-neering. Addison-Wesley.

Felleisen (2004). How to Design Classes.

Zakhour, S., S. Hommel, J. Royal, I. Rabinovitch, T. Risser, and M. Hoe-ber. The Java Tutorial: A Short Course on the Basics, 4th Edition.java.sun.com/docs/books/tutorial/java/nutsandbolts/index.html.

89

Page 95: OOP LectureNotes

Index

arrays, 13

compiled languages, 32compiler, 32constructor, 21, 25, 30, 45, 46, 61, 85contracts, 24

declarative, 2, 7

executable, 32

for loops, 14functional, ii, 1, 24

imperative, ii, 2, 6, 7, 34inheritence, 40, 41interpreted languages, 32interpreter, 32iteration, 2, 7, 11, 14

Java Virtual Machine (JVM), 32

libraries, 33

method overloading, 62mutual references, 62

overriding, 45overriding methods, 43

SDK, 33static, 29, 30, 34, 35, 44, 85strictly typed, ii, 2, 3, 6, 13, 28Sun Java SDK, 33

90

Page 96: OOP LectureNotes

INDEX 91

[default]