Sie sind auf Seite 1von 67

Chapter 2.

Java Object & Development

Context

The purpose of this unit is to give you an experience of the life story (from start to finish)
of a non-trivial Java program. This will support your investigation and learning of the
activities involved in the implementation of software systems. The system you will
develop during this unit should provide you with an idea of the kind of Java
programming you will progress towards achieving as you work through this module. As
you progress through the module you may wish to revisit this unit to apply your
developing knowledge of Java and its implementation of object concepts.

Objectives

At the end of this unit you should be able to:

 Explain what is meant by the terms such as programming language, machine


code, high-level language, source code, object code
 Enter, compile and execute a simple Java program
 Describe the differences between a compiler and an interpreter, including the
advantages and disadvantages of each for commercial software production
 Explain the extent and way the Java implements the concepts of object
orientation:
 Argue the strengths and weaknesses of the Java programming language,
referring to such concepts as portability and platform independence
 Explain the difference between Java application and applet

Required Study Time

Preparation (Introduction and On-line ½ hour


Planning):
Disk-based and Textbook Content: 2 hours
Application (Exercises & Activities): 3¾ hours
Reflection (On-line discussions, review 1 hour
questions):
Tutorial Work: 1 hour
Related Coursework: ¼ hour
Extension Work: ½ hour
For a more detailed breakdown of the unit see Study Map

Equipment/software required

Sun Java Development Kit (JDK1.3)


TextPad 4.5

Reading material and resources

 Set text:

1. Deitel and Deitel (1997) "Java: how to program",3rd edition, Prentice-Hall,
ISBN: 0-13-012507-5

 Online Resources

1. Frequently-asked questions
2. Additional Source Code Examples

Implementing Software Systems


This material should be read in conjunction with Deitel and Deitel chapters 2 & 3. We
suggest that you work through Chapter 2 making notes on each of the "Common
Programming Error" sections.

Although some of these error descriptions may not make sense to you yet, it is a good
habit to make your own notes on different types of errors and how to solve and avoid
them.

If you write such notes as a text or word processor file, you will be able to easily search
your notes for particular phrases, especially particular word or phrases that may appear
in error messages displayed by the Java compiler.

Different text books and teaching aids will present concepts in different orders. So you
will find some aspects of Deitel and Deitel Chapter 1 different to the first units of this
module. This is no bad thing, since you may need to work from multiple reference
sources, and to things in an order that makes sense to you to understand and be able to
apply each concept of the module.

You might wish to both work through the module units in order, while simultaneously
working through the Deitel and Deitel (or some other book you find you prefer) in the
order of the book's presentation. Alternatively you may simply stick with the order of
concepts and skills presented by this module, and locate each units concepts where-
ever they might appear in each of your reference sources.

Another alternative is to work through the units of this module in a different order than
their presentation. Although you need to be careful, since courseworks will assume you
work through the units in order, you may find later some later unit(s) easier at first, and
then when you go back to an earlier unit it makes more sense.

Each person learns best in his or her own way, and part of every programme of study,
and every different module, is finding out how you best learn the concepts and their
application.

Introduction to implementation

Before a programmer sits at a computer and starts coding (enter program instructions)
other actives must have occurred. A programmer needs to have some kind of model of
how the final software system will behave, and usually (hopefully) has developed or
been provided with some kind of software design document.

Implementation of modern software systems often happens a number of times during


the life cycle of a software system. For example a prototyping approach may have been
adopted for the software project, where parts (or even all) of the system are designed
and implemented and then evaluated, to provide feedback on how to go back and
improve the design of the system. Another common situation where implementation
happens a number of times is when a software system is so large, or important, that an
organization decides to introduce the system in stages. Thus one part of a system may
be designed and implemented (perhaps a new stock control system), while other parts
of the system are still in the modeling or design stage (perhaps the supplier or payroll
systems). As the project goes on more and more sub-systems may be redesigned and
implemented to eventually form a coherent, integrated corporate information system. A
third situation where software implementation occurs two or more times is when an
organization using an implemented system changes its requirements (perhaps for Y2K,
or the introduction of the Euro, or a change in some legislation effecting an
organizations taxation). In such cases a system needs to be analyzed and modeled
again, taking on board changes, the changes designed and then implemented.

Even for small software projects such as those you will undertake on this module, it is
important you have analyzed, modeled and worked the design of a piece of software
before actually beginning to sit at the computer and start coding.

This part of this unit will help you investigate the process of writing computer programs,
and of their translation into instructions understandable on a given hardware computer
system.

From source file to execution

Although all the programs you will be writing for this module will be in Java, computers
have at their "heart" a microprocessor that cannot understand, and so cannot execute,
statements in the Java programming language. Each computer's microprocessor can
only understand and execute instructions in its specific, very low level machine
language. By low level it is meant that machine code instructions relate to tasks close to
the physical design of the microprocessor -- moving data to and from places in memory,
storing a value in a temporary memory location (register) and performing simple
computation (arithmetic and logic) on data in these temporary locations. Java is a high
level language, allowing human programmers to ignore the low level details of memory
and simple logic. High level languages provide facilities for humans to program in terms
of more abstract concepts -- object oriented programming languages allow humans to
program in terms of object concepts, with the benefits and sophistication object
technology brings through features such as encapsulation and inheritance.

This section presents a summary of how it is possible for a microprocessor to execute


languages that were originally written in a non-microprocessor specific programming
language such as Java. There are a number of stages in this program translation
process. Such concepts are important, since Java has been designed to be a much
more portable programming language than many before it. Such a feature comes with
associated costs, of efficiency and complexity of language translation, however the
great interest and investment in Java by academia and industry demonstrate that for
many the benefits outweigh these costs.

Microprocessors and their machine code

Computers work on electronic signals We find it convenient to represent highs and lows
as zeroes and ones - the digits of the binary number system. We go further by
discussing sequences of binary digits, bits, as representing contents of memory,
registers, disk sectors, etc. These binary sequences can be interpreted as a whole
plethora of things: instructions to a processor or controller, packets on a network, or
data such as numbers, strings, true and false values, etc. Consequently we often
(incorrectly) talk of machine instructions (machine code) as binary numbers. They are
maybe structured sequences of bits, but not always numbers.

This kind of misuse of language is common in computing where you are often switching
between different levels of abstraction. You even hear people say "It's all bits in the
end." Of course, this is not true, but physicists might even challenge the maybe more
accurate statement that "It's all electrons in the end."

The machine code for a particular microprocessor is called its "native machine code".
The we could talk about Pentium II native machine code, PowerPC native machine
code, and Athlon native machine code etc.

A need for higher level languages and virtual machines

Software is designed and written by different groups of people for different purposes.
For hardware designers and "systems" programmers there is a need to think in bits or
hardware instructions -- i.e. these people need to think about and write software that is
"close" to the particular computer they are working on. Such people may need to
program computers in "low" or "machine" level languages. However, for most analysts
and designers and (higher level) programmers, it is not useful to think in such machine-
level concepts, but to think in terms of higher level abstractions. A plethora of plausible
abstractions have been proposed, usually expressed in a programming language,
graphical notation or mathematical notation.

Traditionally many programming language development environments were


implemented in a way that closely matched specific hardware. This led to problems
moving software from one hardware or operating system platform to another. However,
a compiler technology that assumes an idealised processor has alleviated this problem.
First used for languages like Pascal and Smalltalk, this idea of a ‘virtual’ machine has
become popular with Java, and platform independence for a popular language has
enhanced its popularity and usefulness.

From Java source files to microprocessor specific machine codes


The statements we write in high level languages such as Java are called "source code".
When a source code statement has been translated into some other (usually lower
level) computer language, the result is called "object code".

JDK Java Translation requirement:

A source file containing a Java program has to have the extension ".java"

One stage may produce code for and idealised, so-called virtual, machine. This means
there is a two stage translation process: from high level language to virtual machine
code, and then from virtual machine to a native (real world microprocessor) machine
code.

Translation from one computer language to another can be one of two forms:
interpretation or compilation.

Interpreting software means that, in essence, each instruction in turn is translated


to a sequence of real (not virtual) machine instructions and executed by the
processor.
Compilation means that the whole piece of software (source code file) is
translated into machine instructions first and stored. A stored translated program
is called an object code file. If a piece of software has been compiled into a
native machine code, then the object code instructions can be executed. If
compilation has been into a virtual machine code, then this compiled object file
needs to be translated again (again via either interpretation or compilation) to be
executed on a real microprocessor.

The first way, interpretation, is more flexible, and results in smaller storage
requirements for the software expressed in virtual machine code. The second way,
compilation, results in faster execution, but much larger storage requirements.

In almost all cases where translation is from a high level language to a virtual machine
language the translation process is by compilation -- i.e. from a high level source file
one compiles to a virtual machine code object file. Once this virtual machine code file
has been prepared, it may be interpreted, or compiled into a native machine language.

Java has been designed to be first compiled and then interpreted. A typical Java
compiler produces Java bytecode, which are instructions for an idealised computer --
called the Java Virtual Machine (JVM). Bytecode object files can be loaded into a real
computer for interpretation by a piece of software that essentially pretends to be the
idealised computer and so is confusingly called the Java Virtual Machine (JVM). The
Java Virtual Machine interpreter translates one instruction at a time from bytecode into
the native machine code for the computer it is running on.

