Anda di halaman 1dari 109

Java

Fundamentals
Introduction
Java is an Object Orientated programming language that is very popular
amongst commercial organizations to develop a wide range of applications from
small utilities to enterprise wide, mission critical systems.

In this module we will start at the beginning and help you through getting going
and developing your first applications.

If there is anything you need some extra assistance with just post a question on
the message board. Don’t forget to have a look though to see if you can help
anyone else.
Objectives

This module will give you a solid introduction to Java.

You will install the Java Software Development Kit.

And then set up your development environment.

Once everything is ready to go you will write your first Java program.

We will then take you through the core features of the Java programming
language.

Of course we will keep you busy with exercises and tests as you go through the
module.
Module Navigation

Java Fundamentals

Introduction

Objectives

What is Java

History of Java

Versions of Java

Getting Started

Installing Java

Your Enviroment

Alternative Enviroments

Your First Application

What Just Happened?

Java Basics

Class Libraries

JavaDocs

Third Party Libraries

Primitive Types

Input and Output

Printing Output

Reading Input

Exercise

Summary

Operators

Arithmetic Operators

Comparison Operators

Bitwise Operators

Making Decisions

Arrays

Looping

Execise One

Exercise Two

Summary

Objects

Java Objects

Syntax

Using Constructors

Using Objects
Packages & Imports

Casting

Exercise

Summary

Grouping Objects

Collections

Sets

Lists

Maps

Looping

Summary

Advanced Objects

Encapsulation

Inheritance

Polymorphism

Interfaces

Abstraction

Summary

Exercise

Error Handling

Exceptions

Syntax

Exercise

Summary

GUI

Files

Configuration Files

Recursion

Exercise

Exercise

Summary

Logging

Configuration

Using Loggers

Testing

Threads

Test

Summary
Introduction

One of the most important skills you will need to have as a good computer
programmer is a good background knowledge of everything that is involved in
software development. Whether you are conversing with somebody who will be
using the finished solution or the architect who produced the specification you
are following, you will come across generic terms that are used everyday in the
world of software development.

"Review this Use Case and produce a Sequence Diagram that implements the
Factory Pattern."

Obviously that will not be the entire conversation and asking questions is fine but
in order to operate effectively on a project you need to know a lot more than a
single programming language.

This module will give you some of that essential knowledge.

You will build on the concepts introduced here in later modules and you may
even be confronted with exercises

click here to add comments


The History of Java

Java evolved from a language called Oak and has actually been around for about
twenty years. Knowing its history is unlikely to change your career but you might
find it interesting to know a little about how we got to where we are today.

1. History of the World Wide Web


1.4. History of Java

At first glance, it may appear that Java was developed specifically for the world wide
web. However, interestingly enough, Java was developed independently of the web, and
went through several stages of metamorphosis before reaching its current status of de
facto programming language for the world wide web. Below is a brief history of Java
since its infancy to its current state.

1.4.1 Oak

According the Java FAQ, [Harold] Bill Joy, currently a vice president at Sun
Microsystems, is widely believed to have been the person to conceive of the idea of a
programming language that later became Java. In late 1970's, Joy wanted to design a
language that combined the best features of MESA and C. In an attempt to re-write the
UNIX operating system in 1980's, Joy decided that C++ was inadequate for the job. A
better tool was needed to write short and effective programs. It was this desire to invent a
better programming tool that swayed Joy, in 1991, in the direction of Sun's "Stealth
Project" - as named by Scott McNealy, Sun's president. [Harold]