JDK Java Translation requirement:


An object file containing a Java program compiled into JVM bytecode is
automatically given the extension ".class"

Of course, in order to run itself, the JVM interpreter must be a native machine code
program itself. So in order to run a Java program on, say, a PC one needs a set of
compiled Java bytecode object files, and a JVM interpreter for the PCs microprocessor.
In order to run the same compiled Java bytecode object files on a Macintosh, one needs
another JVM interpreter written in the Macintoshes native machine code.

A popular feature of Java is that a certain kind of Java program, called an " applet " can
be run on computers with modern web browsers. This is possible because such modern
web browsers, like Internet Explorer 4 and Netscape Communicator 4.5, include their
own Java Virtual Machine interpreter. So the web browser can interpret (and so
execute) compiled Java bytecode files.

It is not necessary to use a browser to execute all Java programs -- a second kind of
Java program, called an "application" is not designed to be run within a browser. To run
a Java application one uses a "stand alone" Java Virtual Machine interpreter. In this
module we use the JVM interpreter provided in Sun's Java Development Kit (JDK)
called "java.exe".

In fact, it is possible to run Java applet programs outside of a web browser using a
second of Sun's interpreters, called "appletviewer.exe" which interprets Java bytecode
files in the same way that web browsers are designed to.

The real world

Although not untrue, the above is a slightly simplistic view of what


happens in the real world. Almost always, the translated instructions (in
the virtual machine code) that results directly from what the programmer
wrote is packaged with a run-time environment. A run-time environment is
code written by developers of the language implementation because it is
needed to match the target hardware and operating system.

With the exception of very trivial software systems, you will almost always be working
with 2 or more Java classes. Each class needs to be compiled separately (from its
".java" file into a corresponding bytecode ".class" file) and then the run-time interpreter
is used to repeatedly choose the appropriate bytecode instruction to translate and
execute (from the appropriate bytecode file).

Life story of a Java program

The life story of one possible Java program is illustrated in the figure below.
The following steps are illustrated in the figure above:

a Java source file has been written and saved into the file "MyClass.java"
a Java compiler has then been used to compiled this source file into JVM
bytecode instructions stored in a file called "MyClass.class"
in order to execute the program, the bytecode "MyClass.class" file, along with 2
other required pre-compiled files are provided to the JVM interpreter

this JVM interpreter iterates, choosing the next bytecode instruction to be


executed, translating that instruction into the native machine code, and
executing it (then choosing the next bytecode instruction and so on until
the program terminates).

In the figure above "XXX"s indicate bytecode instructions, and the sequence of binary
digists "001001…" represent a native machine code instruction that has just been
translated for execution by the run-time interpreter.

A note on computers with Java processors

In fact research is underway to develop a new family of microprocessors


whose native machine language is actually Java bytecode. However, such
computers are not yet available for consumer or business use, and for a
very long time most people will be wishing to execute Java programs on
computers whose microprocessors native machine code is not JVM
bytecode.

A note on "native code" compilers

Some companies (for example Symantec) are now beginning to release


Java software development environments that will compile Java programs
into native machine code object files. This means that, potentially,
software developers can create source files that can be both interpreted
on any computer with a Java Virtual Machine, and also run efficiently on
computers for which there exist native code compilers.

However, the introduction of native code compilers also introduces


possible problems of portability, since it is very tempting for a software
developer to introduce special Java libraries designed to take advantage
of a particular computer's features. Thus one can write Java programs in,
say, Microsoft's J++ environment that make very efficient use of Windows
Java classes, but result in Java programs that cannot be compiled into
"pure" Java Virtual Machine bytecode.

Native code compilers and machine specific Java libraries resulting in


non-standard bytecode are both examples of directions developers are
going in order to overcome some of the efficiency and speed limitations of
interpreted "pure" Java programs.

From source file to execution: Summary

A compiler converts a whole file from one language into a machine code

either into a native or virtual machine code

A native machine code file can be executed


A virtual machine code file needs to be further translated
An interpreter translates and executes one statement at a time
The end user does not need a compiler to run a bytcode Java program
The end-user does need a run-time interpreter to interpret a Java bytecode
virtual machine code file

Interactive development environments (IDEs)

This module has been written with the assumption that you are using Sun's Java
Development Kit (JDK) for the compilation and interpretation of your programs.
However, there are other software development environments for Java available.
Most of these other environments are Interactive development environments (IDEs).
IDEs are useful for automating some of the steps in production of a program. Most
people who program extensively use an IDE, but IDEs do not allow anything different to
be achieved, compared with using the basic JDK.

One advantage of using the JDK for development is that it is free. Many software
developers, through personal preference, do not use any IDE tools, for programming in
any language. However, many do use user interface design tools. Apart from cost, a
good reason for using the standard JDK in a module like this is that it exposes the
operations that would be "behind the scenes" when using an IDE. When you
understand fully what these operations are, you may prefer to use an IDE.

For the production of large scale software systems, IDEs can provide tools to speed up
and help manage the coding process. However, there are also costs associated with
IDEs. In addition to their purchase price, perhaps the most significant cost is the amount
of time and effort that needs to be invested in learning to use a sophisticated IDE. It is
often difficult to learn to use an IDE until after one knows how to program, at least to
some degree, in the language the IDE is to support.

After completing this module you will have sufficient knowledge of the Java
programming language, the processes of compilation and interpretation, and the way
Java programs may require the use of class libraries to be able to learn to use Java
IDEs should you choose to do so.

At the time of writing there are no free IDEs for the Windows environment, but there are
for Unix.

Interactive development environments: Summary

IDEs support the steps of software production


They may also provide:

user interface design tools


interactive debugging

The IDEs use the same Java language


The result of working with IDEs is the same as working with the JDK
Most IDEs have a significant cost in terms of the learning required to be able to
benefit from their sophisticated features.

Coding steps at a computer

When writing a Java program you will find yourself going through a cycle of steps many
times. These steps will be:
edit using a text editor to create or modify a Java source file
save saving the completed Java source file (into a file with a ".java" extension)
compile translating your Java source file into a compiled Java bytecode object
file (with a ".class" extension)
run provide the Java interpreter with the compiled classes it needs to execute
your program

Illustration of coding steps

The figure below illustrates the steps in program implementation, and also where errors
may be detected and need to be debugged.

Debugging different kinds of error

The process of locating, identifying and correcting the errors in a piece of software is
called debugging. Like many complex activities it is very unlikely that every program you
write will work first time. There are two stages at which you will need to identify and
attempt to debug (solve) errors in your programs:

compile time it may not be possible for the compiler to understand your program, and so
it will not be able to create a compiled bytecode object file
run time even once a program has been successfully compiled errors may occur when
you attempt to run the program

There are 2 types of error you will find at compile time:

syntax errors errors in the form of a statement


semantic errors syntactically correct statements which do not make sense in the
language

The syntax of a language refers to the spelling, punctuation and grammar -- in other
words whether a statement in the language follows the rules of the language. The
English statement "Yestday me shops down went" contains both a spelling error "
Yestday", and violations of English grammar, also this sentence should end with a full
top -- a syntactically correct version of the sentence is "Yesterday I went down to the
shops.". Syntax errors in programming languages such as Java include:

spelling the names of reserved words wrong (for example writing "clas" instead of
"class")
forgetting required punctuation (in Java every statement should be followed by a
semi-colon)
putting punctuation in the wrong place
not having matching pairs of parentheses "( )" or braces "{ }"
and so on.

The semantics of a language refer to the meaning of the statements. An semantic error
is an statement that meets a languages rules of syntax, but does not make sense. An
English statement with a semantic error might be "Late one stone the angry table died."
-- although the sequence of verbs and adjectives etc. are correct in this sentence, and
the spelling and punctuation are correct, this sentence does not make sense, since a
stone doesn’t have lateness, tables do not die or feel angry. Examples of semantic
errors in Java include:

trying to send a message to a variable that does not refer to an object


trying to store some characters in a variable that can only stored integer values

The third kind of error you will encounter is the most difficult kind. You may get a
program to successfully compile and run, but the program may not do what you
intended. Errors in the way a program behaves are called logic errors. A logic error
occurs when the computer can understand and execute your software, but the things it
does are not what you intended. An example of a logic error in some instructions in
English might be: "To drive to work, open your driver's door, sit in the drivers seat, start
the engine, put the car into gear, drive along the route to work, park the car, switch off
the engine, get out the car and close your driver's door". While following such
instructions might get you to work, since you drove all the way without ever closing the
driver's door the chances are other drivers would get angry due to the danger and
effective width of your car. Examples of logic errors in Java programs include:

non-termination of your program because you make it go into a loop that never stops
writing a test for the wrong condition (for example writing "if( age < 21 )" rather than "if(
age > 21)" when you wish to test if some value is greater than 21 changing the value of
a variable to that of another, when in fact you wished to compare the two values -- this
is very common due the to similarity of the symbol to change a varibale's value "=", and
the symbol to compare two values "= ="

Learning how to debug

Learning how to debug each kind of error takes practice. You will get this practice since
most programs you write when you begin programming will contain all three kinds of
error, and you will need to debug them to get your programs to work. Don't feel you are
wasting time if it takes 10 minutes (or whatever) to identify, location and correct an
error. Such an activity means you not only have learnt to debug that particular error, you
are also much less likely to write a program containing that error in the future. You can
improve your learning of debugging, and the writing of error free programs by making
notes each time you debug an error. Such notes will help you understand the error and
Java's error messages, and help you learn how to write programs that do not contain
that error in the future. Also, if you have notes on each error you have debugged, when
a similar error message occurs again, you have your own notes to guide the debugging
of the new error.

The steps in debugging are often:

identify that there is an error, and what kind of error it is -- either from
compiler error messages, or incorrect program behavior
locate the error -- find out which part of your program has the error. This is
a form of detective work, locating the class, method or variable, and
eventually statement(s) that are causing the problem
understand the error -- work out what the problem is, and how changing
program statements will solve the problem
fix the error -- try out alternative changes to the program, recompile (and
run if it was a logic error) and test to see if the error has been fixed

What can make debugging difficult is that there may be many error in a program the first
time it is compiled, so you may have 5, or 10 or 20 Java error messages. Often a single
error can lean to multiple error messages, and the Java compiler may not always
correctly suggest the line or method of your program where the error is located.
Obviously, if the program has errors in syntax, since it is not a valid set of Java
statements, the Java compiler has trouble working out which part of which statement is
ungrammatical.

Programming concept map

Introduction

Java implements many, although not all, object concepts. A Java program comprises of
a set of classes. All program instructions must be defined inside methods, which are
parts of classes.

Some other programming languages support the concept of "global" data and sub-
programs (called functions or procedures or some such term in other languages).
Global data and sub-programs are those hat are accessible to all parts of a software
system. There are no "global' sub-programs or data permitted in Java.
Object concepts in Java

A Java program is a software system -- i.e. an executing Java program is a network of


software objects. The writing of a program in Java consists of defining a set of classes
using the Java programming language. Simple Java programs may consist of a single
class, or just two or three classes, while complex programs can consist of many tens,
hundreds or even thousands of classes.

Usually (preferably) the writing of Java programs happens after the desired system has
been modelled and represented using object concepts. Such a model acts as a
specification of the system, and as a design from which a computer program can be
implemented.

The model of a class involves defining the attributes and operations of a class. When
implementing a class in Java:

attributes are implemented as Java variables


operations are implemented as Java methods.

Java provides three different types of variable, an overview of which are given in this
unit. A more detailed investigation of Java types and variables is conducted in the next
unit.

The implementation of a class in Java

A class is implemented by writing Java program statements in a file with the same name
as the class. So, for example, a class called "BankAccount" would be implemented in a
file called "BankAccount.java".

The contents of such a class would be something like:

file: BankAccount.java

class BankAccount

<variable1 defined here>

<variable2 defined here>

<variableN defined here>

<method1 defined here>

<method2 defined here>

<methodN defined here>


}

Notice how a class is defined using the Java reserved word "class" followed by the
name of the class. Also notice how the use of the open "{" and close "}" braces are used
to encapsulate the contents of the class, i.e. all variables and methods are written inside
these braces to define the class.

The implementation of class attributes in Java

Attributes are implemented as Java variables.

Consider the following attributes from a model of a class of BankAccount objects:

accountNumber
accountHolderName
accountHolderDateOfBirth
balance
overdraftLimit

To implement these attributes in Java we need to decide what type (kind) of Java
variable to use for the storing of each of these attributes. The term "type" has a
particular meaning in computer programming, and in fact many object concepts have
evolved from earlier work on a form of programming involving abstract data types. In a
computer program any variable is of a specified type. Each computer programming
language provides facilities for its own particular set of variable types. Pure object-
oriented programming languages provide only one type of variable -- the object.

Attributes store different types of value. Examples of each of the attributes for our
BankAccount class might be:

accountNumber: 00101234, 02224488, 01012001


accountHolderName "James Smith", "Leopold Schubert", "Pierre Dupont"
accountHolderDateOfBirth 06-05-1945, 11-11-1990, 28-12-1975
balance 1002.56, 0.01, -256.99
overdraftLimit -50, -500, -875

The programmer can infer from examples such as these the types of value for each
attribute:

"accountNumber" might always be an 8-digit number


"accountHolderName" might be a series of up to 20 characters
"accountHolderDateOfBirth" might be a date object
"balance" might be a decimal value stored to 2 decimal places
"overdraftLimit" might be a whole number

One possible implementation of the above attributes as Java variables is as follows:


file: BankAccount.java

class BankAccount

// variables

char accountNumber[];

String accountHolderName;

Date accountHolderDateOfBirth;

float balance;

int overdraftLimit;

// methods

<method1 defined here>

<method2 defined here>

<methodN defined here>

Java is not a pure object-oriented programming language. One way in which Java is not
pure is that not every attribute is implemented as a object variable. Java provides three
types of variable:

objects
primitive types
arrays (of either objects or primitive types)

All three types of variable are introduced in the following units. In the example above we
can see that to implement the variables of a class in Java, as well as stating the variable
name, we also need to precede this with the name of the type of variable it is. Above we
see examples of five different types:

char [ ]
String
Date
float
int

Although the details are not important for this illustrative example, the first is an array of
characters, the second and third are objects of classes String and Date, the fourth is a
floating point (decimal) number, and the last an integer (whole) number.
Java Programming convention:

Classes are written with a capitalised first letter (String, Date)

Java Programming requirement:

Primitive types must be written with a lower case first letter (char, float,
int), since this is how they have been named in the definition of the Java
programming language

The implementation of class operations in Java

Operations are implemented as Java methods.

Consider the following operations from a model of a class of BankAccount objects:

getBalance tell us the balance


setOverdraftLimit set a new overdraft limit
overdraftLimitExceeded has the overdraft limit been exceeded?

Java Programming convention:

Method names start with a lower case first letter

As part of the object-oriented modelling process, each operation should be defined in


terms of any arguments it may need, and also if, and what type, of reply the operation
may return.

The implementation of methods in Java involves writing Java program statements to


specify:

the return type, if any, of a method’s reply


the name of the method
a list of any arguments (and their types) required by the method
the list of Java statements to be executed when the method is invoked

Consider possible implementation of the operation "getBalance" as a Java method:

it does return a value, it returns the value of the "balance" variable. This
reply is of type "float" (the same type as the "balance" variable)
the name of the method is "getBalance"
this method does not need any arguments
the only action to be performed is to return a reply that is the value inside
the "balance" variable
One possible implementation of the "getBalance" operation as a Java method is
illustrated as follows:

file: BankAccount.java

class BankAccount

// variables

char accountNumber[];

String accountHolderName;

Date accountHolderDateOfBirth;

float balance;

int overdraftLimit;

// methods

float getBalance()

return balance;

<method2 defined here>

<methodN defined here>

Java Programming requirement:

All methods must specify a list of arguments in parentheses immediately


after the method name. If no arguments are required, nothing is written
between the parentheses. This is illustrated in the method "getBalance",
written with no arguments "getBalance()".

Let us consider a possible method implementations of the remaining two operations:

operation: setOverdraftLimit

it does not need to return any reply (this is indicated in Java with the Java
term "void")
the name of the method is "setOverdraftLimit"
this method requires one argument, an integer value that is to be the new
value of the "overdraftLimit" variable
the only action to be performed is to overwrite the old value of the
"overdraftLimit" variable with the value of the argument provided

operation: overdraftLimitExceeded

it should return a reply of "true" or "false" (this is of the primitive type


"boolean", explored detail in the next unit)
the name of the method is "overdraftLimitExceeded"
this method requires no arguments
the action to be performed is to compare the value of the "balance"
variable with the value of the "overdraftLimit" variable, and to return "true"
is the balance is a larger negative number, and "false" otherwise

One possible implementation of the "setOverdraftLimit" and "overdraftLimitExceeded"


operations as Java methods are illustrated as follows:

file: BankAccount.java

class BankAccount

// variables

char accountNumber[];

String accountHolderName;

Date accountHolderDateOfBirth;

float balance;

int overdraftLimit;

// methods

float getBalance()

return balance;

void setOverdraftLimit( int newLimit )

overdraftLimit = newLimit;
}

boolean overdraftLimitExceeded()

if( balance < overdraftLimit )

return true;

else

return false;

Public and Private variables and methods: Access methods

It is often the case that some of the variables and methods defined for a class of objects
are solely for an object to help perform its tasks. For example a variable to store the
intermediate result of some calculation, or a method that performs some calculation on
the objects variables. Such variables and methods are not intended to be interrogated
or invoked by other objects.

For example, consider an object that is an instance of a Loan class. An attribute


identified in modeling might be "remaining Loan". When a payment has been made, the
payment is deducted from the remaining loan balance and the balance reduced. When
interest is calculated it is calculated according to the remaining balance and the added
to the balance. However, when a customer wishes to pay off a loan in total, earlier than
the original loan period, the loan total to repay is actually calculated with a charge for
some portion of the remaining interest. Thus, for such a Loan object, we would not wish
other objects to be able to interrogate the variable "remainingLoan" directly, but to be
required to interrogate the value of this variable via a "get" method. Thus an method to
be implemented might be "getRemainingLoan( purpose )" -- where the argument
"purpose" might be one of "installmentPayment", "interestCalculation",
"earlyRepayment". The way such a method might be implemented, expressed in an
informal way might be:

IF (purpose is "installmentPayment" or "interestCalculation")

return remainingLoan
ELSE
return remainingLoan +