In January of 1991, Bill Joy, James Gosling, Mike Sheradin, Patrick Naughton (formerly
the project leader of Sun's OpenWindows user environment), and several other
individuals met in Aspen, Colorado for the first time to discuss the ideas for the Stealth
Project. The goal of the Stealth Project was to do research in the area of application of
computers in the consumer electronics market. The vision of the project was to develop
"smart" consumer electronic devices that could all be centrally controlled and
programmed from a handheld-remote-control-like device. According to Gosling, "the
goal was ... to build a system that would let us do a large, distributed, heterogeneous
network of consumer electronic devices all talking to each other." With this goal in mind,
the stealth group began work. [O'Connell]

Members of the Stealth Project, which later became known as the Green Project, divided
the tasks amongst themselves. Mike Sheradin was to focus on business development,
Patrick Naughton was to begin work on the graphics system, and James Gosling was to
identify the proper programming language for the project. Gosling who had joined Sun in
1984, had previously developed the commercially unsuccessful NeWS windowing
system as well as GOSMACS - a C language implementation of GNU EMACS. He
began with C++, but soon after was convinced that C++ was inadequate for this particular
project. His extensions and modifications to C++ (also know as C++ ++ --), were the first
steps towards the development of an independent language that would fit the project
objectives. He named the language "Oak" while staring at an oak tree outside his office
window! The name "Oak" was later dismissed due to a patent search which determined
that the name was copyrighted and used for another programming language. According to
Gosling, "the Java development team discovered that Oak was the name of a
programming language that predated Sun's language, so another name had to be chosen."
[O'Connell] [Harold]

"It's surprisingly difficult to find a good name for a programming language, as the team
discovered after many hours of brainstorming. Finally, inspiration struck one day during
a trip to the local coffee shop" Gosling recalls. Others have speculated that the name Java
came from several individuals involved in the project: James gosling, Arthur Van hoff,
Andy bechtolsheim. [McCarthy]

There were several criteria that Oak had to meet in order to satisfy the project objective
given the consumer electronics target market. Given the wide array of manufacturers in
the market, Oak would have to be completely platform independent, and function
seamlessly regardless of the type of CPU in the device. For this reason, Oak was
designed to be an interpreted language, since it would be practically impossible for a
complied version to run on all available platforms. To facilitate the job of the interpreter,
Oak was to be converted to an intermediate "byte-code" format which is then passed
around across the network, and executed/interpreted dynamically. [O'Connell] [Harold]
[McCarthy]

Additionally, reliability was of great concern. A consumer electronics device that would
have to be "rebooted" periodically was not acceptable. Another important design
objective for Oak would then have to be high reliability by allowing the least amount of
programmer-introduced errors. This was the motivation for several important
modification to C++. The concepts of multiple-inheritance and operator overloading were
identified as sources of potential errors, and eliminated in Oak. Furthermore, in contrast
to C++, Oak included implicit garbage collection thereby providing efficient memory
utilization and higher reliability. Finally, Oak attempted to eliminate all unsafe constructs
used in C and C++ by only providing data structures within objects. [O'Connell]
[McCarthy]

Another essential design criterion was security. By design, Oak-based devices were to
function in a network and often exchange code and information. Inherently, security is of
great concern in a networked environment, especially in an environment as network
dependent as the conceived Oak-based systems. For this reason, pointers were excluded
in the design of Oak. This would theoretically eliminate the possibility of malicious
programs accessing arbitrary addresses in memory. [O'Connell] [McCarthy]
If Oak were to be widely accepted and used within the consumer electronics industry, it
would have to be simple and compact, so that the language could be mastered relatively
easily, and development would not be excessively complex. Some would argue that
Oak/Java is C++ done right, but the jury is still out on that...

In April of 1991, Ed Frank, a SPARCstation 10 architect, joined the green project. He led
the project's hardware development effort. In two months, they developed the first
hardware prototype known as star-seven (*7). The name *7 was somewhat demonstrative
of the project's objective. *7 was the key combination to press on any telephone to
answer any other ringing telephone on their network. In the meantime, Gosling was
beginning work on the Oak interpreter. By August of 1991, the team had a working
prototype of the user interface and graphical system which was demonstrated to Sun's co-
founders Scott McNealy and Bill Joy. [O'Connell]

Development of Oak, the green OS, the user interface, and the hardware continued
through the summer of 1992. In September of that year, the *7 prototype was complete
and demonstrated to McNealy and Joy. The prototype was a PDA-like (personal digital
assistant) device that Gosling described as a "handheld remote control." Patrick Naughton
proclaimed that "in 18 months, we did the equivalent of what 75-people organizations at
Sun took three years to do -- an operating system, a language, a toolkit, an interface, a
new hardware platform, ..." [O'Connell]

While impressive, the market was not conducive to this type of technology, as later
demonstrated by Apple's Newton PDA. The Green project's business planner, Mike
Sheradin, and hardware designer, Ed Frank had envisioned a technology similar to that of
Dolby Labs which would become the standard for the consumer electronics products.
[O'Connell]

1.4.2 FirstPerson

In November of 1992, the Green Project is incorporated under the name FirstPerson.
Given Java's lack of success in the consumer electronics industry, the company's
direction was somewhat uncertain. Under Sun's influence, the company began re-
evaluating its mission.

In early 1993, Time-Warner issued an RFP (request for proposal) for a set-top box
operating system and interactive, video-on-demand technology. FirstPerson identified
this area as a new target market, and began working in that direction. However, despite
FirstPerson's great efforts, SGI was granted the contract by Time-Warner. By mid 1993
Sun began negotiating with 3DO to provide a Java-based OS for their set-top box. The
negotiations were, however, unsuccessful and a deal was never made. FirstPerson was
left on its own without any viable business prospects. Another attempt by the company to
market its interactive TV technology fails when in February of 1994 a public launching
of their products is canceled. [O'Connell]
A Sun higher level review of FirstPerson determines the interactive TV market to be
immature in 1994. FirstPerson then shifts its focus yet again. Business plans are
submitted to Sun's executives for developing Oak-based on-line and CD-ROM
applications. Sun's response was not favorable, and FirstPerson was dissolved. Most of
FirstPerson's employees moved to Sun Interactive to digital video data servers. However,
a few individuals from FirstPerson still pursued the objective of finding a home for Java
in a networked desktop market. [O'Connell]

1.4.3 Java and the World Wide Web

In June of 1994, Bill Joy started the "Liveoak" project with the stated objective of
building a "big small operating" system. In July of 1994, the project "clicked" into place.
Naughton gets the idea of putting "Liveoak" to work on the Internet while he was playing
with writing a web browser over a long weekend. Just the kind of thing you'd want to do
with your weekend! This was the turning point for Java. [O'Connell]

The world wide web, by nature, had requirements such as reliability, security, and
architecture independence which were fully compatible with Java's design parameters. A
perfect match had been found. By September of 1994, Naughton and Jonathan Payne (a
Sun engineer) start writing "WebRunner," a Java-based web browser which was later
renamed "HotJava." By October 1994, HotJava is stable and demonstrated to Sun
executives. This time, Java's potential, in the context of the world wide web, is
recognized and the project is supported. Although designed with a different objective in
mind, Java found a perfect match in the World Wide Web. Many of Java's original design
criteria such as platform independence, security, and reliability were directly applicable
to the World Wide Web as well. Introduction of Java marked a new era in the history of
the web. Information provides were now given the capability to not only deliver raw data,
but also the applications that would operate on the data.

Sun formally announced Java and HotJava at SunWorld `95. Soon after, Netscape Inc.
announced that it would incorporate Java support in their browser. This was a great
triumph for Java since it was now supported by the most popular browser in the world.
Later, Microsoft also announced that they would support Java in their Internet Explorer
web browser, further solidifying Java's role in the World Wide Web.
Versions of Java

Knowing the history of Java may not change your career but it is important to
know your stuff when it comes to the different versions of Java. You need to be
aware of this because you might find yourself working on a project for a client
that has elected to use a version other than the one you are used to or even one
from a different manufacturer.

When it comes to the version of there are three main variables, the manufacturer,
the edition and the version number.

Java was invented by Sun Microsystems but other manufactures, including IBM,
also produce their own Java Virtual Machines, compilers and other tools.

There are two editions of Java, the Standard Edition (J2SE) and the Enterprise
Edition (J2EE). The Enterprise Edition is basically a set of technologies that
extend the Standard Edition. These technologies include those used in larger
system such as Enterprise Java Beans (EJBs).

The [standard edition] version number is the most complicated bit. Some
software vendors choose to name the versions of their products or use larger
numbers like the current year but Java version numbers tend to increment very
slowly. The first commonly available version of Java was 1.1 and was followed by
1.2 but 1.2 was considered such an improvement it became known as Java 2 or
J2SE. The next major version was 1.4 (known as J2SE 1.4) and most recently
came 1.5. This version introduced some new language features so the decision
was made to call it J2SE version 5.
To complicate things even further each of these versions has sub versions and
sub-sub versions. These are used for interim and maintenance releases.

It is always a good idea to check exactly which version you should be using when
joining a project team. It is common for project managers to not use the very
latest version, they will often use a version that has been around long enough for
any bug to have been fixed. For this reason we will be using version J2SE 1.5 for
this course but will be highlighting features that didn't exist in 1.4.

If that is clear then you are doing well but there is one other variable, the
enviroment. If you want to develop (or compile) Java applications you need the
Java Development Kit (JDK), if all you want to do is run Java applications you
only need the Java Runtime Enviroment (JRE).
Before attempting this exercise make sure that you have copied the code in the
preceding examples and got the servlets up and running.

• Create a HTML file with a form in it.


• Ask some multiple choice questions in the form.
• Write a servlet that processes the answers and returns a web page with
the results of the test.
• Show the correct solutions for all answers that were answered incorrectly.
• Use the GET method to send data to the servlet.

Note: Put the compiled class files in %Tomcat_Home%\webapps\jjolt\WEB-


INF\classes directory and HTML files in %Tomcat_Home%\webapps\jjolt\html
directory. In order to run the servlet, you need to add servlet entry in web.xml file.
The web.xml file is %Tomcat_Home%\webapps\jjolt\WEB-INF.

Once you have completed the exercise, zip all the files and submit them for
review.

Installing Java
The first step towards your first application is downloading Java, we are going to
use the Sun Microsystems J2SE 5.0 JDK
Visit the following page click on 'Download JDK 5.0 Update X' where X is the
latest version.
http://java.sun.com/javase/downloads/index_jdk5.jsp
You will need to agree to the license terms and select your platform.

It will also be a good idea to download the documentation from the same page
and install it locally because you are likely to be using it a lot!!!

Don't worry about downloading NetBeans, J2EE or the source code.

Once you have downloaded it, run the executable to install the JDK.
Your Enviroment

The next step is to ensure that you can use Java from your command prompt.

You need to make sure that the folder containing the Java executables is in your
'PATH' enviroment variable.

To test whether it is there already do the following:

1. Open a Command Prompt Window by clicking Start, going to All Programs


the Accessories then clicking Command Prompt.
2. type java -version
3. if you see java version "1.5.0_04" or similar then everything is fine,
if not continue with the following steps.
4. right-click on My Computer on your desktop and choose Properties.
5. click on the Advanced tab then click Enviroment Variables.
6. check in the list of variables (user and system) for a variable called
'JAVA_HOME', if it doesn't exist add it to the system variables.
7. ensure that the value of the JAVA_HOME variable is the path to the
directory where the you installed the JDK e.g. C:\Program
Files\Java\jdk1.5.0_04
8. check in the list of variables (user and system) for a variable called
'PATH', if it doesn't exist add it to the system variables.
9. add ';%JAVA_HOME%\bin' to the end of the value of the PATH variable.
10. now close the command prompt and try again and you should see java
version "1.5.0_04" or similar.

The next step is ensure that the Java executables can find your classes. We will
use another enviroment variable to hold this information.

1. using windows explorer create a new directory where you will store your
code e.g. c:\java_code
2. right-click on My Computer on your desktop and choose Properties.
3. click on the Advanced tab then click Enviroment Variables.
4. check in the list of variables (user and system) for a variable called
'CLASSPATH', if it doesn't exist add it to the system variables.
5. ensure that the value of the 'CLASSPATH' variable is the path to the
directory you just created

You should now be ready to write your first application. You may need to refer
back to this section if everything doesn't go to plan.
Your First Application

There a tradition amongst courses, books etc. that teach programming that the
first program you write simply prints out "Hello World" to the screen. We will stick
with that tradition.

Follow the steps below to write, compile and execute your first Java Application
and then we come back and review what we did.

1. Open Notepad
2. Copy and paste the following code into Notepad:

package firstapplication;
public class HelloWorld{
public static void main(String[] args){
System.out.println("Hello World");
}
}

3. Save the code in a file call HelloWorld.java in the directory


c:\java_code\firstapplication
4. Open a Command Prompt window and change to the directory
c:\java_code
5. Type javac firstapplication\HelloWorld.java and press enter
(you should just get a blank line - no errors).
6. Type java firstapplication.HelloWorld and press enter. You
should see Hello World.

Congatulations, you have just written your first Java application. We'll review
what we did in the next section.

What just Happened?

That wasn't too hard was it!

The first thing you need to know is that every line of java code ends in a
semicolon.

This means that you can make your code more readable by breaking it over
several lines without effecting the way it works or causing errors.
You will have probably already noticed that there are exceptions to the semicolon
rule. Most Java code is devided into blocks. A block is one or more lines of code
surrounded by braces (or curley brackets). The only lines of code that don't end
with semicolon are lines that begin or end a block.

Our Hello World application contains two blocks, the first one is a class identified
by the code public class HelloWorld. This block contains a second block
identified by the code public static void main(String[] args). This second block is a
method (also known as a function).

The function contains a single line of code:

System.out.println("Hello World");

As we known, Java is an Object Oriented language, that means that every line of
code you write will either define part of, or interact with at least one, object.
System is an object that is provided as part of the JDK. Out is actually another
object that is itself a property of the System object and finally println is a method
within the out object. This method expects one argument - a piece of text (a
String object).

You will notice that both our class and our method are prefixed by the word
public. This is how you can control whether or not other objects can access your
objects and methods, you will learn more about this later.

Before we go any further it is important to understand a couple of definitions.

Class - A model, template or blueprint for an object.


Object - An instance of a class.

To understand this imagine you have a class called Car. The Car class is only a
blueprint but if you create an instance then you would have an object
representing a car, you could then set the make, model and colour properties to
make a red BMW 3 series. You could then create other instances of the Car
class and set the make model and colour of each one without affecting the
others.

Java also provides a means to manipulate the template itself rather than each
instance. These properties and methods are identified by the key word static. Our
main method is static, this means that the Java Virtual Machine does not need to
create an instance of our class before it calls our methods.
The key word void simply means that our method does not return anything to the
code that called it.

You will notice that our main method can actually be an argument (or parameter).
Arguments are defined by two words, the first word specifies what type of object
the argument must be and the second word is the name that will be assigned to
argument, we would then be able to use the name to reference the argument
from within our code. The square brackets [ ] after the type indicates that our
method actually expects an array of String objects rather than just one. We'll
discuss arrays later.

The only line we haven't discussed is the first one! package firstapplication;.
When developing applications you may well end up with hundreds or even
thousands of classes. To keep them organised we can organise our classes into
packages and sub packages these packages relate directly to (and must be
the same as) folders within your operating system. The name of the class must
also match the name of the file it is in. For example a class called
SecondApplication in a the package com.jjpeople.training must be declared the
the file com\jjpeople\training\SecondApplication.java

The naming of files, folders, classes and packages is important. if they don't
match your code will not compile.

We used the javac executable to compile the class, you may have noticed that a
file with the extension .class was created in the same folder as your java file.

We then used the java executable to run the application.

Here's a tip for you. There are a lot of things that can go wrong even with the
smallest of applications. Whilst this application is working we now change some
things (one at a time) like the package, class or method names and try compiling
your modified code. Obviously it is going to fail but make a note of the errors you
get and what caused, that way if you have problems in the future you may
recognise the error and know where to start with fixing it.

One last thing before we move on. how did the java executable know which
method to call? We specified the class from the command prompt but at no point
did we specify which method to call. Well every java application always starts
with the same method, only the class you use to start your application need have
it but every application starts with the method public static void main(String[]
args).
Java Basics

So you have written your first application but there is a long way to go.

The next few sections will guide you through the basic building blocks of most
applications.

There is a lot to take in and you may find it easier to piece it all together by
reading the ahead a few sections and coming back to re-enforce your
understanding

Class Libraries

As you know Java is an object orientated language and that means you are
going to need objects for more or less everything you do. We used three objects
in our one line hello world application.

Imagine you want to write some text into a file and save it, you will need an
ojbect to hold the text but you also need an object that represents the file. Java
would be pretty hard work if you had to write the classes that these objects are
instances of.

Obviously you don't need to write all these classes they and many more are
provided as part of the JDK.

The J2SE 1.5.0 JDK comes with 3279 public classes that you can use within
your applications, obviously you can't hope to learn the names and features of all
of them but one of the biggest parts of learning Java is getting to know more or
less what is available to you otherwise you will spend your life re-inventing the
wheel.

Of course Sun provides extensive documentation on these classes. If you didn't


download and install it, you can find it at:
Java 2 Platform Standard Edition 5.0 API Specification
http://java.sun.com/j2se/1.5.0/docs/api/index.html
API is another term you will come across a lot. API stands for Application
Programming Interface. The interface basically means 'what you can see', a
mobile phone for example has a lot of compexities inside but the interface is
quite simple. An API is the interface to a class or library of classes available for
programming applications.

With this many classes in one API you can see the benefit of packages. It is a
good idea to read through the list of packages and their descriptions on the API
Specification home page even if it doesn't all make perfect sense at the
momment.

JavaDocs

The API documentation you reviewed is known as JavaDoc. This is the standard
way of documenting Java code.

Documenting your code is vital, the manager of every project you ever work on
will tell you that too. If you develop an application for a bank for example and
months after the project has finished and you have moved on the bank brings in
another developer to add a new feature, if you have not documented your
classes they could spent weeks trawling through you code trying to understand it.
Many project manager use automated tools that inspect every class to ensure it
is documented.

For this reason we are going to insist that every class you write as part of
this course is documented using JavaDoc. Any exercise solution that you
submit with code that is not documented will be rejected as incomplete.

Don't worry, it is not hard and will soon become second nature. To demonstrate
this we will JavaDoc our first application.

JavaDocs are actually generated from comments you add to you code as follows

package firstapplication;
/**
* Simple application that writes
* <code>Hello World</code> to the
* Standard Out
*
* @author Dave Finch
*/
public class HelloWorld{
/**
* This is the method that writes
* <code>Hello World</code> to the
* Standard Out
*
* @param args - An array of string arguments
* supplied on the command line
*/
public static void main(String[] args){
System.out.println("Hello World");
}
}

In Java you can add a comment on a single line by starting that line with two
slashes

public static void main(String[] args){


//this is a comment on a single line
System.out.println("Hello World");
}

Or over multiple lines by starting with slash star and ending with star slash, you
can put anything you like in between.

public static void main(String[] args){


/* this is a comment
spread over two lines */
System.out.println("Hello World");
}

JavaDoc comments simply start with two stars instead of one and have a star
begining each line. This should be placed before your class declaration and
every method.

To generate your documentation do the following:

1. open a command prompt window at the folder containing your


firstapplication package (c:\java_code)
2. execute the command javadoc -d docs firstapplication

The -d docs specifies where to generate the documentation


and firstapplication specifies which package to generate the
documentation for. You should now have a new folder containing your
documentation. open index.html to view it.

This is the most basic usage of the javadoc tool. It is actually very powerful, for
full documentation on it visit
Javadoc 5.0 Tool
http://java.sun.com/j2se/1.5.0/docs/guide/javadoc/index.html

Third Party Libraries

The libraries that come with the JDK are extensive but by no means exhaustive.

The great thing about the JDK is that it is free (unlike other development
enviroments like Microsoft's Visual Basic .Net). Another good thing about Java is
that is cross platform and very easy to package and distribute small libaries or
entire applications.

As a result a vast array of Java libraries or API's available for free. If you are
developing an application then chances are you can use some of these libraries
and save a lot of time and money. Making good use of the tools available to you
is an important part of being a good Java developer and we will be introducing
you to several different libaries throughout this course.

It is important to remember that not everybody wants to give away their hard work
and even if they do, the license terms will vary. Always respect the the license terms
and never use a third party API without checking with your project manager first.

Primitive Types

As we mentioned previously, you are going to need objects for more or less
everything you do. But not absolutely everything. A fundamental part of the Java
language are Primitive Types (or Primitives for short).

Primitives are the eight basic data types that everything else is built from. They
are not objects.

Primitives do not have properties or methods can only be used to one value of
their own type. When you use primitives they are automatically initialised to a
default value and can't be empty (or null).

The primitive types are boolean, byte char, short, int, long,
float and double.

A chart showing what can be store in each primitive type and how much memory
they use can be found here:
Language Fundamentals - Primitive Types
http://www.janeg.ca/scjp/lang/primitives.html

It is important to note that for each primitive there is class that allows you
to create objects that can be used to store the same value as their
associated primitive and also provide some useful utility methods but they
are not the same.

The classes have the same name as the associated primitive but with the fist
letter capitalised, with the exception of int and char which are actually
abbreviations of their full names Interger and Character.

As a general rule, if a primitive meets your needs then you should use it, only if it
doesn't should you use an object.

Input and Output

Most applications handle data in some way, shape or form and when you have
data the needs to be way off passing the information into the application and
getting it out again. Imagine a calculator that had no way to enter numbers or
view the result. There are numerous different ways of getting data in and
out including files, databases or over a network but the most basic way of getting
information in and out of your application is using your keyboard and the
command prompt on your monitor (known as the console).

Transfering data between your application and any of these locations in known
as input and output or I/O.

Java has the concept of standard input and output device where it will send
errors, for example. By default the standard input devices are your keyboard and
your console. over the next few sections we will experiment with standard I/O.

Printing Output

In our first application we printed 'Hello World' to standard out but we didn't
explain what happened in any detail.

Underpinning I/O in Java is the concept of streams. When watering your garden
it is a lot less hard work if you use a hose pipe to transfer the water from one end
of the garden to the other than if you were to use a watering can. Streams follow
the same basic principle to move data from one place to another.
To better understand this, read the following article.
The Standard I/O Streams
http://scv.bu.edu/Doc/Java/tutorial/java/system/iostreams.html

We'll consolidate what you have just read with an example after you have had an
intro to reading input.

Reading Input

Reading input is a little more complicated because there is no such thing as


System.in.readln(). we need to make use of a couple of classes from the java.io
package to achieve the desired result.

Read the following article


Reading input from console in Java
http://www.ericsson.com/mobilityworld/sub/open/technologies/open_development
_tips/docs/odt_reading_input_console_java

If you tried to run the example in this article you will know that it simply prompts
for input from the console and echos it back to you (unless you typed 'ok' or just
pressed enter).

The article is actually from Ericsson and targets people writing mobile phone
software but because Java is cross platform it applies equally well to us.

Although we will be covering all the features used in the code later, it is worth
talking you through what is actually going on.

1. The first line of code - import java.io.*;- lets the compiler know what
classes it needs to import and make available to our code. This statement
imports all the classes in the java.io package.
2. The code block beginning while(true) is actually an infinite loop. It is
only the break statement that causes the loop to end.
3. String objects can be created implicitly. For example
System.out.print("ECHO< "); actually creates a new String object
containing the value 'ECHO<'.
4. Note the statement if ("".equals(input)) . When comparing
objects it is very important to use an objects equals method. We will
discuss this further later.
5. Note how the comments explain why one approach was taken over an
alternative. Always comment your code.

Exercise - A Simple IO Application


Welcome to your first exercise. Throughout the course you will be faced with
exercises to consolidate what you have read and ensure we haven't missed
anything. Simply complete the task below and then click on the link to have your
work reviewed by a mentor. Before uploading your work ensure it is well
documented, it would also help if you could zip all your files up together. Don't
forget, if you have problems or questions just put a post on the message board.

Write an application that prompts the user for their first name and then their last
name. The application should then respond with 'Hello first & last name, what is
the weather like today? Once the user has answered, the application should
reply with 'Maybe tomorrow will be nicer'.

Summary

Nearly all applications gather information, manipulate it and send it back out
again. You can now do that.

You have also picked up some other useful snippets of information along the way
about controlling the flow of your application.

And finally (and this is only a guess) you can't wait to find out what is coming next

Operators

Operators are a fundamental part of any programming language. They are the
functions that can be performed on up to three primitive operands. Many
operators will become second nature to you very quickly.

View this page for a list of the operators available in Java


Overview of Java operators
http://java.sun.com/docs/books/tutorial/java/nutsandbolts/opsummary.html

Obviously a list of operators without any context will be difficult to remember so


you may like to bookmark that page. The next couple of pages will expand on a
few of the ones that warrant a bit more explanation.
Comparison Operators

One of the most common mistakes that people make when learning Java is in
the area of comparison.

int a = 1;
int b = 2;
if(a = b){
System.out.println("a equals b");
}else{
System.out.println("a doesn't equal b");
}

At first glance you might expect the comparison in this code to return false but in
fact it will return true because a single equals sign means 'assignment' and an
attempt to assign the value of the variable b to a will succeed. In order to
compare a and b we must use two equals signs (known as a 'double equals').

Another common mistake is to use a double equals to compare objects,


particularly Strings. This will not cause an error but will usually return false, true
will only be returned if the two objects are actually the very same object - not two
different objects that have the same value.

Ands and Ors

You can of course cover more than one comparison in a single statement using
and or or operators.

if(a == b || a == c){
System.out.println("a equals b or c");
}else{
System.out.println("a doesn't equal b or c");
}

if(a == b && b == c && c == d){


System.out.println("a equals b, c and d");
}else{
System.out.println("a doesn't equal b, c or d");
}
Although there is an order of precedence for all operators it is a good idea to use
parenthesise to ensure your code is readable.

if((a == b && b == c) || (a == c && c == d)){


System.out.println("a equals either b and c, or c and
d");
}

Bitwise Operators

Bitwise Operators are functions that can be applied to the binary values of the
variables you are operating on.

You will not use bitwise operators every day but it is useful to know about so that
you can read and understand code that does use them.

Read the following page


Shift and Logical
Operatorshttp://java.sun.com/docs/books/tutorial/java/nutsandbolts/op3.html

Bitwise and Bit Shift Operators


The Java programming language also provides operators that perform bitwise and bit
shift operations on integral types. The operators discussed in this section are less
commonly used. Therefore, their coverage is brief; the intent is to simply make you
aware that these operators exist.

The unary bitwise complement operator "~" inverts a bit pattern; it can be applied to any
of the integral types, making every "0" a "1" and every "1" a "0". For example, a byte
contains 8 bits; applying this operator to a value whose bit pattern is "00000000" would
change its pattern to "11111111".

The signed left shift operator "<<" shifts a bit pattern to the left, and the signed right shift
operator ">>" shifts a bit pattern to the right. The bit pattern is given by the left-hand
operand, and the number of positions to shift by the right-hand operand. The unsigned
right shift operator ">>>" shifts a zero into the leftmost position, while the leftmost
position after ">>" depends on sign extension.

The bitwise & operator performs a bitwise AND operation.

The bitwise ^ operator performs a bitwise exclusive OR operation.

The bitwise | operator performs a bitwise inclusive OR operation.


The following program, BitDemo, uses the bitwise AND operator to print the number "2"
to standard output.

class BitDemo {
public static void main(String[] args) {
int bitmask = 0x000F;
int val = 0x2222;
System.out.println(val & bitmask); // prints "2"
}
}

Making Decisions

We have already exposed you to the if statement but to expand on what you
have figured out we'll go through the decision making options.

The Test

The most important part of any decision is the actual test. The test is a
comparison that evaluates to either true our false.

if()...else

if and else are both statements that begin blocks of code so are usually followed
by an open brace but as you will remember, the braces are only required around
a block if it contains more than one statement.

if(a = b){
System.out.println("a equals b");
}else{
System.out.println("a doesn't equal b");
}

The code above will function exactly the same as the code below.

if(a = b)
System.out.println("a equals b");
else
System.out.println("a doesn't equal b");

Some project managers prefer the braces to be left in your code even if there is
only one statement because it is considered more readable.
If statements can be chained together at infinitum as follows.

if(a > b){


System.out.println("a is greater than b");
}else if(a > c){
System.out.println("a is greater than c");
}else if(a > d){
System.out.println("a is greater than d");
}

But the code above is not the same as the code below because in the code
above only one condition can apply but in the code below all the conditions to be
true.

if(a > b){


System.out.println("a is greater than b");
}
if(a > c){
System.out.println("a is greater than c");
}
if(a > d){
System.out.println("a is greater than d");
}

Conditional Expressions

Java provides support for you to combine a logical test and an assignment into a
single statement as follows.

System.out.println("a is " + (a <= b ? "not " : "") +


"greater than b");

In the above code, the test is followed by a question mark. The return values for
true and false appear after the question mark split by a colon (true before and
false after). In this example the word 'not' will only be included in the middle of
the sentence if a is less than or equal to b.

Switch Statement

Another powerful option for decision making is the switch statement.


Read about it here:
switch Statement - Overview

Java Notes
switch Statement - Overview
Purpose of switch: select one of many possible statements to
execute

The if statement allows you to select one of two sections of code to execute
based on a boolean value (only two possible values). The switch statement
allows you to choose from many statements based on an integer (including
char) or enum value.

Syntax example

Syntax

switch (expr) {

case c1:

statements // do these if expr == c1

break;

case c2:

statements // do these if expr == c2

break;

case c2:

case c3:

case c4: // Cases can simply fall thru.

statements // do these if expr == any of c's

break;

. . .

default:
statements // do these if expr != any above

Switch keywords
switch
The switch keyword is followed by a parenthesized integer expression,
which is followed by the cases, all enclosed in braces.. The switch
statement executes the case corresponding to the value of the
expression. Normally the code in a case clause ends with a break
statement, which exits the switch statement and continues with the
statement following the switch. If there is no corresponding case
value, the default clause is executed. If no case matched and there is
no default clause, execution continues after the end of the switch
statement.
case
The case keyword is followed by an integer constant and a colon. This
begins the statements that are executed when the switch expression
has that case value.
default
If no case value matches the switch expression value, execution
continues at the default clause. This is the equivalent of the "else" for
the switch statement. It is written after the last case be convention,
and typically isn't followed by break because execution just continues
out the bottom of switch if this is the last clause.
break
The break statement causes execution to exit to the statement after
the end of the switch. If there is no break, execution flows thru into
the next case. Flowing directly into the next case is almost always an
error.

Example - Random comment


String comment; // The generated insult.

int which = (int)(Math.random() * 3); // Result is 0, 1, or 2.

switch (which) {

case 0: comment = "You look so much better than usual.";

break;
case 1: comment = "Your work is up to its usual standards.";

break;

case 2: comment = "You're quite competent for so little


experience.";

break;

default: comment = "Oops -- something is wrong with this code.";

Equivalent if statement

A switch statement can often be rewritten as an if statement in a


straightforward manner. For example, the preceding switch statement could
be written as follows. When one of a number of blocks of code is selected
based on a single value, the switch statement is generally easier to read. The
choice of if or switch should be based on which is more readable.

String comment; // The generated insult.

int which = (int)(Math.random() * 3); // Result is 0, 1, or 2.

if (which == 0) {

comment = "You look so much better than usual.";

} else if (which == 1) {

comment = "Your work is up to its usual standards.";

} else if (which == 2) {

comment = "You're quite competent for so little experience.";

} else {

comment = "Oops -- something is wrong with this code.";

Defensive programming

Always include a default clause in your switch statement as a general policy


of defensive programming - assume there will be bugs in your code and
make sure they are caught.
Where to use switch?

The ability of switch to choose between many sections of code seems to


make it more powerful than if. However, selecting sections of code depending
on specific integer values turns out not to be very common. If you are
handling specific coded values (eg, the number of the button that was clicked
in a JOptionPane), or processing characters (whose codes are treated like
numbers), you may find it useful.

Efficiency? Some compilers can produce more efficient code for certain
switch statements than for equivalent if statements. I haven't bothered to
test the Java compiler because, if there is a speed difference, it would be
extremely small and the choice between switch and if should be based on
readability.

Comments on switch

Java's switch statement, which was taken directly from C++ to increase its
attractiveness to C++ programmers, is not well loved.

• No ranges. It doesn't allow ranges, eg case 90-100:. Many other


languages do.

• Integers only. It requires integers and doesn't allow useful types like
String. Many other languages do.

• Error-prone. It is error-prone and a common source of bugs -


forgetting break or default silently ignores errors. Some languages
have eliminated these dangerous situations.

Arrays

Array means 'arranged formally and indexed'. In computing terms an array is a


number of memory elements or references to memory elements grouped and
indexed.

This means that you can store a number of variables in an array and retrieve,
modify and replace them at will.
To see this in practice read the following page
Language Fundamentals - Arrays http://www.janeg.ca/scjp/lang/arrays.html

To clarify a couple of points:

1. Arrays are zero based. This means that if you have an array containing
ten variables, the first item will be at position (index) zero rather than one
and the last item will be a position nine.
2. The last example on that page uses loops. We will be moving on to loops
shortly.
3. You can't change the size of an array, you need to create a new array of
the required size and copy the elements from the old one.

Looping
A loop is simply a way of repeating the same piece of code multiple times. Why?
so that if you had an array you could apply the same process to all the elements
in the array.
Looping in Java is actually quite a big subject because, besides arrays, there are
many other groups or objects that you might to loop through. For this reason, in
this section we will only discuss basic for and while loops. We will cover other
options when we discuss the other options for grouping objects.

For Loops

The basic syntax for a for statement is as follows:

for ( [initialization]; [while condition]; [incrementer] ) {


your code;
}

Technically you can put what ever code you want in each of the three sections
but most commonly a for loop would look like this.

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


your code;
}

The initialization section contains code to initialize the variable you are going to
use as your counter.
The code while condition section gets evaluated each time round the loop and
must evaluate to true or false. Your code inside the loop block will only be run if
this code returns true.

The incrementer section gets evaluated each time round the loop and must not
return anything. This is where you increment your counter.

The above example will always loop 10 times, if you want to loop through an
array you would do the following:

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


your code;
}

While Loops

int i = 0;
while( i < myArray.length ) {
i++;
your code;
}

While loops only have one section, that section being equivalent to the while
section of a for loop. The above code will work exactly the same as the for loop
but in reality that is not the intended use of while loops.

A more appropriate use of a while loop would be as follows:

StringTokenizer st = new StringTokenizer("this is a test");


while (st.hasMoreTokens()) {
System.out.println(st.nextToken());
}

StringTokenizer is utility class that breaks a string into tokens using spaces (or
any other character you care to specify) so the output would be:

this
is
a
test
The fact that the StringTokenizer class has a hasMoreTokens method but no
method that returns the number of tokens makes the while loop more appropriate
in this case.

Any time you see a class used in an example like this it is a good idea to look it
up in the JDK documentation.

Exercise Looping Arguments

Write a simple class that iterates through all the arguments passed in on the
command line(not standard-input) and prints them out to the screen.
If no arguments are specified print a message explaining to the user that they
need to supply some arguments.
Remember to comment your code and handle any errors that may arise.

Exercise - Number Square

You have a seven year old daughter who is currently learning 'times tables'. To
help her, create an application that generates a number square like the one
below.
1 2 3 4
1 1 2 3 4
2 2 4 6 8
3 3 6 9 12
4 4 8 12 16
Your number square should have the numbers 1 to 10 across the top and down
the side. Since you are sending your output to the console don't worry about
colour but so that it looks neat and tidy make sure every cell contains 3
characters (if your number has less than three characters prefix it with spaces to
make up the numbers). Also use hyphens (-) to separate the rows and pipe
symbols (|) to separate the columns.
Your code should be flexible and by changing only few setting (values in static
variables) you should be able to produce any number square ( m x n ).

Summary

Well that's the basics. Now you know how to communicate with the user to get
data, how to manipulate that data using loops and decision statements and
present it back to the user.

You also know how to document your work.


Java Basics

So you have written your first application but there is a long way to go.

The next few sections will guide you through the basic building blocks of most
applications.

There is a lot to take in and you may find it easier to piece it all together by
reading the ahead a few sections and coming back to re-enforce your
understanding.

Java Objects
All the classes that we have written so far have only had static methods. This
means that although it is possible to create instances of these classes, those
instances would not have any properties or methods.
Before we go any further lets just confirm what exactly what properties and
methods are.
package methoddemo;
public class Car{
// A method
public void moveForward(int distance){
position += distance;
}
// A property
public int position = 1;
public static void main(String[] args){
Car myCar = new Car();
System.out.println("The position of the car is " +
myCar.position);
myCar.moveForward(3);
System.out.println("The new position of the car is " +
myCar.position);
}
}
In the main method of the above code we create an instance of a Car and then
call its property and method.
In OO terms a property is an attribute of an object. In the example above the
myCar object that is an instance of Car has a position attribute.
A method is an action of an object. The myCar object has a moveForward action
which expects one argument, that being the distance that the car is required to
move.
Read the following article to learn more about objects and instance methods.
Objects, Instance Methods, and Instance Variables
http://math.hws.edu/javanotes/c5/s1.html
Section 5.1

Objects, Instance Methods, and Instance Variables

OBJECT-ORIENTED PROGRAMMING (OOP) represents an attempt to make


programs more closely model the way people think about and deal with the world. In the
older styles of programming, a programmer who is faced with some problem must
identify a computing task that needs to be performed in order to solve the problem.
Programming then consists of finding a sequence of instructions that will accomplish that
task. But at the heart of object-oriented programming, instead of tasks we find objects --
entities that have behaviors, that hold information, and that can interact with one another.
Programming consists of designing a set of objects that somehow model the problem at
hand. Software objects in the program can represent real or abstract entities in the
problem domain. This is supposed to make the design of the program more natural and
hence easier to get right and easier to understand.

To some extent, OOP is just a change in point of view. We can think of an object in
standard programming terms as nothing more than a set of variables together with some
subroutines for manipulating those variables. In fact, it is possible to use object-oriented
techniques in any programming language. However, there is a big difference between a
language that makes OOP possible and one that actively supports it. An object-oriented
programming language such as Java includes a number of features that make it very
different from a standard language. In order to make effective use of those features, you
have to "orient" your thinking correctly.

5.1.1 Objects, Classes, and Instances

Objects are closely related to classes. We have already been working with classes for
several chapters, and we have seen that a class can contain variables and subroutines. If
an object is also a collection of variables and subroutines, how do they differ from
classes? And why does it require a different type of thinking to understand and use them
effectively? In the one section where we worked with objects rather than classes,
Section 3.8, it didn't seem to make much difference: We just left the word "static" out
of the subroutine definitions!

I have said that classes "describe" objects, or more exactly that the non-static portions of
classes describe objects. But it's probably not very clear what this means. The more usual
terminology is to say that objects belong to classes, but this might not be much clearer.
(There is a real shortage of English words to properly distinguish all the concepts
involved. An object certainly doesn't "belong" to a class in the same way that a member
variable "belongs" to a class.) From the point of view of programming, it is more exact to
say that classes are used to create objects. A class is a kind of factory for constructing
objects. The non-static parts of the class specify, or describe, what variables and
subroutines the objects will contain. This is part of the explanation of how objects differ
from classes: Objects are created and destroyed as the program runs, and there can be
many objects with the same structure, if they are created using the same class.

Consider a simple class whose job is to group together a few static member variables. For
example, the following class could be used to store information about the person who is
using the program:

class UserData {
static String name;
static int age;
}

In a program that uses this class, there is only one copy of each of the variables
UserData.name and UserData.age. There can only be one "user," since we only
have memory space to store data about one user. The class, UserData, and the variables
it contains exist as long as the program runs. Now, consider a similar class that includes
non-static variables:

class PlayerData {
String name;
int age;
}

In this case, there is no such variable as PlayerData.name or PlayerData.age,


since name and age are not static members of PlayerData. So, there is nothing much
in the class at all -- except the potential to create objects. But, it's a lot of potential, since
it can be used to create any number of objects! Each object will have its own variables
called name and age. There can be many "players" because we can make new objects to
represent new players on demand. A program might use this class to store information
about multiple players in a game. Each player has a name and an age. When a player
joins the game, a new PlayerData object can be created to represent that player. If a
player leaves the game, the PlayerData object that represents that player can be
destroyed. A system of objects in the program is being used to dynamically model what is
happening in the game. You can't do this with "static" variables!

In Section 3.8, we worked with applets, which are objects. The reason they didn't seem to
be any different from classes is because we were only working with one applet in each
class that we looked at. But one class can be used to make many applets. Think of an
applet that scrolls a message across a Web page. There could be several such applets on
the same page, all created from the same class. If the scrolling message in the applet is
stored in a non-static variable, then each applet will have its own variable, and each
applet can show a different message. The situation is even clearer if you think about
windows, which, like applets, are objects. As a program runs, many windows might be
opened and closed, but all those windows can belong to the same class. Here again, we
have a dynamic situation where multiple objects are created and destroyed as a program
runs.
An object that belongs to a class is said to be an instance of that class. The variables that
the object contains are called instance variables. The subroutines that the object contains
are called instance methods. (Recall that in the context of object-oriented programming,
method is a synonym for "subroutine". From now on, since we are doing object-oriented
programming, I will prefer the term "method.") For example, if the PlayerData class,
as defined above, is used to create an object, then that object is an instance of the
PlayerData class, and name and age are instance variables in the object. It is
important to remember that the class of an object determines the types of the instance
variables; however, the actual data is contained inside the individual objects, not the
class. Thus, each object has its own set of data.

An applet that scrolls a message across a Web page might include a subroutine named
scroll(). Since the applet is an object, this subroutine is an instance method of the
applet. The source code for the method is in the class that is used to create the applet.
Still, it's better to think of the instance method as belonging to the object, not to the class.
The non-static subroutines in the class merely specify the instance methods that every
object created from the class will contain. The scroll() methods in two different
applets do the same thing in the sense that they both scroll messages across the screen.
But there is a real difference between the two scroll() methods. The messages that
they scroll can be different. You might say that the method definition in the class
specifies what type of behavior the objects will have, but the specific behavior can vary
from object to object, depending on the values of their instance variables.

As you can see, the static and the non-static portions of a class are very different things
and serve very different purposes. Many classes contain only static members, or only
non-static. However, it is possible to mix static and non-static members in a single class,
and we'll see a few examples later in this chapter where it is reasonable to do so. You
should distiguish between the source code for the class, and the class itself. The source
code determines both the class and the objects that are created from that class. The
"static" definitions in the source code specify the things that are part of the class itself,
whereas the non-static definitions in the source code specify things that will become part
of every instance object that is created from the class. By the way, static member
variables and static member subroutines in a class are sometimes called class variables
and class methods, since they belong to the class itself, rather than to instances of that
class.

5.1.2 Fundamentals of Objects

So far, I've been talking mostly in generalities, and I haven't given you much idea what
you have to put in a program if you want to work with objects. Let's look at a specific
example to see how it works. Consider this extremely simplified version of a Student
class, which could be used to store information about students taking a course:

public class Student {


public String name; // Student's name.
public double test1, test2, test3; // Grades on three tests.

public double getAverage() { // compute average test grade


return (test1 + test2 + test3) / 3;
}

} // end of class Student

None of the members of this class are declared to be static, so the class exists only for
creating objects. This class definition says that any object that is an instance of the
Student class will include instance variables named name, test1, test2, and
test3, and it will include an instance method named getAverage(). The names and
tests in different objects will generally have different values. When called for a particular
student, the method getAverage() will compute an average using that student's test
grades. Different students can have different averages. (Again, this is what it means to
say that an instance method belongs to an individual object, not to the class.)

In Java, a class is a type, similar to the built-in types such as int and boolean. So, a class
name can be used to specify the type of a variable in a declaration statement, the type of a
formal parameter, or the return type of a function. For example, a program could define a
variable named std of type Student with the statement

Student std;

However, declaring a variable does not create an object! This is an important point,
which is related to this Very Important Fact:

In Java, no variable can ever hold an object.


A variable can only hold a reference to an object.

You should think of objects as floating around independently in the computer's memory.
In fact, there is a special portion of memory called the heap where objects live. Instead of
holding an object itself, a variable holds the information necessary to find the object in
memory. This information is called a reference or pointer to the object. In effect, a
reference to an object is the address of the memory location where the object is stored.
When you use a variable of class type, the computer uses the reference in the variable to
find the actual object.

In a program, objects are created using an operator called new, which creates an object
and returns a reference to that object. For example, assuming that std is a variable of
type Student, declared as above, the assignment statement

std = new Student();

would create a new object which is an instance of the class Student, and it would store
a reference to that object in the variable std. The value of the variable is a reference to
the object, not the object itself. It is not quite true, then, to say that the object is the "value
of the variable std" (though sometimes it is hard to avoid using this terminology). It is
certainly not at all true to say that the object is "stored in the variable std." The proper
terminology is that "the variable std refers to the object," and I will try to stick to that
terminology as much as possible.

So, suppose that the variable std refers to an object belonging to the class Student.
That object has instance variables name, test1, test2, and test3. These instance
variables can be referred to as std.name, std.test1, std.test2, and
std.test3. This follows the usual naming convention that when B is part of A, then
the full name of B is A.B. For example, a program might include the lines

System.out.println("Hello, " + std.name + ". Your test grades


are:");
System.out.println(std.test1);
System.out.println(std.test2);
System.out.println(std.test3);

This would output the name and test grades from the object to which std refers.
Similarly, std can be used to call the getAverage() instance method in the object by
saying std.getAverage(). To print out the student's average, you could say:

System.out.println( "Your average is " + std.getAverage() );

More generally, you could use std.name any place where a variable of type String is
legal. You can use it in expressions. You can assign a value to it. You can even use it to
call subroutines from the String class. For example, std.name.length() is the
number of characters in the student's name.

It is possible for a variable like std, whose type is given by a class, to refer to no object
at all. We say in this case that std holds a null reference. The null reference is written in
Java as "null". You can store a null reference in the variable std by saying

std = null;

and you could test whether the value of std is null by testing

if (std == null) . . .

If the value of a variable is null, then it is, of course, illegal to refer to instance
variables or instance methods through that variable -- since there is no object, and hence
no instance variables to refer to. For example, if the value of the variable std is null,
then it would be illegal to refer to std.test1. If your program attempts to use a null
reference illegally like this, the result is an error called a null pointer exception.

Let's look at a sequence of statements that work with objects:


Student std, std1, // Declare four variables of
std2, std3; // type Student.
std = new Student(); // Create a new object belonging
// to the class Student, and
// store a reference to that
// object in the variable std.
std1 = new Student(); // Create a second Student object
// and store a reference to
// it in the variable std1.
std2 = std1; // Copy the reference value in std1
// into the variable std2.
std3 = null; // Store a null reference in the
// variable std3.

std.name = "John Smith"; // Set values of some instance variables.


std1.name = "Mary Jones";

// (Other instance variables have default


// initial values of zero.)

After the computer executes these statements, the situation in the computer's memory
looks like this:

This picture shows variables as little boxes, labeled with the names of the variables.
Objects are shown as boxes with round corners. When a variable contains a reference to
an object, the value of that variable is shown as an arrow pointing to the object. The
variable std3, with a value of null, doesn't point anywhere. The arrows from std1
and std2 both point to the same object. This illustrates a Very Important Point:
When one object variable is assigned
to another, only a reference is copied.
The object referred to is not copied.

When the assignment "std2 = std1;" was executed, no new object was created.
Instead, std2 was set to refer to the very same object that std1 refers to. This has some
consequences that might be surprising. For example, std1.name and std2.name are
two different names for the same variable, namely the instance variable in the object that
both std1 and std2 refer to. After the string "Mary Jones" is assigned to the
variable std1.name, it is also true that the value of std2.name is "Mary Jones".
There is a potential for a lot of confusion here, but you can help protect yourself from it if
you keep telling yourself, "The object is not in the variable. The variable just holds a
pointer to the object."

You can test objects for equality and inequality using the operators == and !=, but here
again, the semantics are different from what you are used to. When you make a test
"if (std1 == std2)", you are testing whether the values stored in std1 and std2
are the same. But the values are references to objects, not objects. So, you are testing
whether std1 and std2 refer to the same object, that is, whether they point to the same
location in memory. This is fine, if its what you want to do. But sometimes, what you
want to check is whether the instance variables in the objects have the same values. To do
that, you would need to ask whether "std1.test1 == std2.test1 &&
std1.test2 == std2.test2 && std1.test3 == std2.test3 &&
std1.name.equals(std2.name)".

I've remarked previously that Strings are objects, and I've shown the strings "Mary
Jones" and "John Smith" as objects in the above illustration. A variable of type
String can only hold a reference to a string, not the string itself. It could also hold the
value null, meaning that it does not refer to any string at all. This explains why using
the == operator to test strings for equality is not a good idea. Suppose that greeting is
a variable of type String, and that the string it refers to is "Hello". Then would the test
greeting == "Hello" be true? Well, maybe, maybe not. The variable greeting
and the String literal "Hello" each refer to a string that contains the characters H-e-l-l-
o. But the strings could still be different objects, that just happen to contain the same
characters. The function greeting.equals("Hello") tests whether greeting
and "Hello" contain the same characters, which is almost certainly the question you
want to ask. The expression greeting == "Hello" tests whether greeting and
"Hello" contain the same characters stored in the same memory location.

The fact that variables hold references to objects, not objects themselves, has a couple of
other consequences that you should be aware of. They follow logically, if you just keep
in mind the basic fact that the object is not stored in the variable. The object is
somewhere else; the variable points to it.
Suppose that a variable that refers to an object is declared to be final. This means that
the value stored in the variable can never be changed, once the variable has been
initialized. The value stored in the variable is a reference to the object. So the variable
will continue to refer to the same object as long as the variable exists. However, this does
not prevent the data in the object from changing. The variable is final, not the object.
It's perfectly legal to say

final Student stu = new Student();

stu.name = "John Doe"; // Change data in the object;


// The value stored in stu is not changed!
// It still refers to the same object.

Next, suppose that obj is a variable that refers to an object. Let's consider what happens
when obj is passed as an actual parameter to a subroutine. The value of obj is assigned
to a formal parameter in the subroutine, and the subroutine is executed. The subroutine
has no power to change the value stored in the variable, obj. It only has a copy of that
value. However, that value is a reference to an object. Since the subroutine has a
reference to the object, it can change the data stored in the object. After the subroutine
ends, obj still points to the same object, but the data stored in the object might have
changed. Suppose x is a variable of type int and stu is a variable of type Student.
Compare:

void dontChange(int z) { void change(Student s) {


z = 42; s.name = "Fred";
} }

The lines: The lines:

x = 17; stu.name = "Jane";


dontChange(x); change(stu);
System.out.println(x); System.out.println(stu.name);

output the value 17. output the value "Fred".

The value of x is not The value of stu is not


changed by the subroutine, changed, but stu.name is.
which is equivalent to This is equivalent to

z = x; s = stu;
z = 42; s.name = "Fred";

5.1.3 Getters and Setters

When writing new classes, it's a good idea to pay attention to the issue of access control.
Recall that making a member of a class public makes it accessible from anywhere,
including from other classes. On the other hand, a private member can only be used in
the class where it is defined.
In the opinion of many programmers, almost all member variables should be declared
private. This gives you complete control over what can be done with the variable.
Even if the variable itself is private, you can allow other classes to find out what its value
is by providing a public accessor method that returns the value of the variable. For
example, if your class contains a private member variable, title, of type String, you
can provide a method

public String getTitle() {


return title;
}

that returns the value of title. By convention, the name of an accessor method for a
variable is obtained by capitalizing the name of variable and adding "get" in front of the
name. So, for the variable title, we get an accessor method named "get" + "Title", or
getTitle(). Because of this naming convention, accessor methods are more often
referred to as getter methods. A getter method provides "read access" to a variable.

You might also want to allow "write access" to a private variable. That is, you might
want to make it possible for other classes to specify a new value for the variable. This is
done with a setter method. (If you don't like simple, Anglo-Saxon words, you can use the
fancier term mutator method.) The name of a setter method should consist of "set"
followed by a capitalized copy of the variable's name, and it should have a parameter
with the same type as the variable. A setter method for the variable title could be
written

public void setTitle( String newTitle ) {


title = newTitle;
}

It is actually very common to provide both a getter and a setter method for a private
member variable. Since this allows other classes both to see and to change the value of
the variable, you might wonder why not just make the variable public? The reason is
that getters and setters are not restricted to simply reading and writing the variable's
value. In fact, they can take any action at all. For example, a getter method might keep
track of the number of times that the variable has been accessed:

public String getTitle() {


titleAccessCount++; // Increment member variable titleAccessCount.
return title;
}

and a setter method might check that the value that is being assigned to the variable is
legal:

public void setTitle( String newTitle ) {


if ( newTitle == null ) // Don't allow null strings as titles!
title = "(Untitled)"; // Use an appropriate default value
instead.
else
title = newTitle;
}

Even if you can't think of any extra chores to do in a getter or setter method, you might
change your mind in the future when you redesign and improve your class. If you've used
a getter and setter from the beginning, you can make the modification to your class
without affecting any of the classes that use your class. The private member variable
is not part of the public interface of your class; only the public getter and setter
methods are. If you haven't used get and set from the beginning, you'll have to contact
everyone who uses your class and tell them, "Sorry guys, you'll have to track down every
use that you've made of this variable and change your code to use my new get and set
methods instead."

A couple of final notes: Some advanced aspects of Java rely on the naming convention
for getter and setter methods, so it's a good idea to follow the convention rigorously. And
though I've been talking about using getter and setter methods for a variable, you can
define get and set methods even if there is no variable. A getter and/or setter method
defines a property of the class, that might or might not correspond to a variable. For
example, if a class includes a public void instance method with signature
setValue(double), then the class has a "property" named value of type double,
and it has this property whether or not the class has a member variable named value.

Syntax

There are a number of different options when declaring classes, methods and
properties. For example we have already learned that we can prefix methods
with static to make it a method of the class rather than the object instance. These
options are called modifiers.

For a list and description of all the available modifiers, read this page.
Modifiers http://www.csci.csusb.edu/dick/samples/java.glossary.html#Modifiers

Modifiers will become clearer as you practice using them, if the mentors think you
should have used different modifiers they will let you know.

1. Modifiers
2. default_modifier::=In the absence of any modifiers fields are associated
with objects and are visible to all classes in a package, and accessible by
a subclass in the same package only.
3. public::modifier=A public variable or function can be accessed in any
other class.
4. private::=modifierA private variable or function can only be accessed its
own class.
5. protected::modifier=A degree of hiding lie between public and private,
subclasses and classes in the same package have access to these items. --
unwise since any class can claim to be a member of the same package!
Note for C++ programming, the C++ protected is the Java 1.0
private_protected. (Thanks to Andrew who correct this July 2007)
6. private_protected::=`A private protected field or function can be
accessed by any subclass, but can not be used otherwise', -- in Java 1.0
only, and equivalent to the C++ protected. This is deprecated by 1.5.
7. static::=A variable or functions associated with a class rather than with
the objects of the class.

Note for C programmers. In C a static variable declared in a functions is


the same variable each time you call it. This is not available in Java. In C a
static variable declared outside a function is shared by the set of functions
in the same file and following the declaration an hidden from other
functions. In Java a static variable is shared by all functions in that class.
Whether other classes can access it depend on whether it is private, public,
and/or protected. A Java variable that is nonstatic is something that is not
found in C. Each object in the class has its own variable, and all functions
refer to that particular variable. The variable is created as part of the object
and deleted with it.

In Java instance variables are the same each time you call them. A variable
or function is declared to be static when it associated with the class of
objects rather than a particular object in that class. This means that a static
function can not refer any data in an object - because it has no object. It
also means that static data is essentially shared in common by every object
but only stored in a single place. If you are in doubt about whether some
data should be static or not - ask yourself how many times it occurs: once
per class(static) or once per object(not static) or many time per object (its
in a different class!).

8. final::=once initialized it can not be changed. A variable(a field of a class


or object) is declared final when you want it to keep its initial value for
ever. It makes it a constant variable. A class is declared as final if it can
not be extended.
9. native::=Preprogrammed in another language and running as machine
code. For a tutorial on a way to integrate C functions into Java methods
see [ index.html ]
10. synchronized::=Only one thread can execute this at a time. A method or
block of code is marked as synchronized if only one thread of control can
be in it at a time. Other threads are locked out. The code is reentrant. It
protects resources from interference by multiple access at one time.
11. abstract::method=A method that must exist for objects in a class but is
fully defined only in subclasses,
12. abstract::class=A class with one or more abstract methods.
13. abstract::=not concrete, not yet implemented, deferred, prototypical. An
abstract method is one that is defined in classes derived from this class.
All subclasses have a version as defined in the base class or also declare it
as abstract. Certain methods can not be abstract: constructors, static,
private, final, native, synchronized, plus those that override superclass
methods. An abstract method makes the whole class abstract. A class that
inherits an abstract method and does not override it is also an abstract
class. An abstract class can not be used to construct new objects. You can
only call an abstract method via an object in a class that has extended the
abstract class and defined all the abstract methods.
14. threadsafe::= If another thread excuting this code at the same time can
not change the value of a variable then the variable is threadsafe and the
compiler may do clever things with it to make the code faster or smaller..
15. transient::=something that does last longer than a function call. If an
object can exist longer than a given applet....is persistent.... then its
transient data does not have to be preserved when a function exits.

Using Constructors

Constructors are a special kind of method that you can only, and must, call when
creating an instance of a class (or constructing an object). Constructors are
methods with the same name as the class and no return type. The purpose of
constructors is to allow the developer that every instance of a class is initialised
in the appropriate manner.

Here are a few tips on constructors:

1. If you don't provide your class with a constructor, it will inherit the default
(no argument) one from java.lang.Object (the default base object that all
other objects extend).
2. You may have multiple constructors as long as they all take different
arguments. For example you could have one constructor that expected
one String and a second that expected two Strings.
3. If you define a constructor that expects arguments then you will not inherit
the default constructor from java.lang.Object.

Example:
package methoddemo;
public class Car{
/**
* This constructor ensures that the car
* is given a starting position.
*/
public Car(int position){
this.position = position;
}
// A method
public void moveForward(int distance){
position += distance;
}
// A property
public int position = 0;
public static void main(String[] args){
Car myCar = new Car(7);
System.out.println("The position of the car is " +
myCar.position);
myCar.moveForward(3);
System.out.println("The new position of the car is " +
myCar.position);
}
}

In the code above we have added one constructor that expects one argument.
The presence of this constructor means that it is not possible to create a Car
object without specifying an initial position.

Note how we use the keyword this to refer to this instance of Car and
differentiate from the argument of the same name.

Using Objects

So far all the properties of the objects we have used in our example have either
been primitives or objects that are part of the JDK. As we know the theory behind
OO is that you should use classes to model the real world objects that your
application manipulates.

If you where to pick any object on your desk and then analyse it you would
realize that it is made up of numerous other objects. For example my mobile
phone has a battery, a display, several keys or buttons, a speaker and a
microphone, most of those are in turn made up of smaller objects and many have
associated actions (I can press a button for example).

When designing OO applications we should mimic real world structures as


closely as is practical but also be careful not to go to overboard. Obviously if you
started your application with an object representing an atom, you would end up
with a very complex application and would require a lot of knowledge.

package methoddemo;
public class Car{
/**
* Construct a new car setting its position and the size of each
wheel
*
*/
public Car(int position, int wheelDiameter){
this.position = position;
wheels[0] = new Wheel(wheelDiameter);
wheels[1] = new Wheel(wheelDiameter);
wheels[2] = new Wheel(wheelDiameter);
wheels[3] = new Wheel(wheelDiameter);
}
/**
* move forward by rotating the wheels
*
*/
public void moveForward(int miles){
long inches = miles * 63360;
//asume all wheels have the same diameter
double rotaions = inches / (wheels[0].diameter * Math.PI);
for(int i=0;i<wheels.length;i++){
wheels[i].rotate(rotaions);
}
position += miles;
}
public int position = 0;
public Wheel[] wheels = new Wheel[4];
/**
* simple main method to demonstrate the intended use of this class
*
*/
public static void main(String[] args){
Car myCar = new Car(0,17);//17 inch wheels
myCar.moveForward(1); //inches in a mile
System.out.println("The wheels rotated "
+myCar.wheels[0].rotations+" time in one mile");
}
}

The above code demonstrates how multiple objects can be used in conjunction
with each other.

Packages & Imports

A couple of things that we have brushed over a bit are packages and imports.
Packages

We know that packages are a way of grouping related classes and that package
names must match the names of the folders containing those classes but it is
also worth understanding that in the future you may well wish to use a library that
you created on a previous project on your current one (as long as it is not the
property of your previous client). But if both applications use the same package
name you will have problems because when you import classes the compiler will
look for the package rather than the class and then look in the package for the
class, if you have duplicate package names then the class may not be in the first
package the compiler finds.

The recognised convention for package names is your internet domain name in
reverse, followed by the project name and then optional you can break your
classes in logical groups. Package names should also be in lower case. For
example the package for our first application should really be
com.jjpeople.firstapplication rather than just firstapplication. That way if you give
your code to another organization and they also have a firstapplication there will
not be any conflict.

Imports

In order to make use of another class with yours you need to import it. The
exceptions to this rule are:

1. The class is in the same package as your class.


2. The class is part of java.lang package.
3. You use the fully qualified name of the class within your code.

Import statements appear after the package statement and before the class
statement. The syntax for an import statement is simply import
your.package.name.classname; if you want to import multiple classes from
a single package you can simply replace the classname with an asterisk.

Always keep your import statments tidy. If you stop using a class, remove
the import statment.

Casting

No we are not looking for people to star in a movie. Casting is the process of
converting an object of type to another type that is a subclass of the current type.

We know that one class can extend another class and all classes are extended
from Object.
We also know that it is often useful to treat an object as the type of object that it
extends. But when we have been working an object in this way we often need a
way to get it back to its original type. This is where we use casting.

A common use of casting is when working with lists. A list (java.util.List) is


capable of holding objects of any type (it would be pretty limited if it couldn't) but
in order to achieve this its add method has to accept an argument of type
java.lang.Object, because all classes extend Object every instance of every class
is an Object so it can be passed into the add method. The list does not know (or
care) what sub-type the object is so when we call the get method of a list to
retrieve an item we are given it back as an Object. Usually we need to return it to
its original type using casting as follows.

public Human findOldest(Arraylist family){


Human oldest = null;
for(int i=0;i<family.size();i++){
Human familyMember = (Human)family.get(i);
if(oldest == null || familyMember.age > oldest.age){
oldest = familyMember;
}
}
return oldest;
}

In the above code the cast statement is highlighted. Simply specify the required
type in parenthesise in front of the statement that returns the value you wish to
cast.

You can also cast primitives but because they are not objects you need to refer
to the documentation to see which types can be cast to each other (either
implicitly or explicitly).

The following article expands on casting and includes a primitive casting matrix
Casts & Mixing Primitive Types
http://www.particle.kth.se/~lindsey/JavaCourse/Book/Part1/Java/Chapter02/casts
Mixing.html

Casts & Mixing Primitive Types JavaTech


Course Map
Chapter 2
Introduction
Essentials
Structure
Keywords
Primitive Types
Comments
Literals
Expressions
Operators
Statements
Casts & Mixing
Strings
Console Output
Demo
Exercises

Supplements
Conditional: if-else
Repetitions
Flow Control
Java vs C/C++
JVM Instructions 1

About JavaTech
Codes List
Exercises
Feedback
References
Resources
Tips
Topic Index
Course Guide
What's New

Converting one type of data into another must follow the rules of
casting. If a conversion results in the loss of precision, as in an int
value converted to a short, then the compiler will issue an error
message unless an explicit cast is made.

To convert type AA data into type BB data, put the type BB name in
parentheses in front of the type AA data:

AA a = aData;
BB b = (BB)a; // cast type AA to type BB

For example, to convert integer data to floating point:

int i=0;
float f;
f=(float)i; // Cast int as float

Expressions can promote to a wider type without an explicit cast:

int i=1;
long j=3L; // Literals are int types so require L
suffix
j=i; // OK

However, you can not assign a value to a more narrow type without
an explicit cast:

i=j; // Error in assigning long to int


i=(int)j; // OK

So a data type with lower precision (fewer bits) can be converted to


a type of higher precision without explicit casting. To convert a
higher precision type to a lower precision, however, an explicit cast
is required or the compiler will flag an error.

Note that when you cast a value of a wider type down to a more
narrow type, such as an int value to a byte variable, the upper
bytes will be truncated. That is, the lowest order byte in the int
value will be copied to the byte value.

Primitive Type Conversion Table

Below is a table that indicates to which of the other primitive types


you can cast a given primitive data type. The symbol C indicates
that an explicit cast is required since the precision is decreasing.
The symbol A indicates that the precision is increasing so an
automatic cast occurs without the need for an explicit cast. N
indicates that the conversion is not allowed.

int
long
float
double
char
byte
short
boolean
int
-
A
A*
A
C
C
C
N
long
C
-
A*
A*
C
C
C
N
float
C
C
-
A
C
C
C
N
double
C
C
C
-
C
C
C
N
char
A
A
A
A
-
C
C
N
byte
A
A
A
A
C
-
A
N
short
A
A
A
A
C
C
-
N
boolean
N
N
N
N
N
N
N
-
The * asterisk indicates that the least significant digits may be lost
in the conversion even though the target type allows for bigger
numbers. For example, a large value in an int type value that uses
all 32 bits will lose some of the lower bits when converted to float
since the exponent uses 8 bits of the 32 provided for float values.

Mixed Types in an Expression

If an expression holds a mix of types, the lower precision or


narrower value operand is converted to a higher precision or wider
type. This result then must be cast if it goes to a lower precision
type:

float x,y=3;
int j,i=3;
x= i*y; // OK since i will be promoted to
float
j= i*y; // Error since result is a float
value
j= (int)(i*y) // OK

The process of converting a value to a wider or higher precision


integer or floating point type is called "numeric promotion". The
Java VM specification states the following rules for promotion in
an expression of two operands, as in x+i:

• If either operand is of type double, the other is converted to


double.
• Otherwise, if either operand is of type float, the other is
converted to float.
• Otherwise, if either operand is of type long, the other is
converted to long.
• Otherwise, both operands are converted to type int.

Exercise - Using Objects


This exercise will allow you to demonstrate what you have learned about objects.

Develop a class to represents a human. The head, arms and legs should be
properties of the human and should be represented by separate objects. All of
your objects should have at least three properties and one method. Ensure that
the head, arms and legs can only be constructed from with the same
package. The human should include a walk method that uses the legs to actually
move.

Summary

Now you should be starting to see everything starting to come together.

We have actually started to do Object Orientated Programming and have put to


use some of the things we have covered previously.

In the main method of the human, create an instance of a human and set the
properties so that it looks like you.

Finally produce a UML class diagram that explains how your classes relate to
each other.
Assume that relations between Human and Arm or Leg are compositions. Be
careful creating your constructor in Human class. Understand well what
composition means.

Summary

Now you should be starting to see everything starting to come together.

We have actually started to do Object Orientated Programming and have put to


use some of the things we have covered previously.
Grouping Objects

We have already looked at arrays, but they are only the tip of the iceberg when it
comes to working with groups of objects.

When confronted with a challenge, the fact that you need to work with a group of
objects will become apparent quickly but the best way to manage that group will
require further analysis and more importantly knowledge of the options available.

Over the next few sections we will look at the main alternatives, and the benefits
of each.

Note that if you are working with multiple primitives then an array will usually be
the best option because the other options would require you to wrap your
variables in an object.

Collections

The Collection interface is the root of the Collections Hierarchy and provides
basic functionality used by Lists and Sets.

When initializing a collection you do not need to specify a size (although you
can), you can simple use the add method to add items to your collection. It also
provides methods to retrieve the size or an iterator to assist with looping.

Read more about the collection interface in the JDK documentation


Collection http://java.sun.com/j2se/1.5.0/docs/api/java/util/Collection.html

Collection is an interface so it can't be instantiated directly.

Interface Collection<E>
All Superinterfaces:
Iterable<E>
All Known Subinterfaces:
BeanContext, BeanContextServices, BlockingQueue<E>, List<E>, Queue<E>,
Set<E>, SortedSet<E>
All Known Implementing Classes:
AbstractCollection, AbstractList, AbstractQueue, AbstractSequentialList,
AbstractSet, ArrayBlockingQueue, ArrayList, AttributeList,
BeanContextServicesSupport, BeanContextSupport, ConcurrentLinkedQueue,
CopyOnWriteArrayList, CopyOnWriteArraySet, DelayQueue, EnumSet,
HashSet, JobStateReasons, LinkedBlockingQueue, LinkedHashSet, LinkedList,
PriorityBlockingQueue, PriorityQueue, RoleList, RoleUnresolvedList, Stack,
SynchronousQueue, TreeSet, Vector
public interface Collection<E>
extends Iterable<E>

The root interface in the collection hierarchy. A collection represents a group of objects,
known as its elements. Some collections allow duplicate elements and others do not.
Some are ordered and others unordered. The JDK does not provide any direct
implementations of this interface: it provides implementations of more specific
subinterfaces like Set and List. This interface is typically used to pass collections
around and manipulate them where maximum generality is desired.

Bags or multisets (unordered collections that may contain duplicate elements) should
implement this interface directly.

All general-purpose Collection implementation classes (which typically implement


Collection indirectly through one of its subinterfaces) should provide two "standard"
constructors: a void (no arguments) constructor, which creates an empty collection, and a
constructor with a single argument of type Collection, which creates a new collection
with the same elements as its argument. In effect, the latter constructor allows the user to
copy any collection, producing an equivalent collection of the desired implementation
type. There is no way to enforce this convention (as interfaces cannot contain
constructors) but all of the general-purpose Collection implementations in the Java
platform libraries comply.

The "destructive" methods contained in this interface, that is, the methods that modify the
collection on which they operate, are specified to throw
UnsupportedOperationException if this collection does not support the operation. If
this is the case, these methods may, but are not required to, throw an
UnsupportedOperationException if the invocation would have no effect on the
collection. For example, invoking the addAll(Collection) method on an unmodifiable
collection may, but is not required to, throw the exception if the collection to be added is
empty.

Some collection implementations have restrictions on the elements that they may contain.
For example, some implementations prohibit null elements, and some have restrictions on
the types of their elements. Attempting to add an ineligible element throws an unchecked
exception, typically NullPointerException or ClassCastException. Attempting to
query the presence of an ineligible element may throw an exception, or it may simply
return false; some implementations will exhibit the former behavior and some will exhibit
the latter. More generally, attempting an operation on an ineligible element whose
completion would not result in the insertion of an ineligible element into the collection
may throw an exception or it may succeed, at the option of the implementation. Such
exceptions are marked as "optional" in the specification for this interface.

This interface is a member of the Java Collections Framework.

Many methods in Collections Framework interfaces are defined in terms of the equals
method. For example, the specification for the contains(Object o) method says:
"returns true if and only if this collection contains at least one element e such that
(o==null ? e==null : o.equals(e))." This specification should not be construed to
imply that invoking Collection.contains with a non-null argument o will cause
o.equals(e) to be invoked for any element e. Implementations are free to implement
optimizations whereby the equals invocation is avoided, for example, by first comparing
the hash codes of the two elements. (The Object.hashCode() specification guarantees
that two objects with unequal hash codes cannot be equal.) More generally,
implementations of the various Collections Framework interfaces are free to take
advantage of the specified behavior of underlying Object methods wherever the
implementor deems it appropriate.

Since:
1.2
See Also:
Set, List, Map, SortedSet, SortedMap, HashSet, TreeSet, ArrayList,
LinkedList, Vector, Collections, Arrays, AbstractCollection

Method Summary
boolean add(E o)
Ensures that this collection contains the specified element (optional
operation).
boolean addAll(Collection<? extends E> c)
Adds all of the elements in the specified collection to this collection
(optional operation).
void clear()
Removes all of the elements from this collection (optional
operation).
boolean contains(Object o)
Returns true if this collection contains the specified element.
boolean containsAll(Collection<?> c)
Returns true if this collection contains all of the elements in the
specified collection.
boolean equals(Object o)
Compares the specified object with this collection for equality.
int hashCode()
Returns the hash code value for this collection.
boolean isEmpty()
Returns true if this collection contains no elements.
Iterator<E> iterator()
Returns an iterator over the elements in this collection.
boolean remove(Object o)
Removes a single instance of the specified element from this
collection, if it is present (optional operation).
boolean removeAll(Collection<?> c)
Removes all this collection's elements that are also contained in the
specified collection (optional operation).
boolean retainAll(Collection<?> c)
Retains only the elements in this collection that are contained in the
specified collection (optional operation).
int size()
Returns the number of elements in this collection.
Object[] toArray()
Returns an array containing all of the elements in this collection.
<T> T[] toArray(T[] a)
Returns an array containing all of the elements in this collection; the
runtime type of the returned array is that of the specified array.

Method Detail
size
int size()
Returns the number of elements in this collection. If this collection contains more
than Integer.MAX_VALUE elements, returns Integer.MAX_VALUE.
Returns:
the number of elements in this collection

isEmpty
boolean isEmpty()
Returns true if this collection contains no elements.
Returns:
true if this collection contains no elements

contains
boolean contains(Object o)
Returns true if this collection contains the specified element. More formally,
returns true if and only if this collection contains at least one element e such that
(o==null ? e==null : o.equals(e)).
Parameters:
o - element whose presence in this collection is to be tested.
Returns:
true if this collection contains the specified element
Throws:
ClassCastException - if the type of the specified element is incompatible with
this collection (optional).
NullPointerException - if the specified element is null and this collection does
not support null elements (optional).

iterator
Iterator<E> iterator()
Returns an iterator over the elements in this collection. There are no guarantees
concerning the order in which the elements are returned (unless this collection is
an instance of some class that provides a guarantee).
Specified by:
iterator in interface Iterable<E>
Returns:
an Iterator over the elements in this collection

toArray
Object[] toArray()
Returns an array containing all of the elements in this collection. If the collection
makes any guarantees as to what order its elements are returned by its iterator,
this method must return the elements in the same order.

The returned array will be "safe" in that no references to it are maintained by this
collection. (In other words, this method must allocate a new array even if this
collection is backed by an array). The caller is thus free to modify the returned
array.

This method acts as bridge between array-based and collection-based APIs.

Returns:
an array containing all of the elements in this collection

toArray
<T> T[] toArray(T[] a)
Returns an array containing all of the elements in this collection; the runtime type
of the returned array is that of the specified array. If the collection fits in the
specified array, it is returned therein. Otherwise, a new array is allocated with the
runtime type of the specified array and the size of this collection.
If this collection fits in the specified array with room to spare (i.e., the array has
more elements than this collection), the element in the array immediately
following the end of the collection is set to null. This is useful in determining the
length of this collection only if the caller knows that this collection does not
contain any null elements.)

If this collection makes any guarantees as to what order its elements are returned
by its iterator, this method must return the elements in the same order.

Like the toArray method, this method acts as bridge between array-based and
collection-based APIs. Further, this method allows precise control over the
runtime type of the output array, and may, under certain circumstances, be used to
save allocation costs

Suppose l is a List known to contain only strings. The following code can be
used to dump the list into a newly allocated array of String:

String[] x = (String[]) v.toArray(new String[0]);

Note that toArray(new Object[0]) is identical in function to toArray().

Parameters:
a - the array into which the elements of this collection are to be stored, if it is big
enough; otherwise, a new array of the same runtime type is allocated for this
purpose.
Returns:
an array containing the elements of this collection
Throws:
ArrayStoreException - the runtime type of the specified array is not a supertype
of the runtime type of every element in this collection.
NullPointerException - if the specified array is null.

add
boolean add(E o)
Ensures that this collection contains the specified element (optional operation).
Returns true if this collection changed as a result of the call. (Returns false if
this collection does not permit duplicates and already contains the specified
element.)

Collections that support this operation may place limitations on what elements
may be added to this collection. In particular, some collections will refuse to add
null elements, and others will impose restrictions on the type of elements that
may be added. Collection classes should clearly specify in their documentation
any restrictions on what elements may be added.
If a collection refuses to add a particular element for any reason other than that it
already contains the element, it must throw an exception (rather than returning
false). This preserves the invariant that a collection always contains the specified
element after this call returns.

Parameters:
o - element whose presence in this collection is to be ensured.
Returns:
true if this collection changed as a result of the call
Throws:
UnsupportedOperationException - add is not supported by this collection.
ClassCastException - class of the specified element prevents it from being
added to this collection.
NullPointerException - if the specified element is null and this collection does
not support null elements.
IllegalArgumentException - some aspect of this element prevents it from being
added to this collection.

remove
boolean remove(Object o)
Removes a single instance of the specified element from this collection, if it is
present (optional operation). More formally, removes an element e such that
(o==null ? e==null : o.equals(e)), if this collection contains one or more
such elements. Returns true if this collection contained the specified element (or
equivalently, if this collection changed as a result of the call).
Parameters:
o - element to be removed from this collection, if present.
Returns:
true if this collection changed as a result of the call
Throws:
ClassCastException - if the type of the specified element is incompatible with
this collection (optional).
NullPointerException - if the specified element is null and this collection does
not support null elements (optional).
UnsupportedOperationException - remove is not supported by this collection.

containsAll
boolean containsAll(Collection<?> c)
Returns true if this collection contains all of the elements in the specified
collection.
Parameters:
c - collection to be checked for containment in this collection.
Returns:
true if this collection contains all of the elements in the specified collection
Throws:
ClassCastException - if the types of one or more elements in the specified
collection are incompatible with this collection (optional).
NullPointerException - if the specified collection contains one or more null
elements and this collection does not support null elements (optional).
NullPointerException - if the specified collection is null.
See Also:
contains(Object)

addAll
boolean addAll(Collection<? extends E> c)
Adds all of the elements in the specified collection to this collection (optional
operation). The behavior of this operation is undefined if the specified collection
is modified while the operation is in progress. (This implies that the behavior of
this call is undefined if the specified collection is this collection, and this
collection is nonempty.)
Parameters:
c - elements to be inserted into this collection.
Returns:
true if this collection changed as a result of the call
Throws:
UnsupportedOperationException - if this collection does not support the
addAll method.
ClassCastException - if the class of an element of the specified collection
prevents it from being added to this collection.
NullPointerException - if the specified collection contains one or more null
elements and this collection does not support null elements, or if the specified
collection is null.
IllegalArgumentException - some aspect of an element of the specified
collection prevents it from being added to this collection.
See Also:
add(Object)

removeAll
boolean removeAll(Collection<?> c)
Removes all this collection's elements that are also contained in the specified
collection (optional operation). After this call returns, this collection will contain
no elements in common with the specified collection.
Parameters:
c - elements to be removed from this collection.
Returns:
true if this collection changed as a result of the call
Throws:
UnsupportedOperationException - if the removeAll method is not supported
by this collection.
ClassCastException - if the types of one or more elements in this collection are
incompatible with the specified collection (optional).
NullPointerException - if this collection contains one or more null elements
and the specified collection does not support null elements (optional).
NullPointerException - if the specified collection is null.
See Also:
remove(Object), contains(Object)

retainAll
boolean retainAll(Collection<?> c)
Retains only the elements in this collection that are contained in the specified
collection (optional operation). In other words, removes from this collection all of
its elements that are not contained in the specified collection.
Parameters:
c - elements to be retained in this collection.
Returns:
true if this collection changed as a result of the call
Throws:
UnsupportedOperationException - if the retainAll method is not supported
by this Collection.
ClassCastException - if the types of one or more elements in this collection are
incompatible with the specified collection (optional).
NullPointerException - if this collection contains one or more null elements
and the specified collection does not support null elements (optional).
NullPointerException - if the specified collection is null.
See Also:
remove(Object), contains(Object)

clear
void clear()
Removes all of the elements from this collection (optional operation). This
collection will be empty after this method returns unless it throws an exception.
Throws:
UnsupportedOperationException - if the clear method is not supported by this
collection.

equals
boolean equals(Object o)
Compares the specified object with this collection for equality.

While the Collection interface adds no stipulations to the general contract for
the Object.equals, programmers who implement the Collection interface
"directly" (in other words, create a class that is a Collection but is not a Set or a
List) must exercise care if they choose to override the Object.equals. It is not
necessary to do so, and the simplest course of action is to rely on Object's
implementation, but the implementer may wish to implement a "value
comparison" in place of the default "reference comparison." (The List and Set
interfaces mandate such value comparisons.)
The general contract for the Object.equals method states that equals must be
symmetric (in other words, a.equals(b) if and only if b.equals(a)). The
contracts for List.equals and Set.equals state that lists are only equal to other
lists, and sets to other sets. Thus, a custom equals method for a collection class
that implements neither the List nor Set interface must return false when this
collection is compared to any list or set. (By the same logic, it is not possible to
write a class that correctly implements both the Set and List interfaces.)

Overrides:
equals in class Object
Parameters:
o - Object to be compared for equality with this collection.
Returns:
true if the specified object is equal to this collection
See Also:
Object.equals(Object), Set.equals(Object), List.equals(Object)

hashCode
int hashCode()
Returns the hash code value for this collection. While the Collection interface
adds no stipulations to the general contract for the Object.hashCode method,
programmers should take note that any class that overrides the Object.equals
method must also override the Object.hashCode method in order to satisfy the
general contract for the Object.hashCodemethod. In particular, c1.equals(c2)
implies that c1.hashCode()==c2.hashCode().
Overrides:
hashCode in class Object
Returns:
the hash code value for this collection
See Also:
Object.hashCode(), Object.equals(Object)

Sets
A Set is a Collection that does not allow you add duplicate objects (two objects
that are equal).
Read more about the Set interface in the JDK documentation
Set http://java.sun.com/j2se/1.5.0/docs/api/java/util/Set.html

A set is also an interface but you can instantiate a HashSet which implements it.

public interface Set<E>


extends Collection<E>
A collection that contains no duplicate elements. More formally, sets contain no pair of
elements e1 and e2 such that e1.equals(e2), and at most one null element. As implied
by its name, this interface models the mathematical set abstraction.

The Set interface places additional stipulations, beyond those inherited from the
Collection interface, on the contracts of all constructors and on the contracts of the add,
equals and hashCode methods. Declarations for other inherited methods are also
included here for convenience. (The specifications accompanying these declarations have
been tailored to the Set interface, but they do not contain any additional stipulations.)

The additional stipulation on constructors is, not surprisingly, that all constructors must
create a set that contains no duplicate elements (as defined above).

Note: Great care must be exercised if mutable objects are used as set elements. The
behavior of a set is not specified if the value of an object is changed in a manner that
affects equals comparisons while the object is an element in the set. A special case of this
prohibition is that it is not permissible for a set to contain itself as an element.

Some set implementations have restrictions on the elements that they may contain. For
example, some implementations prohibit null elements, and some have restrictions on the
types of their elements. Attempting to add an ineligible element throws an unchecked
exception, typically NullPointerException or ClassCastException. Attempting to
query the presence of an ineligible element may throw an exception, or it may simply
return false; some implementations will exhibit the former behavior and some will exhibit
the latter. More generally, attempting an operation on an ineligible element whose
completion would not result in the insertion of an ineligible element into the set may
throw an exception or it may succeed, at the option of the implementation. Such
exceptions are marked as "optional" in the specification for this interface.

This interface is a member of the Java Collections Framework.

Since:
1.2
See Also:
Collection, List, SortedSet, HashSet, TreeSet, AbstractSet,
Collections.singleton(java.lang.Object), Collections.EMPTY_SET

Method Summary
boolean add(E o)
Adds the specified element to this set if it is not already present
(optional operation).
boolean addAll(Collection<? extends E> c)
Adds all of the elements in the specified collection to this set if
they're not already present (optional operation).
void clear()
Removes all of the elements from this set (optional operation).
boolean contains(Object o)
Returns true if this set contains the specified element.
boolean containsAll(Collection<?> c)
Returns true if this set contains all of the elements of the specified
collection.
boolean equals(Object o)
Compares the specified object with this set for equality.
int hashCode()
Returns the hash code value for this set.
boolean isEmpty()
Returns true if this set contains no elements.
Iterator<E> iterator()
Returns an iterator over the elements in this set.
boolean remove(Object o)
Removes the specified element from this set if it is present (optional
operation).
boolean removeAll(Collection<?> c)
Removes from this set all of its elements that are contained in the
specified collection (optional operation).
boolean retainAll(Collection<?> c)
Retains only the elements in this set that are contained in the
specified collection (optional operation).
int size()
Returns the number of elements in this set (its cardinality).
Object[] toArray()
Returns an array containing all of the elements in this set.
<T> T[] toArray(T[] a)
Returns an array containing all of the elements in this set; the
runtime type of the returned array is that of the specified array.

Method Detail
size
int size()
Returns the number of elements in this set (its cardinality). If this set contains
more than Integer.MAX_VALUE elements, returns Integer.MAX_VALUE.
Specified by:
size in interface Collection<E>
Returns:
the number of elements in this set (its cardinality).

isEmpty
boolean isEmpty()
Returns true if this set contains no elements.
Specified by:
isEmpty in interface Collection<E>
Returns:
true if this set contains no elements.

contains
boolean contains(Object o)
Returns true if this set contains the specified element. More formally, returns
true if and only if this set contains an element e such that (o==null ? e==null
: o.equals(e)).
Specified by:
contains in interface Collection<E>
Parameters:
o - element whose presence in this set is to be tested.
Returns:
true if this set contains the specified element.
Throws:
ClassCastException - if the type of the specified element is incompatible with
this set (optional).
NullPointerException - if the specified element is null and this set does not
support null elements (optional).

iterator
Iterator<E> iterator()
Returns an iterator over the elements in this set. The elements are returned in no
particular order (unless this set is an instance of some class that provides a
guarantee).
Specified by:
iterator in interface Collection<E>
Specified by:
iterator in interface Iterable<E>
Returns:
an iterator over the elements in this set.

toArray
Object[] toArray()
Returns an array containing all of the elements in this set. Obeys the general
contract of the Collection.toArray method.
Specified by:
toArray in interface Collection<E>
Returns:
an array containing all of the elements in this set.

toArray
<T> T[] toArray(T[] a)
Returns an array containing all of the elements in this set; the runtime type of the
returned array is that of the specified array. Obeys the general contract of the
Collection.toArray(Object[]) method.
Specified by:
toArray in interface Collection<E>
Parameters:
a - the array into which the elements of this set are to be stored, if it is big enough;
otherwise, a new array of the same runtime type is allocated for this purpose.
Returns:
an array containing the elements of this set.
Throws:
ArrayStoreException - the runtime type of a is not a supertype of the runtime
type of every element in this set.
NullPointerException - if the specified array is null.

add
boolean add(E o)
Adds the specified element to this set if it is not already present (optional
operation). More formally, adds the specified element, o, to this set if this set
contains no element e such that (o==null ? e==null : o.equals(e)). If this
set already contains the specified element, the call leaves this set unchanged and
returns false. In combination with the restriction on constructors, this ensures
that sets never contain duplicate elements.

The stipulation above does not imply that sets must accept all elements; sets may
refuse to add any particular element, including null, and throwing an exception,
as described in the specification for Collection.add. Individual set
implementations should clearly document any restrictions on the elements that
they may contain.

Specified by:
add in interface Collection<E>
Parameters:
o - element to be added to this set.
Returns:
true if this set did not already contain the specified element.
Throws:
UnsupportedOperationException - if the add method is not supported by this
set.
ClassCastException - if the class of the specified element prevents it from
being added to this set.
NullPointerException - if the specified element is null and this set does not
support null elements.
IllegalArgumentException - if some aspect of the specified element prevents it
from being added to this set.

remove
boolean remove(Object o)
Removes the specified element from this set if it is present (optional operation).
More formally, removes an element e such that (o==null ? e==null :
o.equals(e)), if the set contains such an element. Returns true if the set
contained the specified element (or equivalently, if the set changed as a result of
the call). (The set will not contain the specified element once the call returns.)
Specified by:
remove in interface Collection<E>
Parameters:
o - object to be removed from this set, if present.
Returns:
true if the set contained the specified element.
Throws:
ClassCastException - if the type of the specified element is incompatible with
this set (optional).
NullPointerException - if the specified element is null and this set does not
support null elements (optional).
UnsupportedOperationException - if the remove method is not supported by
this set.

containsAll
boolean containsAll(Collection<?> c)
Returns true if this set contains all of the elements of the specified collection. If
the specified collection is also a set, this method returns true if it is a subset of
this set.
Specified by:
containsAll in interface Collection<E>
Parameters:
c - collection to be checked for containment in this set.
Returns:
true if this set contains all of the elements of the specified collection.
Throws:
ClassCastException - if the types of one or more elements in the specified
collection are incompatible with this set (optional).
NullPointerException - if the specified collection contains one or more null
elements and this set does not support null elements (optional).
NullPointerException - if the specified collection is null.
See Also:
contains(Object)

addAll
boolean addAll(Collection<? extends E> c)
Adds all of the elements in the specified collection to this set if they're not already
present (optional operation). If the specified collection is also a set, the addAll
operation effectively modifies this set so that its value is the union of the two sets.
The behavior of this operation is unspecified if the specified collection is
modified while the operation is in progress.
Specified by:
addAll in interface Collection<E>
Parameters:
c - collection whose elements are to be added to this set.
Returns:
true if this set changed as a result of the call.
Throws:
UnsupportedOperationException - if the addAll method is not supported by
this set.
ClassCastException - if the class of some element of the specified collection
prevents it from being added to this set.
NullPointerException - if the specified collection contains one or more null
elements and this set does not support null elements, or if the specified collection
is null.
IllegalArgumentException - if some aspect of some element of the specified
collection prevents it from being added to this set.
See Also:
add(Object)

retainAll
boolean retainAll(Collection<?> c)
Retains only the elements in this set that are contained in the specified collection
(optional operation). In other words, removes from this set all of its elements that
are not contained in the specified collection. If the specified collection is also a
set, this operation effectively modifies this set so that its value is the intersection
of the two sets.
Specified by:
retainAll in interface Collection<E>
Parameters:
c - collection that defines which elements this set will retain.
Returns:
true if this collection changed as a result of the call.
Throws:
UnsupportedOperationException - if the retainAll method is not supported
by this Collection.
ClassCastException - if the types of one or more elements in this set are
incompatible with the specified collection (optional).
NullPointerException - if this set contains a null element and the specified
collection does not support null elements (optional).
NullPointerException - if the specified collection is null.
See Also:
remove(Object)

removeAll
boolean removeAll(Collection<?> c)
Removes from this set all of its elements that are contained in the specified
collection (optional operation). If the specified collection is also a set, this
operation effectively modifies this set so that its value is the asymmetric set
difference of the two sets.
Specified by:
removeAll in interface Collection<E>
Parameters:
c - collection that defines which elements will be removed from this set.
Returns:
true if this set changed as a result of the call.
Throws:
UnsupportedOperationException - if the removeAll method is not supported
by this Collection.
ClassCastException - if the types of one or more elements in this set are
incompatible with the specified collection (optional).
NullPointerException - if this set contains a null element and the specified
collection does not support null elements (optional).
NullPointerException - if the specified collection is null.
See Also:
remove(Object)

clear
void clear()
Removes all of the elements from this set (optional operation). This set will be
empty after this call returns (unless it throws an exception).
Specified by:
clear in interface Collection<E>
Throws:
UnsupportedOperationException - if the clear method is not supported by this
set.

equals
boolean equals(Object o)
Compares the specified object with this set for equality. Returns true if the
specified object is also a set, the two sets have the same size, and every member
of the specified set is contained in this set (or equivalently, every member of this
set is contained in the specified set). This definition ensures that the equals
method works properly across different implementations of the set interface.
Specified by:
equals in interface Collection<E>
Overrides:
equals in class Object
Parameters:
o - Object to be compared for equality with this set.
Returns:
true if the specified Object is equal to this set.
See Also:
Object.hashCode(), Hashtable

hashCode
int hashCode()
Returns the hash code value for this set. The hash code of a set is defined to be the
sum of the hash codes of the elements in the set, where the hashcode of a null
element is defined to be zero. This ensures that s1.equals(s2) implies that
s1.hashCode()==s2.hashCode() for any two sets s1 and s2, as required by the
general contract of the Object.hashCode method.
Specified by:
hashCode in interface Collection<E>
Overrides:
hashCode in class Object
Returns:
the hash code value for this set.
See Also:
Object.hashCode(), Object.equals(Object), equals(Object)

Lists
A List is a Collection that allows its objects to be ordered. Unlike other
Collections you can control the position of an object within a List.
Read more about the List interface in the JDK documentation
List http://java.sun.com/j2se/1.5.0/docs/api/java/util/List.html
A List is also an interface but you can instantiate a ArrayList which implements it.

Maps

The Map interface is not a Collection. It offers the ability to store pairs of objects,
a pair consisting of a key and a value. Although the Map interface does have a
size() method items are not indexed so it does not allow you to retrieve an
value by it's position. Therefore you can't loop through (or iterate over) a map
directly but you can use the values() method to get a collection of values
which you can iterate over, or the keySet() method to get a Set of keys which
you can also iterate over. The HashMap is an implementation that you can use.
Read more about the Map interface in the JDK documentation.
Map http://java.sun.com/j2se/1.5.0/docs/api/java/util/Map.html

Interface Map<K,V>
All Known Subinterfaces:
ConcurrentMap<K,V>, SortedMap<K,V>
All Known Implementing Classes:
AbstractMap, Attributes, AuthProvider, ConcurrentHashMap, EnumMap,
HashMap, Hashtable, IdentityHashMap, LinkedHashMap, PrinterStateReasons,
Properties, Provider, RenderingHints, TabularDataSupport, TreeMap, UIDefaults,
WeakHashMap
public interface Map<K,V>

An object that maps keys to values. A map cannot contain duplicate keys; each key can
map to at most one value.

This interface takes the place of the Dictionary class, which was a totally abstract class
rather than an interface.

The Map interface provides three collection views, which allow a map's contents to be
viewed as a set of keys, collection of values, or set of key-value mappings. The order of a
map is defined as the order in which the iterators on the map's collection views return
their elements. Some map implementations, like the TreeMap class, make specific
guarantees as to their order; others, like the HashMap class, do not.

Note: great care must be exercised if mutable objects are used as map keys. The behavior
of a map is not specified if the value of an object is changed in a manner that affects
equals comparisons while the object is a key in the map. A special case of this prohibition
is that it is not permissible for a map to contain itself as a key. While it is permissible for
a map to contain itself as a value, extreme caution is advised: the equals and hashCode
methods are no longer well defined on a such a map.

All general-purpose map implementation classes should provide two "standard"


constructors: a void (no arguments) constructor which creates an empty map, and a
constructor with a single argument of type Map, which creates a new map with the same
key-value mappings as its argument. In effect, the latter constructor allows the user to
copy any map, producing an equivalent map of the desired class. There is no way to
enforce this recommendation (as interfaces cannot contain constructors) but all of the
general-purpose map implementations in the JDK comply.

The "destructive" methods contained in this interface, that is, the methods that modify the
map on which they operate, are specified to throw UnsupportedOperationException if
this map does not support the operation. If this is the case, these methods may, but are not
required to, throw an UnsupportedOperationException if the invocation would have
no effect on the map. For example, invoking the putAll(Map) method on an
unmodifiable map may, but is not required to, throw the exception if the map whose
mappings are to be "superimposed" is empty.

Some map implementations have restrictions on the keys and values they may contain.
For example, some implementations prohibit null keys and values, and some have
restrictions on the types of their keys. Attempting to insert an ineligible key or value
throws an unchecked exception, typically NullPointerException or
ClassCastException. Attempting to query the presence of an ineligible key or value
may throw an exception, or it may simply return false; some implementations will exhibit
the former behavior and some will exhibit the latter. More generally, attempting an
operation on an ineligible key or value whose completion would not result in the insertion
of an ineligible element into the map may throw an exception or it may succeed, at the
option of the implementation. Such exceptions are marked as "optional" in the
specification for this interface.

This interface is a member of the Java Collections Framework.

Many methods in Collections Framework interfaces are defined in terms of the equals
method. For example, the specification for the contains(Object key) method says:
"returns true if and only if this map contain a mapping for a key k such that (key==null
? k==null : key.equals(k))." This specification should not be construed to imply
that invoking Map.containsKey with a non-null argument key will cause
key.equals(k) to be invoked for any key k. Implementations are free to implement
optimizations whereby the equals invocation is avoided, for example, by first comparing
the hash codes of the two keys. (The Object.hashCode() specification guarantees that
two objects with unequal hash codes cannot be equal.) More generally, implementations
of the various Collections Framework interfaces are free to take advantage of the
specified behavior of underlying Object methods wherever the implementor deems it
appropriate.

Since:
1.2
See Also:
HashMap, TreeMap, Hashtable, SortedMap, Collection, Set

Nested Class Summary


static interface Map.Entry<K,V>
A map entry (key-value pair).

Method Summary
void clear()
Removes all mappings from this map (optional
operation).
boolean containsKey(Object key)
Returns true if this map contains a mapping for the
specified key.
boolean containsValue(Object value)
Returns true if this map maps one or more keys to the
specified value.
Set<Map.Entry<K,V>> entrySet()
Returns a set view of the mappings contained in this map.
boolean equals(Object o)
Compares the specified object with this map for equality.
V get(Object key)
Returns the value to which this map maps the specified
key.
int hashCode()
Returns the hash code value for this map.
boolean isEmpty()
Returns true if this map contains no key-value mappings.
Set<K> keySet()
Returns a set view of the keys contained in this map.
V put(K key, V value)
Associates the specified value with the specified key in
this map (optional operation).
void putAll(Map<? extends K,? extends V> t)
Copies all of the mappings from the specified map to this
map (optional operation).
V remove(Object key)
Removes the mapping for this key from this map if it is
present (optional operation).
int size()
Returns the number of key-value mappings in this map.
Collection<V> values()
Returns a collection view of the values contained in this
map.
Method Detail
size
int size()
Returns the number of key-value mappings in this map. If the map contains more
than Integer.MAX_VALUE elements, returns Integer.MAX_VALUE.
Returns:
the number of key-value mappings in this map.

isEmpty
boolean isEmpty()
Returns true if this map contains no key-value mappings.
Returns:
true if this map contains no key-value mappings.

containsKey
boolean containsKey(Object key)
Returns true if this map contains a mapping for the specified key. More formally,
returns true if and only if this map contains a mapping for a key k such that
(key==null ? k==null : key.equals(k)). (There can be at most one such
mapping.)
Parameters:
key - key whose presence in this map is to be tested.
Returns:
true if this map contains a mapping for the specified key.
Throws:
ClassCastException - if the key is of an inappropriate type for this map (optional).
NullPointerException - if the key is null and this map does not permit null keys
(optional).

containsValue
boolean containsValue(Object value)
Returns true if this map maps one or more keys to the specified value. More
formally, returns true if and only if this map contains at least one mapping to a
value v such that (value==null ? v==null : value.equals(v)). This
operation will probably require time linear in the map size for most
implementations of the Map interface.
Parameters:
value - value whose presence in this map is to be tested.
Returns:
true if this map maps one or more keys to the specified value.
Throws:
ClassCastException - if the value is of an inappropriate type for this map
(optional).
NullPointerException - if the value is null and this map does not permit null
values (optional).

get
V get(Object key)
Returns the value to which this map maps the specified key. Returns null if the
map contains no mapping for this key. A return value of null does not
necessarily indicate that the map contains no mapping for the key; it's also
possible that the map explicitly maps the key to null. The containsKey
operation may be used to distinguish these two cases.

More formally, if this map contains a mapping from a key k to a value v such that
(key==null ? k==null : key.equals(k)), then this method returns v;
otherwise it returns null. (There can be at most one such mapping.)

Parameters:
key - key whose associated value is to be returned.
Returns:
the value to which this map maps the specified key, or null if the map contains
no mapping for this key.
Throws:
ClassCastException - if the key is of an inappropriate type for this map (optional).
NullPointerException - if the key is null and this map does not permit null keys
(optional).
See Also:
containsKey(Object)

put
V put(K key,
V value)
Associates the specified value with the specified key in this map (optional
operation). If the map previously contained a mapping for this key, the old value
is replaced by the specified value. (A map m is said to contain a mapping for a key
k if and only if m.containsKey(k) would return true.))
Parameters:
key - key with which the specified value is to be associated.
value - value to be associated with the specified key.
Returns:
previous value associated with specified key, or null if there was no mapping for
key. A null return can also indicate that the map previously associated null with
the specified key, if the implementation supports null values.
Throws:
UnsupportedOperationException - if the put operation is not supported by this
map.
ClassCastException - if the class of the specified key or value prevents it from
being stored in this map.
IllegalArgumentException - if some aspect of this key or value prevents it from
being stored in this map.
NullPointerException - if this map does not permit null keys or values, and the
specified key or value is null.

remove
V remove(Object key)
Removes the mapping for this key from this map if it is present (optional
operation). More formally, if this map contains a mapping from key k to value v
such that (key==null ? k==null : key.equals(k)), that mapping is removed.
(The map can contain at most one such mapping.)

Returns the value to which the map previously associated the key, or null if the
map contained no mapping for this key. (A null return can also indicate that the
map previously associated null with the specified key if the implementation
supports null values.) The map will not contain a mapping for the specified key
once the call returns.

Parameters:
key - key whose mapping is to be removed from the map.
Returns:
previous value associated with specified key, or null if there was no mapping for
key.
Throws:
ClassCastException - if the key is of an inappropriate type for this map (optional).
NullPointerException - if the key is null and this map does not permit null keys
(optional).
UnsupportedOperationException - if the remove method is not supported by this
map.

putAll
void putAll(Map<? extends K,? extends V> t)
Copies all of the mappings from the specified map to this map (optional
operation). The effect of this call is equivalent to that of calling put(k, v) on
this map once for each mapping from key k to value v in the specified map. The
behavior of this operation is unspecified if the specified map is modified while the
operation is in progress.
Parameters:
t - Mappings to be stored in this map.
Throws:
UnsupportedOperationException - if the putAll method is not supported by this
map.
ClassCastException - if the class of a key or value in the specified map prevents it
from being stored in this map.
IllegalArgumentException - some aspect of a key or value in the specified map
prevents it from being stored in this map.
NullPointerException - if the specified map is null, or if this map does not permit
null keys or values, and the specified map contains null keys or values.

clear
void clear()
Removes all mappings from this map (optional operation).
Throws:
UnsupportedOperationException - clear is not supported by this map.

keySet
Set<K> keySet()
Returns a set view of the keys contained in this map. The set is backed by the
map, so changes to the map are reflected in the set, and vice-versa. If the map is
modified while an iteration over the set is in progress (except through the
iterator's own remove operation), the results of the iteration are undefined. The set
supports element removal, which removes the corresponding mapping from the
map, via the Iterator.remove, Set.remove, removeAll retainAll, and clear
operations. It does not support the add or addAll operations.
Returns:
a set view of the keys contained in this map.

values
Collection<V> values()
Returns a collection view of the values contained in this map. The collection is
backed by the map, so changes to the map are reflected in the collection, and vice-
versa. If the map is modified while an iteration over the collection is in progress
(except through the iterator's own remove operation), the results of the iteration
are undefined. The collection supports element removal, which removes the
corresponding mapping from the map, via the Iterator.remove,
Collection.remove, removeAll, retainAll and clear operations. It does not
support the add or addAll operations.
Returns:
a collection view of the values contained in this map.

entrySet
Set<Map.Entry<K,V>> entrySet()
Returns a set view of the mappings contained in this map. Each element in the
returned set is a Map.Entry. The set is backed by the map, so changes to the map
are reflected in the set, and vice-versa. If the map is modified while an iteration
over the set is in progress (except through the iterator's own remove operation, or
through the setValue operation on a map entry returned by the iterator) the
results of the iteration are undefined. The set supports element removal, which
removes the corresponding mapping from the map, via the Iterator.remove,
Set.remove, removeAll, retainAll and clear operations. It does not support
the add or addAll operations.
Returns:
a set view of the mappings contained in this map.

equals
boolean equals(Object o)
Compares the specified object with this map for equality. Returns true if the
given object is also a map and the two Maps represent the same mappings. More
formally, two maps t1 and t2 represent the same mappings if
t1.entrySet().equals(t2.entrySet()). This ensures that the equals method
works properly across different implementations of the Map interface.
Overrides:
equals in class Object
Parameters:
o - object to be compared for equality with this map.
Returns:
true if the specified object is equal to this map.
See Also:
Object.hashCode(), Hashtable

hashCode
int hashCode()
Returns the hash code value for this map. The hash code of a map is defined to be
the sum of the hashCodes of each entry in the map's entrySet view. This ensures
that t1.equals(t2) implies that t1.hashCode()==t2.hashCode() for any two
maps t1 and t2, as required by the general contract of Object.hashCode.
Overrides:
hashCode in class Object
Returns:
the hash code value for this map.
See Also:
Map.Entry.hashCode(), Object.hashCode(), Object.equals(Object),
equals(Object)

Looping

There are three basic ways to loop through a group of objects and the method
you use is usually driven by the object type that is holding that group.

If you have access to the size of the group and the ability to retrieve each object
by its index then you can use a normal for loop.

Otherwise you need to use either an Enumeration or an Iterator, both are quite
similar.

Enumerator example
Enumeration e = myVector.elements() ;
while( e.hasMoreElements()) {
System.out.println(e.nextElement());
}

Iterator example
Iterator i = myCollection.iterator() ;
while( i.hasNext()) {
System.out.println(e.next());
}

Of course in both these cases you could use a for loop by putting the line of code
above the loop in the initialization section and leaving the last section empty.

Summary

Using all of these approaches to grouping objects and the various looping
techniques will quickly become second nature and you will wonder what all the
fuss was about but until then, before you add objects to a List, Map or Set just
think about what you are going to do with them once they are in there and how
you want to be able to get them out again.

Don't forget that we looked at the interfaces and one example implementation,
there are many other implementations including some that implement more than
one of these interfaces.

Advanced Objects

Way back in the 'Introduction to Programming' module we introduced you to


several concepts that define a language as being Object Orientated including
encapsulation and polymorphism. But until we have not looked at how to take
advantage of those features.

In this section we will look at those features.

Encapsulation

Encapsulation simply means 'to encapsulate functionality'. In practice this is


easy, all the private methods within a class are encapsulated. The key is that
other classes can only see the public interface of your class. If you decide to
change functionality within your class then none of the classes that use your
class need to be updated. They will just call the same methods that they did
before.

To support encapsulation it is a good idea to make all your properties private and
provide methods to get and set their values as follow:

public void setRotations(double rotations){


this.rotations = rotations;
}
public double getRotations(){
return rotations;
}
private double rotations = 0;

The advantage of doing this is that you can change what the methods do without
changing the public interface of your class, for example you may decide you want
to add code to setRotations to ensure that nobody tries to set the number of
rotations to a negative number.

Inheritance

Conceptually, inheritance is where one class inherits characteristics of another


class. In practical terms we achieve this by extending one class from another. In
fact every class you develop extends java.lang.Object.

public class Wheel{


public Wheel(int diameter){
this.diameter = diameter;
}

public void rotate(double rotations){


this.rotations += rotations;
}

public int diameter = 0;


public double rotations = 0;
}

public class BicycleWheel extends Wheel{


public int spokes = 20;
}
The BicycleWheel class extends the Wheel class so whenever you create an
instance of BicycleWheel it has a rotate method and diameter and rotations
properties.

Some languages allow one class to extend more than one other class but Java
does not.

Polymorphism

Polymorphism means "many forms". In OO terms Polymorphism is the ability of a


class to react differently when arguments of different types are passed to
methods with the same name. This technique is known as overloading.

public class Counter {


public void increase(float value){
count += Math.round(value);
}
public void increase(int value){
count += value;
}
private int count = 0;
}

The above example has two methods, the only difference in the signature is that
one expects an int and the other expects a float. This is overloading.

Overloading is not to be confused with overriding. Overriding is where a class


that extends another class provides a method with the same signature thereby
overriding the implementation in the super-class.

Interfaces

In the real world there are many objects that can be generically grouped but work
completely differently. The problem is that if you want to be able to write different
classes but refer to them as generically most of the time. Well an interface is the
answer.

Read this document for a more detailed explanation.


What Is an Interface?
http://www.particle.kth.se/~lindsey/JavaCourse/Book/Part1/Java/Chapter04/interf
ace.html
Interfaces
JavaTech
As discussed earlier, Java does not allow a class to inherit more than one
Course Map
class as in C++. That is,
Chapter 4
class Test extends aClass, bClass{ // Error !!

Introduction There are situations where multiple inheritance can be useful but it can also
Inheritance
Demo 1
lead to problems. For example, a reference to a method with the same name
Overriding in both classes needs a system for making it explicit as to which class
Demo 2a Demo 2b should be used.
this,super
MoreConstructors
Demo 3 Iinterfaces provide most of the advantages of multiple inheritance with
Abstraction fewer problems. An interface is basically an abstract class but with all of
Interface the methods abstract. (The methods in an interface do not need the explicit
Demo 4
Casting References abstract modifier since they are abstract by definition.)
MoreAboutArrays
Object class A class implements an interface rather than extends it. Any class that
Class Summary implements the interface must override all the interface methods with it's
Exercises own methods.

Supplements (In the case of identical method names in two interfaces, it's irrelevant since
Override/Overload both methods are abstract and carry no code body. In a sense, both are
Annotation-J2SE5.0 overridden by the single method of that name in the implementing class.)
Java Security
Class Loading
Class Verifier In the example below, Runnable is an interface with a single method:
SecurityManager run(). So any method that implements Runnable must override run().

About JavaTech
Codes List
Exercises class Test extends Applet implements Runnable
Feedback {
References ...
Resources public void run () {
Tips ...
Topic Index }
Course Guide }
What's New
interface Runnable
{
public void run ();
}

Any number of interfaces can be implemented. Just separate the interface


names with a comma:

class Test extends Applet implements Runnable, AnInterface


{
...
This example demonstrates how an interface can be used.

First we define an interface in a similar way to defining a class but none of the
methods are implemented.

public interface Phone{


public Connection dial(String number);
public boolean inUse();
}

Next we develop our classes to represent our two different types of phone. Note
how we reference the interface after the name of the class. Also note that we
have added the methods exactly as they are defined in our interface. Both
classes now "implement the phone interface"

public class MobilePhone implements Phone {


public Connection dial(String number){
//mobile implementation
}
public boolean inUse(){
//mobile implementation
}
}

public class LandlinePhone implements Phone {


public Connection dial(String number){
//Landline implementation
}
public boolean inUse(){
//Landline implementation
}
}

The next class demonstrates how we can use either implementation. In the
constructor we add one mobile and one landline phone to an ArrayList, then in
the makeCall method we retrieve each phone in turn from the list until we find
one that is free then make our call.

public class PhoneCallMaker {


public PhoneCallMaker(){
phones = new ArrayList();
MobilePhone mobile = new MobilePhone();
phones.add(mobile);
LandlinePhone landline = new LandlinePhone();
phones.add(landline);
}

public void makeCall(String number){


for(int i=0;i<phones.size();i++){
Phone phone = (Phone)phones.get(i);
if(!phone.inUse()){
phone.dial(number);
break;
}
}
}

private ArrayList phones;


}

Using interfaces makes sense even if only currently have one implementation. If
you only have a mobile phone but later replace it with a satellite phone that
implements the same interface the changes required to your code will be
minimal.

The following article also gives a good description of interfaces


Interfaces http://java.sun.com/docs/books/tutorial/java/concepts/interface.html

What Is an Interface?
As you've already learned, objects define their interaction with the outside world through
the methods that they expose. Methods form the object's interface with the outside world;
the buttons on the front of your television set, for example, are the interface between you
and the electrical wiring on the other side of its plastic casing. You press the "power"
button to turn the television on and off.

In its most common form, an interface is a group of related methods with empty bodies.
A bicycle's behavior, if specified as an interface, might appear as follows:

interface Bicycle {

void changeCadence(int newValue);

void changeGear(int newValue);


void speedUp(int increment);

void applyBrakes(int decrement);


}
To implement this interface, the name of your class would change (to ACMEBicycle, for
example), and you'd use the implements keyword in the class declaration:
class ACMEBicycle implements Bicycle {

// remainder of this class implemented as before

}
Implementing an interface allows a class to become more formal about the behavior it
promises to provide. Interfaces form a contract between the class and the outside world,
and this contract is enforced at build time by the compiler. If your class claims to
implement an interface, all methods defined by that interface must appear in its source
code before the class will successfully compile.
Note: To actually compile the ACMEBicycle class, you'll need to add the public
keyword to the beginning of the implemented interface methods. You'll learn the reasons
for this later in the lessons on Classes and Objects and Interfaces and Inheritance.

Abstract Classes

Interfaces are very useful but sometimes the objects that implement your
interface might contain duplicate code because the implementation is the same.
Abstract classes and methods provide a way to implement the common
functionality in a central class but still require any class that uses it to implement
the remaining functionality.

Consider the following example.

package methoddemo;
public abstract class Phone {
public void makeCall(String number){
Connection conn = getConnection(number);
connectionIsOpen = true;
//talk
connectionIsOpen = false;
}
public abstract Connection getConnection(String number);
public boolean inUse(){
return connectionIsOpen;
}
private boolean connectionIsOpen = false;
}
In this example of an abstract class we implement most of the functionality but
we want the mobile and landline classes to implement the getConnection
method so we have used the abstract identifier. If your class has an abstract
method then you must declare the class as abstract. It is not possible to create
instances of abstract classes they must be extended and the class that extends it
must implement the abstract methods (or also be declared as abstract). We can
for example create instances of the following class.

package methoddemo;
public class MobilePhone extends Phone{
public Connection getConnection(String number){
//mobile phone implemention of getConnection
//goes here
return new Connection();
}
}

Summary
You have learned how to embrace the power of object orientated programming.
Don't worry if you can't remember every little detail, you will be getting plenty of
practice!
But if there is anything you don't understand don't forget to post a question on the
message board.

Exercise

This exercise will put what you have just learned about the more advanced site of
objects to the test.
We are going to expand on the Human classes that we created in the previous
exercise.

1. Create an interface called limb and modify your arm and leg classes so
that they implement it.
2. Create a new abstract class called Mammal and move any properties and
methods that all mammals have from your Human to the Mammal class.
3. Ensure that your mammal has a private property which is an collection of
limbs and protected methods to add, remove and retrieve the limbs
(alternative solution would be to have protected collection of limbs and
protected constructor in which you can pass collection of limbs to add).
4. Modify your Human to extend Mammal.
5. Add methods to your Human that return collections of arms and legs.
implement these methods by iterating through the collection of limbs and
checking what type of limb they are. Note that you will need to use the
instanceOf keyword but we haven't covered it so you will need to research
it.
6. Create three new classes that represent pets. They should all be
mammals but have some unique characteristics.
7. Create a Family class that creates two humans (yourself and your ideal
partner) and three pets.
8. Extend the Human class to create two new classes Adult and Child.
9. Make sure your human has an age property.
10. Modify your family so it includes a child.
11. Add an abstract canWatchMovie method to the Human which takes a
parameter specifying the movie rating.
12. Create a MovieRating class that contains a private map with rating as the
key and minimum age as the value, populate this map when the class is
instantiated. Also include a method which takes two parameters, rating
and age and checks the minimum age in the map and returns true or false
to indicate whether or not a human with the specified age is allowed to
watch a movie with the specified rating.
13. Implement the canWatchMovie method in the child and adult, in the adult
always return true but in the child use the MovieRating class to determine
whether the child can watch the movie.
14. Add a getMovieGoers method to the family that takes a rating as a
parameter and returns a collection of all the family members that can
watch the movie.
15. Demonstrate the use on the getMovieGoers method by calling it twice
from within the main method of the family and prints out the names of the
family members that can watch the movie.

Error Handling

Of course your code is always going to be so good that it never has errors but in
fact good error handling is an essential part of everyday code and you need to
handle errors because there is always something that can go wrong.

Imagine your application store some configuration settings in a file. You have
deployed your application and the users love it until one day the administrator
deletes your file thinking it is part of the application that yours replaced. The main
user of your application is on holiday but when he returns and tries to use your
application it just crashes without explanation everyone is mystified because the
application doesn't handle the error and tell the user what the problem is and
eventually they have to call in another programmer at great expense to fix and
will never call you again.
When developing applications there are certain things that you have no control
over. In Java we call these things exceptions.

Over the next few sections you will learn how to handle exceptions and some
important rules that you must remember.

Exceptions

There are some aspects of Java that are particularly well documented,
exceptions is one of those areas. So rather than duplicate other peoples fine
efforts.

Read these articles


Exceptions in Java http://www.javaworld.com/javaworld/jw-07-1998/jw-07-
exceptions.html?page=1
Three Rules for Effective Exception Handling
http://today.java.net/pub/a/today/2003/12/04/exceptions.html

Exceptions in Java
The full story of exceptions in the Java language and virtual machine
By Bill Venners, JavaWorld.com, 07/01/98

Exceptions are the customary way in Java to indicate to a calling


method that an abnormal condition has occurred. This article is a
companion piece to this month's Design Techniques installment,
which discusses how to use exceptions appropriately in your programs
and designs. Look to this companion article for a tutorial on the nuts
and bolts of what exceptions are and how they work in the Java
language and virtual machine.

When a method encounters an abnormal condition (an exception


condition) that it can't handle itself, it may throw an exception.
Throwing an exception is like throwing a beeping, flashing red ball to
indicate there is a problem that can't be handled where it occurred.
Somewhere, you hope, this ball will be caught and the problem will be
dealt with. Exceptions are caught by handlers positioned along the
thread's method invocation stack. If the calling method isn't prepared
to catch the exception, it throws the exception up to its calling
method, and so on. If one of the threads of your program throws an
exception that isn't caught by any method along the method
invocation stack, that thread will expire. When you program in Java,
you must position catchers (the exception handlers) strategically, so
your program will catch and handle all exceptions from which you want
your program to recover.

Exception classes
In Java, exceptions are objects. When you throw an exception, you
throw an object. You can't throw just any object as an exception,
however -- only those objects whose classes descend from Throwable.
Throwable serves as the base class for an entire family of classes,
declared in java.lang, that your program can instantiate and throw. A
small part of this family is shown in Figure 1.
As you can see in Figure 1, Throwable has two direct subclasses,
Exception and Error. Exceptions (members of the Exception family) are
thrown to signal abnormal conditions that can often be handled by
some catcher, though it's possible they may not be caught and
therefore could result in a dead thread. Errors (members of the Error
family) are usually thrown for more serious problems, such as
OutOfMemoryError, that may not be so easy to handle. In general, code
you write should throw only exceptions, not errors. Errors are usually
thrown by the methods of the Java API, or by the Java virtual machine
itself.

Figure 1. A partial view of the Throwable family


In addition to throwing objects whose classes are declared in java.lang,
you can throw objects of your own design. To create your own class of
throwable objects, you need only declare it as a subclass of some
member of the Throwable family. In general, however, the throwable
classes you define should extend class Exception. They should be
"exceptions." The reasoning behind this rule will be explained later in
this article.
Whether you use an existing exception class from java.lang or create
one of your own depends upon the situation. In some cases, a class
from java.lang will do just fine. For example, if one of your methods is
invoked with an invalid argument, you could throw
IllegalArgumentException, a subclass of RuntimeException in java.lang.

Three Rules for Effective Exception Handling


by Jim Cushing
12/04/2003

Exceptions in Java provide a consistent mechanism for identifying and responding to


error conditions. Effective exception handling will make your programs more robust and
easier to debug. Exceptions are a tremendous debugging aid because they help answer
these three questions:

• What went wrong?


• Where did it go wrong?
• Why did it go wrong?

When exceptions are used effectively, what is answered by the type of exception thrown,
where is answered by the exception stack trace, and why is answered by the exception
message. If you find your exceptions aren't answering all three questions, chances are
they aren't being used effectively. Three rules will help you make the best use of
exceptions when debugging your programs. These rules are: be specific, throw early, and
catch late.

To illustrate these rules of effective exception handling, this article discusses a fictional
personal finance manager called JCheckbook. JCheckbook can be used to record and
track bank account activity, such as deposits, withdrawals, and checks written. The initial
version of JCheckbook runs as a desktop application, but future plans call for an HTML
client and a client/server applet implementation.

Be Specific

Java defines an exception class hierarchy, starting with Throwable, which is extended by
Error and Exception, which is then extended by RuntimeException. These are
illustrated in Figure 1.
Figure 1. Java exception hierarchy

These four classes are generic and they don't provide much information about what went
wrong. While it is legal to instantiate any of these classes (e.g., new Throwable()), it is
best to think of them as abstract base classes, and work with more specific subclasses.
Java provides a substantial number of exception subclasses, and you may define your
own exception classes for additional specificity.

For example, the java.io package defines the IOException subclass, which extends
Exception. Even more specific are FileNotFoundException, EOFException, and
ObjectStreamException, all subclasses of IOException. Each one describes a
particular type of I/O-related failure: a missing file, an unexpected end-of-file, or a
corrupted serialized object stream, respectively. The more specific the exception, the
better our program answers what went wrong.

It is important to be specific when catching exceptions, as well. For example,


JCheckbook may respond to a FileNotFoundException by asking the user for a
different file name. In the case of an EOFException, it may be able to continue with just
the information it was able to read before the exception was thrown. If an
ObjectStreamException is thrown, the program may need to inform the user that the
file has been corrupted, and that a backup or a different file needs to be used.

Java makes it fairly easy to be specific when catching exceptions because we can specify
multiple catch blocks for a single try block, each handling a different type of exception
in an appropriate manner.

File prefsFile = new File(prefsFilename);

try
{
readPreferences(prefsFile);
}
catch (FileNotFoundException e)
{
// alert the user that the specified file
// does not exist
}
catch (EOFException e)
{
// alert the user that the end of the file
// was reached
}
catch (ObjectStreamException e)
{
// alert the user that the file is corrupted
}
catch (IOException e)
{
// alert the user that some other I/O
// error occurred
}

JCheckbook uses multiple catch blocks in order to provide the user with specific
information about the type of exception that was caught. For instance, if a
FileNotFoundException was caught, it can instruct the user to specify a different file.
The extra coding effort of multiple catch blocks may be an unnecessary burden in some
cases, but in this example, it does help the program respond in a more user-friendly
manner.

Should an IOException other than those specified by the first three catch blocks be
thrown, the last catch block will handle it by presenting the user with a somewhat more
generic error message. This way, the program can provide specific information when
possible, but still handle the general case should an unanticipated file-related exception
"slip by."

Sometimes, developers will catch a generic Exception and then display the exception
class name or stack trace, in order to "be specific." Don't do this. Seeing
java.io.EOFException or a stack trace printed to the screen is likely to confuse, rather
than help, the user. Catch specific exceptions and provide the user with specific
information in English (or some other human language). Do, however, include the
exception stack trace in your log file. Exceptions and stack traces are meant as an aid to
the developer, not to the end user.

Finally, notice that instead of catching the exception in the readPreferences() method,
JCheckbook defers catching and handling the exception until it reaches the user interface
level, where it can alert the user with a dialog box or in some other fashion. This is what
is meant by "catch late," as will be discussed later in this article.

Throw Early

The exception stack trace helps pinpoint where an exception occurred by showing us the
exact sequence of method calls that lead to the exception, along with the class name,
method name, source code filename, and line number for each of these method calls.
Consider the stack trace below:

java.lang.NullPointerException
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:103)
at jcheckbook.JCheckbook.readPreferences(JCheckbook.java:225)
at jcheckbook.JCheckbook.startup(JCheckbook.java:116)
at jcheckbook.JCheckbook.<init>(JCheckbook.java:27)
at jcheckbook.JCheckbook.main(JCheckbook.java:318)

This shows that the open() method of the FileInputStream class threw a
NullPointerException. But notice that FileInputStream.close() is part of the
standard Java class library. It is much more likely that the problem that is causing the
exception to be thrown is within our own code, rather than the Java API. So the problem
must have occurred in one of the preceding methods, which fortunately are also displayed
in the stack trace.

What is not so fortunate is that NullPointerException is one of the least informative


(and most frequently encountered and frustrating) exceptions in Java. It doesn't tell us
what we really want to know: exactly what is null. Also, we have to backtrack a few steps
to find out where the error originated.

By stepping backwards through the stack trace and investigating our code, we determine
that the error was caused by passing a null filename parameter to the
readPreferences() method. Since readPreferences() knows it cannot proceed with a
null filename, it checks for this condition immediately:

public void readPreferences(String filename)


throws IllegalArgumentException
{
if (filename == null)
{
throw new IllegalArgumentException
("filename is null");
} //if

//...perform other operations...

InputStream in = new FileInputStream(filename);

//...read the preferences file...


}

By throwing an exception early (also known as "failing fast"), the exception becomes
both more specific and more accurate. The stack trace immediately shows what went
wrong (an illegal argument value was supplied), why this is an error (null is not allowed
for filename), and where the error occurred (early in the readPreferences() method).
This keeps our stack trace honest:

java.lang.IllegalArgumentException: filename is null


at jcheckbook.JCheckbook.readPreferences(JCheckbook.java:207)
at jcheckbook.JCheckbook.startup(JCheckbook.java:116)
at jcheckbook.JCheckbook.<init>(JCheckbook.java:27)
at jcheckbook.JCheckbook.main(JCheckbook.java:318)
In addition, the inclusion of an exception message ("filename is null") makes the
exception more informative by answering specifically what was null, an answer we don't
get from the NullPointerException thrown by the earlier version of our code.

Failing fast by throwing exceptions as soon as an error is detected can eliminate the need
to construct objects or open resources, such as files or network connections, that won't be
needed. The clean-up effort associated with opening these resources is also eliminated.

Catch Late

A common mistake of many Java developers, both new and experienced, is to catch an
exception before the program can handle it in an appropriate manner. The Java compiler
reinforces this behavior by insisting that checked exceptions either be caught or declared.
The natural tendency is to immediately wrap the code in a try block and catch the
exception to stop the compile from reporting errors.

The question is, what to do with an exception after it is caught? The absolute worst thing
to do is nothing. An empty catch block swallows the exception, and all information
about what, where, and why something went wrong is lost forever. Logging the exception
is slightly better, since there is at least a record of the exception. But we can hardly
expect that the user will read or even understand the log file and stack trace. It is not
appropriate for readPreferences() to display a dialog with an error message, because
while JCheckbook currently runs as a desktop application, we also plan to make it an
HTML-based web application. In that case, displaying an error dialog is not an option.
Also, in both the HTML and the client/server versions, the preferences would be read on
the server, but the error needs to be displayed in the web browser or on the client. The
readPreferences() method should be designed with these future needs in mind. Proper
separation of user interface code from program logic increases the reusability of our code.

Catching an exception too early, before it can properly be handled, often leads to further
errors and exceptions. For example, had the readPreferences() method shown earlier
immediately caught and logged the FileNotFoundException that could be thrown while
calling the FileInputStream constructor, the code would look something like this:

public void readPreferences(String filename)


{
//...

InputStream in = null;

// DO NOT DO THIS!!!
try
{
in = new FileInputStream(filename);
}
catch (FileNotFoundException e)
{
logger.log(e);
}
in.read(...);

//...
}

This code catches FileNotFoundException, when it really cannot do anything to


recover from the error. If the file is not found, the rest of the method certainly cannot read
from the file. What would happen should readPreferences() be called with the name
of file that doesn't exist? Sure, the FileNotFoundException would be logged, and if we
happened to be looking at the log file at the time, we'd be aware of this. But what
happens when the program tries to read data from the file? Since the file doesn't exist, in
is null, and a NullPointerException gets thrown.

When debugging a program, instinct tells us to look at the latest information in the log.
That's going to be the NullPointerException, dreaded because it is so unspecific. The
stack trace lies, not only about what went wrong (the real error is a
FileNotFoundException, not a NullPointerException), but also about where the
error originated. The problem occurred several lines of code away from where the
NullPointerException was thrown, and it could have easily been several method calls
and classes removed. We end up wasting time chasing red herrings that distract our
attention from the true source of the error. It is not until we scroll back in the log file that
we see what actually caused the program to malfunction.

What should readPreferences() do instead of catching the exceptions? It may seem


counterintuitive, but often the best approach is to simply let it go; don't catch the
exception immediately. Leave that responsibility up to the code that calls
readPreferences(). Let that code determine the appropriate way to handle a missing
preferences file, which could mean prompting the user for another file, using default
values, or, if no other approach works, alerting the user of the problem and exiting the
application.

The way to pass responsibility for handling exceptions further up the call chain is to
declare the exception in the throws clause of the method. When declaring which
exceptions may be thrown, remember to be as specific as possible. This serves to
document what types of exceptions a program calling your method should anticipate and
be ready to handle. For example, the "catch late" version of the readPreferences()
method would look like this:

public void readPreferences(String filename)


throws IllegalArgumentException,
FileNotFoundException, IOException
{
if (filename == null)
{
throw new IllegalArgumentException
("filename is null");
} //if
//...

InputStream in = new FileInputStream(filename);

//...
}

Technically, the only exception we need to declare is IOException, but we document our
code by declaring that the method may specifically throw a FileNotFoundException.
IllegalArgumentException need not be declared, because it is an unchecked exception
(a subclass of RuntimeException). Still, including it serves to document our code (the
exceptions should also be noted in the JavaDocs for the method).

Of course, eventually, your program needs to catch exceptions, or it may terminate


unexpectedly. But the trick is to catch exceptions at the proper layer, where your program
can either meaningfully recover from the exception and continue without causing further
errors, or provide the user with specific information, including instructions on how to
recover from the error. When it is not practical for a method to do either of these, simply
let the exception go so it can be caught later on and handled at the appropriate level.

Conclusion

Experienced developers know that the hardest part of debugging usually is not fixing the
bug, but finding where in the volumes of code the bug hides. By following the three rules
in this article, you can help exceptions help you track down and eradicate bugs and make
your programs more robust and user-friendly.

Jim Cushing began his Java career in 1997 while working at a small Gainesville, FL
company and attending the University of Florida.

View all java.net Articles.

How are you handling exceptions?

Showing messages 1 through 17 of 17.

• Perfect Exception Handling


2007-04-11 06:44:03 abarnea_2000 [Reply | View]

See www.cajoon.com for how exceptions should be handled . . .

No code changes or instrumentation required . . . JVM activated


• More thoughts...
2005-06-28 08:25:56 dcelovic [Reply | View]

http://www.sanabel-solutions.com/mainFrame.php?context=publications
• More thoughts
2003-12-12 07:08:31 ljnelson [Reply | View]

I have a weblog post on this subject, if anyone is interested. Briefly, I try to explain why catching early
and copious wrapping is a good thing--it leads to better messages and simpler archaeological expeditions
when you need to figure out what went wrong.

Cheers,
Laird
• Articles...
2003-12-08 20:53:57 sullis [Reply | View]

Bonus links...

"Best Practices in EJB Exception Handling"


http://www-106.ibm.com/developerworks/java/library/j-ejbexcept.html

"Best Practices for Exception Handling"


http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html

"Designing with Exceptions"


http://www.javaworld.com/jw-07-1998/jw-07-techniques.html

"Exceptions in Java"
http://www.javaworld.com/jw-07-1998/jw-07-exceptions.html

"Exceptional Practices, Part 1"


http://www.javaworld.com/javaworld/jw-08-2001/jw-0803-exceptions.html

"Exceptional Practices, Part 2"


http://www.javaworld.com/javaworld/jw-09-2001/jw-0914-exceptions.html

"When catching exceptions, don't cast your net too wide"


http://www.javaworld.com/javaworld/javatips/jw-javatip134.html

"Use nested exceptions"


http://www.javaworld.com/javaworld/javatips/jw-javatip91.html

"Beware the dangers of generic exceptions"


http://www.javaworld.com/javaworld/jw-10-2003/jw-1003-generics.html
• Don't forget good messages and thinking about how to handle loops.
2003-12-08 20:10:52 emeade [Reply | View]

Exception messages targeted for users not developers.


Assume that some end user will be up at 2:00AM trying to meet some deadline when this exception is
encountered. Give her a chance and
include filenames, URIs<a/>, classnames, or whatever you have that could help.
Personally I think Jakarta's Ant does a great job of giving helpful error messages.

Looping through objects and calling methods that can throw exceptions can also be a challenge. Should
one failure cause everything to stop?
• Rethrowing exceptions is not the best idea....
2003-12-05 09:30:45 krage [Reply | View]

I have experimented with a few aproaches with regards to handling exceptions and came to conclusions
that

rethrowing an exception is not a good idea. Why ? because you are loosing context information available
in catch() clause. The exception being rethrown contains info about context in the lower layer of your
application but it may not be enough to restore the whole sequence of event. For example, you are doing
jdbc call and getting SQLException. You should not rethrow it because it doesn't contain all the
information about parameters of the call. As soon as you leave catch(SQLEXception ex) block you gonna
loose that "context". So, I ususaly have a dedicated Exception class for each layer. The constructor takes
a Throwable from the lower layer and context from the current layer. This way you do not even have to
log the exception on the lower layers.

think what happens with you application if all heap memory is gone ? Any "new" statement will throws a
subclass of Error. So, any mission critical code must be surrounded by at least catch(Throwable ex). If
you decide to put catch(Exception ex) you must have a very good reason why it is not Throwable...
o Every rule has an exception*
2003-12-09 13:46:58 jimothy [Reply | View]

Like any rule, these rules may be broken when there is a good reason for doing so, and when the rule-
breaker is aware of the consequences.

My observation is the vast majority of programmers (that I have worked with) misunderstand effective
exception handling. They catch exceptions much too soon (right where the compiler complains about
it), use generic catch (Exception e) blocks, and either ignore or do nothing more than log the
error.

I offer these rules in hope of breaking those habits. Once you've gained enough understanding of
exceptions in Java to debate the rules (as you have), you're qualified to break them (with care) when
you see fit, because you do understand the consequences. But the average programmer may not, and
for them, it is important for them to be aware of these rules.

Thanks for your feedback. It's interesting that with all that has been written on Java exceptions, there's
always new insight available.

* pun intended
o Catching Errors
2003-12-05 10:14:09 jimothy [Reply | View]

According to the Javadocs, "An Error...indicates serious problems that a reasonable application
should not try to catch."

Catching Error or Throwable is dangerous. For example, if you do catch an OutOfMemoryError, what
are you going to do about it? Trying to recover could lead to further OutOfMemoryErrors.
 Not, reasonable application SHOULD catch it
2003-12-05 11:16:04 krage [Reply | View]

... particularly mission critical.


OutOfMemoryError often happens when the application is trying to allocate a lot of objects or
instance in deserialization, but the whole process can be rolled back by the releasing the created
objects - just set referenrce to null and gc will help you to recover.
Besides, you still can do some other things like notifing your sa.
 Not, reasonable application SHOULD catch it
2003-12-05 13:29:09 jimothy [Reply | View]

My point was, any action to recover from or report an OutOfMemoryError (such as notifying the
sysadmin) could also result in an OoME.

I suppose there's no harm trying. But do keep in mind that the time between setting a reference
to null and that reference being garbage collected is indeterminant.
 Not, reasonable application SHOULD catch it
2003-12-05 17:24:59 krage [Reply | View]

Most time only allocation of a new object will result in a new OutOfMem. exception. You can
still run any code which manipulates already existing objects. As of indeterministic nature of
GC - yes, this is true, but there is an exception. If there is no memory available it WILL start
collecting garbage BEFORE throwing another OutOfMem. exception.
Another thing is when you have catched it then the context in which it was thrown is already
destroyed and the memory is actually available.
 Not, reasonable application SHOULD catch it
2007-11-06 14:01:42 zolyfarkas [Reply | View]

OOM can be thrown in the thread that is not actually causing the memory exhaustion. This
makes recovery from a OOM almost impossible.

OOM is best handled by running VM with: -XX:+HeapDumpOnOutOfMemoryError


-XX:HeapDumpPath=${DUMPS} -XX:OnOutOfMemoryError="kill -9 %p"
• An endless war...
2003-12-05 00:30:25 bitog [Reply | View]

Good article... but a consideration:


proliferation of "throws" clauses tend to be a noise to developers.

I'm used to catch early specific exceptions, log them as much specific I can, and then re-throw a
RuntimeException.
I can catch them later, displaying a message in a UI-dependent way, looking also to the exception cause
(getCause() method)

For example:

public void aMethod(){


...
try{
...
...
}catch (SQLException s){
myLog.log("database errror");
throw new RuntimeException(s);

}catch (FileNotFoundException f){


myLog.log("wrong file name");
throw new RuntimeException(f);

}... and so on
}finally{
// release resources
}
}

What's your opinion?


Thanks
o An endless war...
2003-12-05 05:55:36 jimothy [Reply | View]

Overall, I agree. Declaring checked exceptions has two main problems: First, it does get awkward as
they proliferate, and second, they constitute an abstraction leak, as they reveal implementation details.
Wrapping exceptions addresses both these problems.

I deferred discussing these issues in order to keep the scope of the article in check. I'd like to do a
follow up, and detail this issue there. But in the meantime, I'm uncomfortable wrapping with a
RuntimeException, because it violates the "be specific rule". It also means that your catch blocks likely
will either be generic (simply catching and displaying a RuntimeException) or filled with a bunch of
"instanceof" operations on the cause. This can be awkward.

Also, is it necessary to log "database error" or "wrong file name"? When the re-thrown
RuntimeException is caught, that information will can be logged then. See my personal article,
Exception Horror Stories for comments on the dangers of double-logging.
 An endless war...
2003-12-12 06:01:06 bitog [Reply | View]

I agree on the violation of the "be specific" rule... but, if you don't write the bunch of instance of, you
have to write a lot of "catch", I guess. At least, you could put the "bunch" on a UI-dependendent
utility class.

In order to the double logging: the higher logger could be located in a different layer (a different log
at all), so I have to log as quick as I can DB errors on the DAO layer log and UI errors (Illegal form
parameters and so on) into another possible log.
In addition: when a lower RuntimeException is caught at an higher level, I'm not forced to log it,
because I'm sure that it was already done. All that I want at the UI level, most of the time, is only to
display an error message to the user.

It's great to talk with you on this argument .. ;)


 An endless war...
2003-12-12 06:40:27 jimothy [Reply | View]

It sounds like you've got an exception handling strategy, and that puts you ahead of a lot of
people. But I am apprehensive that you say, "I have to log as quick as I can DB errors...".

How does your UI layer KNOW that an exception occurred at the DAO layer? When the "catch
late" rule is violated, the rest of the program thinks that there was no error. If there's a DB error
reading a DAO, the rest of the program cannot operate on that DAO (attempting to would like
result in NullPointerExceptions).

Of course, I realize there are details of your program I'm missing, and it may be that you are
taking care of these issues perfectly well. But strongly consider the "catch late" rule in the
context of your program. Of my three rules, I'd say this is probably the most important one, and
the one that is least understood.
 An endless war...
2003-12-05 06:05:23 jimothy [Reply | View]

Oops, I should say instead of wrapping in a RuntimeException, I recommend wrapping in an


application or API specific exception, something like a JCheckbookResourceException (to indicate
an error accessing a resource--be it the file system, an SQL database, etc.). I do plan to expound
upon this in a follow up.

It is often difficult to know the best way to handle an exception so here are a few
tips.

1. NEVER leave a catch block empty. Even if you expect it to occur


sometimes and don't want to actually do anything, in this case add a
detailed comment explaining why.
2. Due to the nature of OO programming you can end up with a very long
stack it is often better to throw an exception rather than try and handle it, if
you don't throw it then the method that called the method you are writing
will never know that there was a problem. Ask yourself, can you handle
the problem and return to the method that called yours in such a way that
the method that called yours will not be affected? If so, handle it,
otherwise, throw it.
3. Only try and communicate an exception to the user if your class is
designed to do so, i.e. your class is the user interface. Consider that your
class might end up being used as part of a larger application on a
distributed system where the user will never get to see an error message
you attempt to show them.
4. Avoid catching an exception only to throw a new one. The result of this is
that the stack trace of your new exception will end at your method not the
actual cause of the problem.
5. You can write your own exception classes but unless you give your class
more functionality than the one you are extending, I regard this as a waste
of effort (although there are varying opinions). For example the
java.io.InterruptedIOException provides a property to indicate how many
bytes were transferred before the exception.

1. Syntax
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class ExceptionDemo{


public String getFileContents(String fileName){
try{
InputStream is = new FileInputStream(fileName);
String contents = "";
/*
read file contents
*/
return contents;
}catch(FileNotFoundException fnfe){
return "";
}
}

public String getMyFileContents(String fileName) throws


FileNotFoundException{
InputStream is = new FileInputStream(fileName);
String contents = "";
/*
read file contents
*/
return contents;
}

public ExceptionDemo() {
String contents = "";
contents = getFileContents("c:/hello.txt");
try{
contents = getMyFileContents("c:/hello.txt");
}catch(Exception e){
System.out.println("Failed to read file");
}
}
}
The above example demonstrates the syntax for handling exceptions. This first
method catches an exception and handles it but the second method just throws
any exception. Obviously exceptions have to be handled somewhere so in the
third method (the constructor), when calling the second method we must handle
any exception.

We will now make your family safer by adding some exception handling.

1. Create a new Movie class which has two properties, title and rating.
2. Create a new Cinema class, add method addMovieGoers which takes a
collection of Humans and another method showMovie which does not take
any arguments. Your Cinema class should also have a setMovie method
which takes a Movie as an argument.
3. When the addMovieGoers is called on a cinema instance the movie goers
should be added to a private collection.
4. Add a new method to your family class that returns all family members.
5. In the main method of the Cinema class call a new static method that
creates a family and a cinema then use the addMovieGoers method of the
cinema to add the family members. Next create a new movie and use it to
set the movie property of the cinema. Finally call cinema.showMovie.

Now, if you were careful your code may have executed without exception but
there are quite a few loopholes in your code, to close them do the following.

1. In the showMovie method test whether or not the movie property has been
set, if not throw an exception, also add code to empty the Cinema whether
the movie was shown or not.
2. In the setMovie method check that the movie title and rating have been
set, if not throw an exception.
3. In the addMovieGoers method, check that the movie property has been
set and if not throw an exception.
4. Also in the addMovieGoers method check that every member of the
collection is a human and that they are old enough to watch the movie, if
not throw an exception. Note that although the family has getMovieGoers
method, you can't be sure it was used to build the collection.
5. Finally add another static method to the cinema class that demonstrates
the usage of the cinema class. Include multiple scenarios to show how the
exceptions work.
6. Remember about creating your own exceptions and passing them to the
controlling module (here method with scenarios). After an exception
occurs your code should stop execution of current scenario and go to
another one.

Ensure your code contains plenty of System.out.println statements so that the


flow is clear.
Summary

You now know how to write bullet proof code.

Exception handling is an important part of your code but it is also an area where
many bugs slip in, pay particular attention when writing exception handlers.

GUI

GUI, pronounced gooey, is a TLA (three letter acronym) for graphical user
interface. Basically when we talk about GUIs we are referring to windows based
user interfaces rather than console or web based user interfaces, whether they
are running on Microsoft Windows or any other operating system is irrelevant.

You may be thinking, that sounds like quite a big topic - why is there only one
section?

Well the answer is simple. Java does support full GUI applications through the
Swing API but the vast majority of Java applications are web based or server
based application, only a very small percentage have a GUI so we are not going
to try and learn swing now. But you do need to know it exists and have an
overview of how it works so that you can bare it in mind if you are ever presented
with a situation where a GUI is required.

Java also provides a second API for creating GUIs - AWT, AWT pre-existed
Swing and Swing is basically build on top of AWT

To quote the JDK "[Swing] Provides a set of "lightweight" (all-Java language)


components that, to the maximum degree possible, work the same on all
platforms."

To get the full picture read this article.


Swing Foundations

That article is actually part of an entire Swing book that available online.

If you would like to learn swing there is a good tutorial here.


The Swing Tutorial

Anda mungkin juga menyukai