earlyPaymentCharge(remainingLoan, remainingPeriod)

Informal design notations

The above statements are not correct Java statements -- they are an
informal way for a human to express a design for a part of a program. This
kind on structured, informal, English-like notation is called "Pseudocode",
and can be very useful for use in the informal design of computer
programs.

Once a design written informally appears to be right, it can then be coded


into correct Java statements and compiled and tested.

For situations such as the above, Java provides a mechanism for hiding variables from
other objects, thus requiring the use of "get" and "set" methods.

Notice that in the above method implementation design we assume there exists some
method that will calculate the early repayment charge given the remaining loan balance
and the period remaining for the loan. Such a method might be one an analyst decides
should not be made available to other objects. Once again, Java provides a method for
hiding such internal methods from being invoked by other objects.

Variables and methods not available to other objects are known as private. Those that
are available to other objects are known as public. The details of how and when to
implement public and private methods and variables are introduced in a later unit.

Life story of a `bouncing ball world' application

This section presents the development of a simple application running bouncing balls
inside an application window. The design and development of this application is
presented in a number of stages. Each stage presents a small increase in the
sophistication (and therefore complexity) of the application. In the real world many, or
perhaps, all of these stages would be jumped by an experienced modeller and
programmer, however, the small steps are presented to the learning and understanding
of how object-oriented software systems can be extended incrementally maintaining an
integrated and elegant system at each stage.

These examples illustrate many of the object concepts implemented in Java. Read over
the fine details of the Java statements, but don't worry about understanding every
semicolon or bracket. The detail aspects of the Java programming language are
gradually introduced in the remaining units of the module.
The role of this set of examples is both to illustrate Java object concepts and give you a
"feel" for incremental development of software systems.

The "Ball" class

The bouncing ball application has at its core a class "Ball". We wish to program a
system to have multiple bouncing balls.

The Ball class we develop below will illustrate the following object concepts in Java:

class
variable
method
method reply
method arguments

State and attributes

Each ball has the following state:

its current (X, Y) position in the window


its direction and amount of movement (direction and distance for X and Y
values for each move)
its colour
its size (i.e. a radius size)

Note on US spelling of "color"

Since Java was developed in the US, and they spell colour as "color", we
shall adopt the US spelling of "color" since some pre-written Java classes
refer to the term.

US spellings such as "color" and "center" are simply a feature of Java that
one has to accept.

This state corresponds to the following attributes:

x position
y position
color
radius size
x motion (we'll call this "dx" from the common maths terms)
y motion (we'll call this "dy")
So at present our class looks as follows:

class Ball

Attributes y

color

radius

dx

dy

Operations

Operations

We will wish to both interrogate and set the following attributes:

x position
y position
x motion (we'll call this "dx" from the common maths terms)
y motion (we'll call this "dy")

We shall define a "get" access method for each attribute:

getX
getY
getXMotion
getYMotion

As is common for two related values, we can define two "set" access methods to set the
(X, Y) position of a ball, and to set the (dx, dy) motion of a ball:

setXY
getMotion

We shall also define another method, that will move the Ball object by the values we set
for its X and Y motion

move
We will also need an operation to set up a new Ball object and an operation to display a
ball.

An operation to set up a new object is called a constructor. In Java a constructor is


implemented as a method with the same name as the class, so we shall call our
constructor operation simply "Ball".

For reasons we won't go into now, it is the convention to call the operation for an object
to display itself "Paint". So we shall provide our Ball object with a "Paint" operation.

Our Ball class now looks as follows:

class Ball

Attributes y

color

radius

dx

dy

Operations Ball

paint

move

getX

getY

getXMotion

getYMotion

setXY

setMotion

If we define the X and Y coordinates to be whole numbers, and also the X and Y motion
attributes to be whole numbers, we are able to describe each operation in terms of
Implementation in Java

To implement our Ball class in Java we need to write a source file whereby:

each attribute will become a Java variable (since we have no computed


attributes)
each operation will become a Java method

The Java source file "Ball.java" looks as follows, although for now we have replaced the
statements of each method with a comment. The full source file for "Ball.java" is
available for viewing.

// Ball.java

import java.awt.*;

// Class representing the MODEL of a ball

public class Ball

/////////////////////////// VARIABLES //////////////

// Ball is circle, with centre (x,y) and radius "radius"

int x;

int y;

int radius;

// each time ball moves it moves (dx, dy)

int dx;

int dy;

// colour of ball is "color" (note we use US spelling)

Color color;

///////////////////////// METHODS //////////////

// initialise new ball object

public Ball (int newX, int newY, int newRadius, int newXMotion, int
newYMotion)

{
x = newX;

y = newY;

radius = newRadius;

color = Color.blue; // default colour is blue

dx = newXMotion;

dy = newYMotion;

// display the ball (using location and color variables)

public void paint (Graphics g)

g.setColor(color);

g.fillOval(x,y,radius, radius);

// set the location of the centre of the ball

public void setXY(int newX, int newY)

x = newX;

y = newY;

public int getX()

return x;

public int getY()


{

return y;

public int getXMotion()

return dx;

public int getYMotion()

return dy;

public void setColor( Color newColor )

color = newColor;

public void setMotion( int newXMotion, int newYMotion )

dx = newXMotion;

dy = newYMotion;

public void move()

x = x + dx;

y = y + dy;

}
} // end of class definition

Perform activity 1 – Compilation of "Ball.java"

For simplicity we have used whole numbers (integers) for all variables, with the
exception of the colour. As you will explore in a later unit, in Java colours are
represented with objects of the class Color. Integers are indicated in Java by the term
int .

The form of Java methods

As you may recall from earlier in the unit, to design each Java method we need to
consider:

the return type (if any) of a method’s reply


the name of the method
a list of any arguments (and their types) required by the method

Methods that do not return any reply

Java uses the reserved word "void" to indicate that a method does not
return a reply.

Each of these is considered below (for now we will continue to ignore the statements to
be executed by each method).

The methods we have implement illustrate:

return method Java method implementation


type name

void Ball Ball (int newX, int newY, int newRadius, int
newXMotion, int newYMotion)

void Paint void paint (Graphics g)

void move void move()

int getX int getX()

int getY int getY()


int getXMotion int getXMotion()

int getYMotion int getYMotion()

void setXY void setXY(int newX, int newY)

void setMotion void setMotion( int newXMotion, int newYMotion )

We can see from the above table (and the Java source file) that each "get" method
returns an integer -- this makes sense since the role of "get" methods is to return the
value of an attribute (possibly after appropriate calculation). The two "set" methods both
require arguments: "setXY" requires the new X and Y values, and "setMotion" requires
the new "dx" and "dy" motion values.

The "Ball" constructor method requires the initial values for each attribute (except "color"
which for now we shall assume is blue). The "paint" methods requires an argument that
tells it which graphics object (i.e. which part of some window usually) to draw the
representation of the object. The "move" method returns no reply, and requires no
arguments -- it will use the values of its "dx" and "dy" variables to update the position of
its "x" and "y" variables.

The "BallWorld" classes

Now we have a Ball class, we need a class that creates a window on screen and a ball
object to display in that window. We will create an application class called BallWorld for
this purpose.

There are lots of technical details required to get an application class to create a
window and so on. We will not worry about these details in this example, but
concentrate on how Java implements the following concepts:

a variable that refers to an instance of a class (i.e. that refers to an object)


an application sending messages to a Ball object

Rather than immediately look at a complex version of class BallWorld dealing with more
than one bouncing ball, we shall first look at a simple BallWorld class, and look at how it
can be refined in stages into a more sophisticated version. The sequence of
refinements we shall go through are as follows:

Version 1: display a static Ball object


Version 2: display a Ball object in one place, then a second place
Version 3: display a moving Ball object
Version 4: display a moving Ball object that can "bounce" off the sides of
its window
Version 5: display 2 bouncing Ball objects
Version 6: display 2 bouncing Ball objects (but reducing code)
Version 7: display many bouncing Ball objects
Version 8: display a bouncing Ball, and a bouncing RandomBall

Each of these refinements illustrates either some object concept in Java, or some way
in which object-oriented software systems can be refined incrementally in a structured
way.

The "BallWorld" class - version 1

We shall design out BallWorld class version 1 to have the following variables and
methods:

class BallWorld

Attributes myBall

Operations main

BallWorld

paint

pause

As can be seen above, the BallWorld class will be implemented to have a single
variable, an object of the Ball class. It will implement each operation as a method.
When run version 1 of our BallWorld will simply show a graphical representation of a
Ball object in a window for a few seconds, and then the application will terminate. The
screen when the application runs should look as follows:

The "main" method required for Java applications

Every Java application requires one class to have a "main" method -- it is


by following the instructions in the "main" method that the Java run-time
interpreter knows which instruction to execute first.

As we shall investigate in a later unit, Java applets determine their first


instruction in a different way.

In a nutshell, for version1 of our BallWorld application we wish to do the following:

create a window of a certain size


show that window on screen
create an instance of a Ball class
display a representation of the current state (i.e. position, size and colour)
of the ball object in our window
pause for a short while (so we can see what the application has done)
terminate the application and close the window

Although the above list of actions has been written in a simple sequence, due to the
nature of object-oriented programming, and its implementation in the Java programming
language, some of these actions will be performed in one method, and others in another
and so on.

Each method does the following:

the "main" method creates a new BallWorld object and causes this
object's window to be shown on screen (as opposed to the window being
hidden)
the "BallWorld" method is the constructor method for the class BallWorld,
i.e. it does all the things necessary to set up (initialise) the application
For our version 1 of BallWorld, the method "BallWorld" defines the
dimensions of its window and also creates an instance of a Ball object
the "paint" method displays a representation of the BallWorld application
on the given graphics object (area of the window). For our version 1 of
BallWorld, the only thing we need to paint is our instance of a Ball object
the "pause" method causes the application to pause for a given number of
milliseconds -- this method allows you to slow down or speed up the
application (since each person's PC is set up in a different way, and will be
faster or slower according to such features and processor speed and
memory)

Implementation of BallWorld in Java - version 1

The Java source file "BallWorld.java" (version 1) looks as follows, although for now we
have replaced the statements of each method with a comment. The full source file for
"BallWorld.java - version 1" is available for viewing (and can be opened in the Kawa
editor).

// BallWorld.java

public class BallWorld extends Frame

/////////////////// variables ///////////

Ball myBall;

///////////////////// methods //////////

void main (String [] args)

// create and display window for a new application object

BallWorld ()

// set up window and create a new


//instance of class Ball
}

void paint(Graphics g)
{

// display things on window, pause,


//then terminate program
}

void pause(int numMilliseconds)

// pause for a given amount of time

// end of class definition

We shall not go into all the details of the implementation of the BallWorld methods
(although by the end of the module you will be able to understand all aspects of this
application). For now we shall look at particular statements of the BallWorld methods, to
illustrate object concepts in Java, and the process of incrementally refining a Java
application.

Perform activity 2 – Compilation and running of "BallWorld.java" - version 1

A closer look at the methods of "BallWorld.java"

Some fundamental object concepts are:

class
object (an instance of a class)
attribute
individuality
the creation of a new instance of a class

An of course, the object concept of the operation is implemented as a method in Java.

Each of these features is illustrated in the implementation of the BallWorld class.

The "BallWorld" method is implemented as:

////////// method SimpleBall ///////////


BallWorld ()

// set size and title of our application window

setSize(600, 400);

setTitle("Ball World");

// make "myBall" a reference to a new instance of ball

myBall = new Ball(100, 100, 50, 4, 5);

The second to last line shows the variable "myBall" referring to a new instance of the
"Ball" class -- being set up with centre (100,100), radius 50 and movement of (4, 5).
This line:

myBall = new Ball(100, 100, 50, 4, 5);

shows how to create an object in Java -- i.e. by the message "new <Classname>", in
this case "new Ball" passed with arguments to set up a new Ball object.

The method (i.e. the Ball method "Ball") returns a reply that is a reference to where this
new object has been created (some place in the computer's memory). The variable
"myBall" is given this reference, so "myBall" now refers to an instance of the Ball class.
The identifier of our variable, "myBall" is the way we can refer to this individual object.
The concept of individuality, and its implementation in the identifiers of Java variables is
important, since potentially we could have 2 instances of the Ball class, whose attributes
are the same, same centre coordinates, same radius, same colour, same movement
values, but they are still two different balls. If one were referred to by a variable "ball1"
and the other "ball2", we can still individually refer to each instance of the class Ball.
By the way, the "setSize" and "setTitle" statements in the "BallWorld" method simply
determine the size of the applications window (600 by 400 pixels), and the title of the
window ("Ball World").

The "BallWorld" class - version 2

We shall make a small change between versions 1 and 2 of our BallWorld class.
Version 2 will display the ball twice -- in different positions on the screen (and with a
long enough delay to make the two positions clear).

To do this we shall introduce a new variable, called "counter". This variable is to count
how many times we have painted our myBall object. This variable needs to be delared
of type "int" so we can stored whole numbers in it. Thus the beginning of our new
version of BallWorld will now looks as follows (don't worry about the "public" and
"private" for now):

public class BallWorld extends Frame

////////////////////////////////

////////// variables ///////////

////////////////////////////////

private Ball myBall;

// NEW NEW NEW

// a counter - so we can paint the ball more than once

private int counter;

We need to ensure that this variable is initialised with zero -- since when the application
starts we will not have painted myBall any times. Thus we need to change our BallWorld
constructor method to initialise our counter to zero:

////////// method BallWorld ///////////

private BallWorld ()

// set size and title of our application window

setSize(600, 400);
setTitle("Ball World");

// make "myBall" a reference to a new instance of ball

myBall = new Ball(100, 100, 50, 4, 5 );

// NEW NEW NEW - set out counter to zero

counter = 0;

As you may have realised, when our application executes and shows the window for out
BallWorld object, the "paint" method of BallWorld is automatically executed. So we can
put some more instructions in out BallWorld "paint" method, to use our "counter"
variable to move myBall and then ensure method "paint" is called again to display
myBall in its new positon.

The pseudocode (informal) representation of how we need to change our BallWorld


"paint" method is as follows (the first 2 steps as before):

draw myBall
pause
send myBall a "move" message
if we have visited method "paint" less than 2 times
call "repaint()" and add 1 to our counter
else
otherwise terminate the program

The "paint" method needs to be extended, so it sets the new (x, y) centre of the ball,
repaints the ball and delays so we can see the change.

////////// method paint ///////////

public void paint(Graphics g)

myBall.paint( g );

pause( 2000 );

// change ball position and increment counter

myBall.move()

// test counter, so will repaint again with new ball position

if( counter < 1 )


{

repaint();

counter = counter + 1;

else

System.exit(0);

Each time out BallWorld receives a "repaint()" message it will cause the "paint()"
method to be executed (we will not go into the reasons for sending a "repaint" message
rather than a "paint" message -- this is dealt with in a later unit).

The first time method "paint" is executed:

a representation of the ball is displayed at the position determined by the


initial settings (of 100, 100)
myBall.paint( g );
the application pauses
pause( 2000 );
we send the myBall object the message "move()"
myBall.move()
when myBall executes its "move()" method, it will add its movement
values (dx was 4, dy was 5) to the current (x,y) centre of the object. When
created, myBall had its centre initialised as (100, 100), so after the
execution of the "move()" method the centre of myBalls circle will become
(104, 105).
a test is made to see if "paint" has been executed before
if( counter < 1 )
this test succeeds (since "counter" is zero)
so we send a "repaint" message
repaint();
and also add 1 to our "counter"
counter = counter + 1;
so "counter" now replaces its previous value of 0 with the value 1

Upon receiving the "repaint" message, out BallWorld object will execute its "paint"
method again after clearing any previous graphics in the window (so the filled circle is
no longer visible). The second time method "paint" is executed:

a representation of the ball is displayed at its new position (of 104, 105)
myBall.paint( g );
the application pauses
pause( 2000 );
we send the myBall object the message "move()"
myBall.move()
when myBall executes its "move()" method, it will add its movement
values (dx was 4, dy was 5) to the current (x,y) centre of the object. Its
centre is (104, 105), so after the execution of the "move()" method the
centre of myBalls circle will become (108, 110).
a test is made to see if "paint" has been executed before
if( counter < 1 )
this test fails (since "counter" is 1)
so we terminate the application and close the window
System.exit(0);

At any point in time the screen looks much as it did version 1 of the application -- but as
you watch it you should see the fill circle change position. The full source file for
"BallWorld.java - version 2" is available for viewing (and can be opened in the Kawa
editor).

Perform activity 3 – Compilation and running of "BallWorld.java" - version 2

The "BallWorld" class - version 3

To make our ball move several times, we can simply change the test we perform in the
"paint" method. By changing the test to:

if( counter < 10 )

the application will continue to move and repaint myBall 10 times, rather than just once.

The full source file for "BallWorld.java - version 3" is available for viewing (and can be
opened in the Kawa editor).

Perform activity 4 – Compilation and running of "BallWorld.java" - version 3


The "BallWorld" class - version 4

If the ball keeps on moving its going to hit the edge of the window. Unless we add some
code to make it stop or bounce the filled circle will just disappear out of sight.

We know the size of the window, since we created it in the "BallWorld" constructor
method that creates a BallWorld object:

private BallWorld ()

// set size and title of our application window

setSize(600, 400);

setTitle("Ball World");

So the size of the window is 600 x 400 pixels. To make our code a little more general,
rather than refer to, say, 600 each time we wish to refer to the width of the window, we
will now introduce two new variables which store the values 600 and 400. Let's call
them "frameWidth" and "frameHeight". Now, if we wished to change the width of the
window we can just change the value in these variables once, and everywhere else in
the class where we refer to these variables remains unchanged -- as opposed to have
to find every occurrence of 600 and change to 800 if we wanted to make the window
wider.

So we need to declare our two new variables:

public class BallWorld extends Frame

////////// variables ///////////

// application variables

// NEW NEW NEW - variables for width and height of frame

public static final int frameWidth = 600;

public static final int frameHeight = 400;

The above demonstrates how it is possible to both declare a variable, and also initialise
it at the same time. We now have variable "frameWidth" set to 600 and "frameHeight"
set to 400. (Don’t worry about the "public static final" terms for now -- these will be
investigated in a later unit). We can now refer to these variables when we set the size of
our window:

private BallWorld ()
{

// set size and title of our application window

// NEW NEW NEW - now set using variables "frameWidth",


"frameHeight"

setSize(frameWidth, frameHeight);

setTitle("Ball World");

In order to make our ball bounce we need to test its X and Y location, and if it hits a side
of the window (top, bottom, left or right) we need to change the direction of the
corresponding "dx" or "dy" motion.

We can design our bounce tests and actions in pseudocode as follows:

if ( x value too small ) set the dx motion to the opposite direction

if ( x value too large ) set the dx motion to the opposite direction

if ( y value too small ) set the dy motion to the opposite direction

if ( y value too large ) set the dy motion to the opposite direction

We can refine our pseucode code to refer to our "frameWidth" and "frameHeight"
variables, for when the X and Y values are too large. We can also refine our
pseudocode design to use the "getX" and "getY" methods of myBall to refer to the
current X and Y values of myBall:

if ( myBall.getX() < 0) set the dx motion to the opposite direction

if ( myBall.getX() > frameWidth ) set the dx motion to the opposite direction

if ( myBall.getY() < 0 ) set the dy motion to the opposite direction

if ( myBall.getY() > frameHeight ) set the dy motion to the opposite direction

We can further refine our pseucode to refer the dx and dy motion of the ball from the
"getXMotion" and "getYMotion" methods. For example:

if ( myBall.getX() < 0) set new motion: -1 * myBall.getXMotion(), myBall.getYMotion

since multipling our current X motion by -1 will reverse it.

So in our "paint" method, after sending the "move" message, we can write Java
statements to implement our bounce actions:
public void paint(Graphics g)

myBall.paint(g);

myBall.move();

pause( 20 );

// NEW NEW NEW - change X or Y motion if ball touches side of


window

// check for left of frame collision (X value too small)

if ( myBall.getX() < 0 )

myBall.setMotion( -myBall.getXMotion(), myBall.getYMotion() );

// check for right of frame collision (X value too large)

if ( myBall.getX() > FrameWidth )

myBall.setMotion(-myBall.getXMotion(), myBall.getYMotion());

// check for top of frame collision (Y value too small)

if ( myBall.getY() < 0 )

myBall.setMotion(myBall.getXMotion(), -myBall.getYMotion());

// check for bottom of frame collision (Y value too large)

if ( myBall.getY() > FrameHeight )

myBall.setMotion(myBall.getXMotion(), -myBall.getYMotion());

// NEW NEW NEW - bounce a lot more times !

if (counter < 500)

counter = counter + 1;

repaint();

else

System.exit(0);

}
As you may also notice, the pause value has been shortened to 20, and we are going to
let myBall bounce 500 times all around the window. The full source file for
"BallWorld.java - version 4" is available for viewing (and can be opened in the Kawa
editor).

Perform activity 5 – Compilation and running of "BallWorld.java" - version 4

The "BallWorld" class - version 5

We shall now demonstrate a strength of object orientation -- the ease in which a


program designed to work with one object can be made to work with multiple objects.
For version 5 of our bouncing ball application we shall add a second, smaller, green
bouncing ball.

First, we need to declare another variable to refer to our new Ball object:

private Ball anotherBall;

Then we need to ensure that a new instance of the class Ball is created, and that out
"anotherBall" variable is made to refer to this new object. Let's make our new Ball object
smaller (radius 25) and start at a different position on screen (200, 200). We shall also
make our new Ball object start moving left and upwards (-3, -2) in small steps. We
create the new instance, and make "anotherBall" refer to this new instance in the
"BallWorld" constructor method:

anotherBall = new Ball(200, 200, 25, -3, -2);

anotherBall.setColor( Color.green );

As you can see, by also sending our "anotherBall" object a "setColor" message, we can
make it a green.

We now need to ensure that our second Ball object is displayed, moved and bounces
when necessary. This is done with changes in the "paint" method:

anotherBall.paint(g);

anotherBall.move();

// pause as before

...

// make "myBall" bounce as before


...

// make "anotherBall" bounce

if ( anotherBall.getX() < 0 )

anotherBall.setMotion( -anotherBall.getXMotion(),
anotherBall.getYMotion() );

if ( anotherBall.getX() > frameWidth )

anotherBall.setMotion(-anotherBall.getXMotion(),
anotherBall.getYMotion());

if ( anotherBall.getY() < 0 )

anotherBall.setMotion(anotherBall.getXMotion(), -
anotherBall.getYMotion());

if ( anotherBall.getY() > frameHeight )

anotherBall.setMotion(anotherBall.getXMotion(), -
anotherBall.getYMotion());

The full source file for "BallWorld.java - version 5" is available for viewing (and can be
opened in the Kawa editor).
When running version 5 of our BallWorld application should look as follows:

Perform activity 6 – Compilation and running of "BallWorld.java" - version 5

The "BallWorld" class - version 6

Although successful, for version 5 of our bouncing ball application we had to duplicate a
lot of lines to make each of the balls bounce. Therefore for version 6, we will not change
the behaviour of our software, but we will see how we can reduce duplicated code by
creating a new method in our BallWorld application.

We shall now create a new BallWorld method called "bounce". This method will require
an argument that is a reference to some Ball object, and the method will check the X
and Y position of the object, and change the object's motion in just the same way we
have written in our "paint" method. With such a "bounce" method we can remove all the
duplicated code from our "paint" method, and just call our "bounce" method once for
each ball.

The new method will look as follows:

  private void bounce(Ball ball)

// check for left of frame collision (X value too small)

if ( ball.getX() < 0 )

ball.setMotion( -ball.getXMotion(), ball.getYMotion() );

// check for right of frame collision (X value too large)

if ( ball.getX() > frameWidth )

ball.setMotion(-ball.getXMotion(), ball.getYMotion());

// check for top of frame collision (Y value too small)

if ( ball.getY() < 0 )

ball.setMotion(ball.getXMotion(), -ball.getYMotion());

// check for bottom of frame collision (Y value too large)

if ( ball.getY() > frameHeight )


ball.setMotion(ball.getXMotion(), -ball.getYMotion());

As can be see form the above, apart from calling the object reference "ball", the code is
just the same as before. When this "bounce" method is called, the "ball" reference will
be made to the same object as provided in the argument - so "bounce( myBall )" will
mean that "ball" refers to the same object as "myBall". When called with "bounce(
anotherBall )" then "ball" will refer to the same object as "anotherBall".

Our "paint" method can now be simplified to the following:

  public void paint(Graphics g)

myBall.paint(g);

myBall.move();

anotherBall.paint(g);

anotherBall.move();

pause( 20 );

// NEW NEW NEW - call method "bounce" with each ball reference

bounce( myBall );

bounce( anotherBall );

counter = counter + 1;

if (counter < 500)

repaint();

else

System.exit(0);

The full source file is available for viewing: BallWorld.java - version 6

Perform activity 7 – Compilation and running of "BallWorld.java" - version 6


The "BallWorld" class - version 7

Since we have made working with 2 Ball objects easy, we shall now generalise our
application to work with 5 balls. So when run our application will look something like the
following:

Rather than create a separate variable for each of 5 balls (since eventually we may wish
to create an application with 100s or 1000s of balls!), we shall use something called an
"array". The details of arrays are delt with in a later unit -- for now just understand that
they can stored references to as many objects as we wish.

So we need to declare our array variable to stored references to instances of the Ball
class:

private Ball balls[];

In out BallWorld constructor, we need to state the size of our array:

balls = new Ball[5];


We also need to make our array refer to five new Ball objects (we'll make them different
sizes, start at different positions, and move in different ways):

balls[0] = new Ball(100, 100, 50, 4, 5);

balls[1] = new Ball(200, 200, 25, -3, -2);

balls[2] = new Ball(50, 50, 5, 1, -1);

balls[3] = new Ball(200, 50, 10, -10, -15);

balls[4] = new Ball(75, 200, 75, -1, 1);

To distinguish them, we can make some of them different colours (we'll leave the first
instance, "balls[0]" as the default blue colour):

balls[1].setColor( Color.green );

balls[2].setColor( Color.red );

balls[3].setColor( Color.yellow );

balls[4].setColor( Color.green );

Now all we need to do is amend our "paint" method to paint, move and bounce each of
the objects referred to by the "balls" array. The "paint" method now looks as follows:

public void paint(Graphics g)

// NEW NEW NEW - display and move all 5 balls

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

balls[i].paint( g );

balls[i].move();

pause( 20 );

// NEW NEW NEW - call method "bounce" for all 5 balls

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

bounce( balls[i] );

counter = counter + 1;
if (counter < 500)

repaint();

else

System.exit(0);

Note that we are using a "loop" statement (which are introduce in a later unit) to send
the "paint" and "move" messages to each ball. Likewise, we are using a loop statement
to call method "bounce" with each object the "balls" array refers to.

The full source file for "BallWorld.java - version 7" is available for viewing (and can be
opened in the Kawa editor).

BallWorld version 7: Activity

Perform activity 8 – Compilation and running of "BallWorld.java" - version 7

The "BallWorld" class - version 8

The final version of our bouncing ball application illustrates two important object
concepts: inheritance and me

We shall add to application a new kind of ball, one that moves randomly. We shall call
this class RandomBall, and it will be an extension, a subclass of our existing Ball class.

The only different between our RandomBall class and our Ball class, shall be that
obects of our RandomBall class randomly change their direction as they move.
RandomBall, as a subclass of Ball automatically inherits all the variables and methods
of the Ball class. Since we wish to create a RandomBall class of objects that behaves
differently when it receives a "move" message than Ball objects, we need to create a
new version of the "move" method. By defining a new "move" method in our
RandomBall class, we shall override the "move" method that would be inherited.

Our new "move" method looks as follows:

public void move()

// 50% chance of chaning X motion


if( Math.random() > 0.5 )

dx = -dx;

// 50% chance of changing Y motion

if( Math.random() > 0.5 )

dy = -dy;

// move centre of object

x = x + dx;

y = y + dy;

Don't worry about the details, we simple have created 2 random tests, that mean there
is a 50% chance of this method reversing the X , and possibly also the Y, movement
values "dx" and "dy". The centre of the object (x, y) then has these movement values
added to it as usual.

Note on Math.random()

This is an example of a pre-written class and method provided by Sun.


There are many classes that have been created for common programming
tasks.

The "random()" method of the Math class simple uses a pseudo-random


number generator to provide a decimal value from zero, up to but not
including 1 (e.g. 0.54, 0.00, 0.99 etc.). Thus by testing if this value is > 0.5
we simulate a 50% probability to give our RandomBall random movement.

As usual, we shall provide a constructor with the same name as the class, RandomBall.
Since we are doing nothing different when creating a RandomBall than when creating a
Ball, we can use the inherited "Ball" constructor method to set the centre, radius and
movement variables. To refer to the inherited "Ball" constructor in the subclass
RandomBall, we use the Java reserved word "super" -- to indicate the direct superclass
of the RandomBall object.

Thus the constructor for RandomBall looks as follows (it simply pass the arguments on
to the inherited constructor method of Ball):

public RandomBall (int newX, int newY, int newRadius, int


newXMotion, int newYMotion)

// call the Ball constructor


super( newX, newY, newRadius, newXMotion, newYMotion );

Since we have no extra method for RandomBall objects, and no extra variables, the
whole definition of the RandomBall class consists of the two methods we've just looked
at. I.e. The full listing of the Java source file "RandomBall.java" is as follows:

// RandomBall.java

public class RandomBall extends Ball

public RandomBall (int newX, int newY, int newRadius, int


newXMotion, int newYMotion)

// call the Ball constructor

super( newX, newY, newRadius, newXMotion, newYMotion );

public void move()

// 50% chance of chaning X motion

if( Math.random() > 0.5 )

dx = -dx;

// 50% chance of changing Y motion

if( Math.random() > 0.5 )

dy = -dy;

// move centre of object

x = x + dx;

y = y + dy;

} // class
The only changes we need to make to our BallWorld class is to create a new variable
that refers to an object of class RandomBall, to initialise this variable (we'll make it black
so it stands out from the coloured ones), and to make sure it is painted, moved and
bounced in our "paint" method.

So do declare a variable "rBall" that can refer to an object of class RandomBall we add:

private RandomBall rBall;

To create a new object, and make variable "rBall" refer to it, and to make this object
black, we add the following to our "BallWorld" constructor:

rBall = new RandomBall(200, 200, 40, 5, 5);

rBall.setColor( Color.black );

To paint, move and bounce the ball, we add these lines to our "paint" method:

rBall.paint( g );

rBall.move();

and

bounce( rBall );

The full source file for "BallWorld.java - version 8" and "RandomBall.java" are available
for viewing (and can be opened in the Kawa editor).

Perform activity 9 – Compilation and running of "BallWorld.java" - version 8

Two forms of Java programs — Applications and applets

Most computer programming is concerned with the production of applications. An


application, as mentioned in Unit 01, supports the user in tasks not directly related to
the computer system. Examples of applications include word processors, we browsers
and spreadsheets. Application programs run on their own, as a separate software object
of an operating system such as Windows 95 or NT.

Another form of program is called an applet. An applet is a "mini-program", one that


relies on other software to support it. The term is usually -- but not always -- used to
refer to programs that are embedded in Web pages. The Java programming language
can be used to produce both applications and applets.
Java is not, on the whole, used for the development of system software (i.e. software for
doing tasks on the computer system, such as virus checkers, backup programs,
operating systems etc.). This is because Java is intended to be platform independent
(i.e., to work on any computer) and system programs by their very nature need to know
about the intimate details of the particular computer the system program runs on.

Most textbooks on Java are concerned very much with applet programming. This is
rather strange in a way, because application programming is so much more common
and more useful. However, the programming techniques required to produce an
application are the same in most ways to those used in applets. In this module we will
mostly be concerned with applet programming.

In the figures below, the first is a bouncing ball application , while the second is a
bouncing ball applet running inside a page being viewed with a web browser.

Applications and applets: Summary

An application is an independent program, with a useful function unrelated to the


software system.
An applet is a program that is embedded inside another.
A Java applet is usually part of a Web page.
Programming principles are the same -- both are computer programs.

Learning to program

As you start programming, you will find that your programs don't work. This is inevitable.
The role of the instructor is to show you how to make them work. However, you will
learn more if you put a good deal of effort into making them work yourself first. Often
you will not have enough information to do this very effectively, and you will have to rely
on a process of trial-and-error. This is perfectly normal in programming. At first, people
make simple errors with the syntax of the language.

Eventually the syntax will become second nature to you, and you won't even have to
think about it. Then you will be able to spend more time on looking for the logical errors,
that is, places where the programmer has told the computer to do something that is not
really what is required. The computer will follow the program's instructions slavishly, and
cannot be blamed when the program is incorrect.

Learning to program The best way to learn is by doing it.

You should not be afraid to try different things to see if they work. In fact much of
your learning will be through making mistakes, learning what those mistakes
were, and how to avoid such mistakes in the future. A faulty Java program will
never damage the computer.
Java concept map

Activity 1: Compilation of "Ball.java"

It is useful to place each version of the bouncing ball application in a different directory
(folder). Bounce1 for version 1, Bounce 2 for the second version etc.

(1) Click on the link Ball.java and then open the file. The file will be displayed in the
Kawa editor window.

(2) Add a comment at the top with your name and date: e.g.

// Kevin Boone 1/03/01

(3) Choose Save As from the File pull down menu of Kawa, and create a new
directory Bounce1 where you will save your file and then save it as Ball.java

(4) Compile the file into bytecode by choosing Compile from the Build pull down
menu of Kawa. You should get the message:

File Compiled….

No Errors ….

in the message window.


Discussion of Activity 1

Activity 1 :Compilation of "Ball.java"

(1) it is good practice to create a new directory for each version of a software

system you work on

(2) a useful skill for this module is the copying of code examples from web

pages etc. into text editors such as the Kawa editor and then saving into a

directory where you are creating a software system.

(3) up to date and meaningful comments make the development,

management and debugging of programs much more easy

(4) remember, you must always save a Java source file with the same name

as the class defined within, and with the extension ".java"

Note - ensure you have used an upper case "B" in the file name. The

compiler will complain with an error message if you have named your file

"ball.java" or "BALL.java" or some such file name.

(5) To compile Ball.java using Kawa choose click on Build , then choose

Compile from, the pull down menu of

If the compilation is successful you will see the message

Class Path -

.;c:\Kawa4.01\kawaclasses.zip;c:\jdk1.3….

File Compiled...

No Errors...

If there were any errors - fix them and re-compile

(6) after successful compilation you should now see the file "Ball.class"
This class is neither an applet nor application though, so we cannot execute

the class with some other classes.

Activity 2: Compilation and running of "BallWorld.java" - version 1

(1) Click on the link BallWorld.java and then open the file. The file will be displayed in
the Kawa editor window

(2) add a comment at the top of the file with your name and date

(3) save the file into your new directory Bounce1, calling the file "BallWorld.java"

(4) Compile the file into bytecode by choosing Compile from the Build pull down menu
of Kawa. You should get the message:

File Compiled….

No Errors ….

in the message window

If there were any errors - fix them and re-compile

(5) check the source file has successfully compiled by looking at the contents of the

directory

(6) now run the application by choosing Run from the Build pull down menu of Kawa

Discussion of Activity 2

Activity 2:Compilation and running of "BallWorld.java" - version 1

After completing steps (1), (2), (3) you should now have both "Ball.java" and
"BallWorld.java" in your

directory.
Again, ensure you have spelt the name of the file the same way as the class name,

i.e. getting the capital letters at the beginning of each word: "BallWorld.java" - not

"ballworld.java" or "ballWorld.java" or some such file name.

The contents of the your directory, for example "Bounce1" should

now be:

Ball.java

Ball.class

BallWorld.java

(5) after successful compilation you should now see the file "BallWorld.class"

(as well as the other "Ball.java", "Ball.class" and "BallWorld.java" files)

(6) now run the application by choosing Run from the Build pull down menu of Kawa

If you have been successful, a new window entitled "BallWorld" should have

appeared, showing a filled in circle (a graphic representation of our Ball object).

After about 2 seconds this window should have closed itself (i.e. the program

terminated and closed the window).

The screen should have looked as illustrated in the figure below:

If everything happens too fast -- i.e. the window appears and dissapears before

you have time to se what happened, you can change the length of the pause to

slow things down. Likewise, if things were too slow, you can change the length of

the pause, to speed things up.

Simply change the line:

pause( 2000 );

in the "BallWorld.java" file to have a larger or smaller value. Then recompile and
run the application.

Activity 3: Compilation and running of "BallWorld.java" - version 2

(1) create a new directory called "Bounce2", to store the files for version 2 of our
application

(2) copy the file "Ball.class" into this new directory

(3) open "BallWorld.java - version 2" into your Kawa editor by clicking on to the
BallWorld.java Version 2 link and then open the file. The file will be displayed in the
Kawa editor window.

(4) add a comment at the top of the file with your name and date

(5) save the file into your new directory, calling the file "BallWorld.java"

(6) compile the file "BallWorld.java" into bytecode

Hint: Use the Compile command from the pull down menu of Build
if the compilation is successful you will see the message

Class Path -

.;c:\ Kawa4.01\kawaclasses.zip;c:\jdk1.3... .
File Compiled...
No Errors...

(7) check the source file has successfully compiled by looking at the contents of the
directory

(8) now run the application by choosing Run from the Build pull down menu of Kawa
if you have been successful, a new window entitled "BallWorld" should have appeared,
showing a filled in circle (a graphic representation of our Ball object). After about 2
seconds or so the window will have closed itself (i.e. the program terminated and closed
the window).
You can change the value of the "pause(2000)" statement to speed up or slow down the
execution of the application.

Activity 3:Compilation and running of "BallWorld.java" - version 2


(1) So if you were working with the directory " Bounce1 " for version 1, now create a
directory " Bounce 2 " for version 2

(2) Since we will not be changing our Ball class, we can simply copy the compiled
bytecode "Ball.class" file into our new directory for version 2 of our bouncing ball
application.

(3) Click onot the " BallWorld.java - version 3 " link and then open the file. The file will
be displayed in the Kawa editor windows.

(4) add a command at the top of the file with your name and date

(5) save the file into your new directory Bounce2, calling the file " BallWorld.java "

you should now have both " Ball.class " and " BallWorld.java " in your directory

Again, ensure you have spelt the name of the file the same way as the class name, i.e.
getting the capital letters at the beginning of each word: "BallWorld.java" - not
"ballworld.java" or "ballWorld.java" or some such file name.

The contents of the your directory "Bounce2" should now be:

Ball.java

Ball.class

BallWorld.java

(6) compile the file "BallWorld.java" into bytecode

Hint: Use the Compile command from the pull down menu of Build
If the compilation is successful you will see the message
Class Path -
.;c:\ kawa4.01\ kawaclasses.zip;c:\jdk1.3... .
File Compiled...
No Errors...
if there were any errors - fix them and recompile

(7) after successful compilation you should now see the file "BallWorld.class"

(as well as the other "Ball.class" and "BallWorld.java" files)

(8) now run the application by choosing Run from the Build pull down menu of Kawa

If you have been successful, a new window entitled "BallWorld" should have appeared,
showing a filled in circle (a graphic representation of our Ball object). After about 2
seconds this window should display the circle in a new position, slightly down and to the
right of its original position. After another 2 seconds or so the window will have closed
itself (i.e. the program terminated and closed the window).
The screen should have looked as illustrated in the figure below (i.e. very similar to
version 1, except for the moving circle on screen).

As with version 1, you can change the value of the "pause( 2000 )" statement to speed
up or slow down the execution of the application.

Activity 4: Compilation and running of "BallWorld.java" - version 3

NOTE - you can either follow all the steps below, to create a completely new "bounce3"
directory and a new version of our BallWorld files, alternatively you can simply change
the version 2 "paint" method test from:

if( counter < 1 )

to

if( counter < 10 )

and recompile and run.

The steps to create a completely new version 3 directory are as follows:

(1) create a new directory called "bounce3", to store the files for version 2 of our
application

(2) copy the file "Ball.class" into this new directory

(3) Open "BallWorld.java - version 3" in your Kawa editor


if there were any errors - fix them and recompile

(4) add a comment at the top of the file with your name and date

(5) save the file into your new directory, calling the file "BallWorld.java"

(6) compile the file "BallWorld.java" into bytecode

(7) after successful compilation you should now see the file "BallWorld.class"

(as well as the other "Ball.class" and "BallWorld.java" files)

(8) now run application by choosing Run from the Build pull down menu of Kawa

Discussion of Activity 4

Activity 4:Compilation and running of "BallWorld.java" - version 3

Complete steps (1) .. (8)

(If you have been successful, a new window entitled "BallWorld" should have appeared,
showing a moving filled circle - this circle should move 10 times then the application
should terminate and the window close itself) .

The screen should have looked as illustrated in the figure below (i.e. vey similar to
versions 1 and 2, except for the moving circle on screen)

You may wish to change the value of the "pause (2000)" statement to speed up or slow
down the execution of the application. Why not try a value of 500 to speed up the
animation a little..

Activity 5: Compilation and running of "BallWorld.java" - version 4

(1) create a new "bounce4" directory and copy "Ball.class" into this new directory

(2) create the file "BallWorld.java" with version 4

(either by copying the version 4 listing into your editor, or making the changes described
in this unit)

(3) compile and run "BallWorld.java"


Activity 5:Compilation and running of "BallWorld.java" - version 4

When the application is run, your window should now show a filled blue circle bouncing
around the screen.

After about 30 seconds the application should terminate and the window close.

You may wish to change the pause value, or the counter test value, to speed up or slow
down the application, or make it bounce more or fewer times.

Discussion of Activity 5

Activity 5:Compilation and running of "BallWorld.java" - version 4

When the application is run, your window should now show a filled blue circle bouncing
around the screen.

After about 30 seconds the application should terminate and the window close.

You may wish to change the pause value, or the counter test value, to speed up or slow
down the application, or make it bounce more or fewer times.

Activity 6: Compilation and running of "BallWorld.java" - version 5

(1) create a new "bounce5" directory and copy "Ball.class" into this new directory

(2) create the file "BallWorld.java" with version 5

(either by copying the version 5 listing into your editor, or making the changes described
in this unit)

(3) compile and run "BallWorld.java"

Discussion of Activity 6

Activity 6:Compilation and running of "BallWorld.java" - version 5

When the application is run, your window should now show a filled blue circle bouncing
around the screen AND a second filled, smaller, green ball bouncing too.
The screen should look as follows:

After about 30 seconds the application should terminate and the window close.

Activity 7: Compilation and running of "BallWorld.java" - version 6

(1) create a new "bounce6" directory and copy "Ball.class" into this new directory

(2) create the file "BallWorld.java" with version 6

(either by copying the version 6 listing into your editor, or making the changes described
in this unit)

(3) compile and run "BallWorld.java"

Discussion of Activity 7

Activity 7:Compilation and running of "BallWorld.java" - version 6

This application should behave in the same way as version 5 -- but we now know that
the Java code is neater and contains less duplication.
Activity 8: Compilation and running of "BallWorld.java" - version 7

(1) create a new "bounce7" directory and copy "Ball.class" into this new directory

(2) create the file "BallWorld.java" with version 7

(either by copying the version 7 listing into your editor, or making the changes described
in this unit)

(3) compile and run "BallWorld.java"

Discussion of Activity 8

Activity 8:Compilation and running of "BallWorld.java" - version 7


This application should behave in a similar way to version 5 and 6, except that there
should be 5 balls, rather than 2, bouncing around the window.

The screen should look as follows:

Activity 9: Compilation and running of "BallWorld.java" - version 8

(1) create a new "bounce8" directory and copy "Ball.class" into this new directory
(2) Click onto the "BallWorld.java - version 8" link and then open the file. The file will be
displayed in the Kawa editor window.

(3) save the file into your new directory Bounce8, calling the file "BallWord.java"

(4) Click onto the RandomBall.java link and then open the file. The file will be displayed
in the Kawa editor window.

(5) save the file into your new directory Bounce8, calling the file "BallWorld.java"

(6) compile the file "RandomBall.java" into bytecode

(7) compile and run "BallWorld.java"

Discussion of Acivity 9

Activity 9:Compilation and running of "BallWorld.java" - version 8

The application should in a similar way to the previous one, except there should also be
a big, randomly ("wobbly") moving black circle in the centre of the window.

The window should look as follows:


Discussion topic 1 -- Portable Java programs

What features (there are several) of the Java programming language, and the way it is
implemented, make it easier to produce programs that are portable ?

Discussion topic 2 -- Limitations of Java programming language

The decision to make the language portable has led to compromises in other areas.
What are these compromises, and how important are they for different users and
software developers?

Discussion topic 3 -- Compilation versus interpretation

The JDK provides a Java interpreter. Other systems, such as some versions of
Symantec VisualCafe provide native code compilers for Java programs. What is the
difference between a compiler and an interpreter, and what situations would a
developer choose each?

Additional Content

No specific additional activities for this unit.


Students may wish to browse the web, especially the Java pages at Sun’s website
www.sun.com for more background information about the Java programming
language.

Unit Test

Now go online and complete the end of unit review questions

Recording your Learning Experience

In your Learning Journal write up your experience of your learning on this unit. Say what
you thought was good or bad, what you had difficulty understanding, and how you
resolved your problems.
Click on the mail icon and send your recorded learning experience to your professor.

Java source file listings

Ball.java
BallWorld.java - Version 1
BallWorld.java - Version 2
BallWorld.java - Version 3
BallWorld.java - Version 4
BallWorld.java - Version 5
BallWorld.java - Version 6
BallWorld.java - Version 7
RandomBall.java
BallWorld.java - Version 8