This
book was designed with one thing in mind: the way people learn the Java
language. Seminar audience feedback helped me understand which parts were
difficult and needed illumination. In the areas where I got ambitious and
included too many features all at once, I came to know – through the
process of presenting the material – that if you include a lot of new
features, you need to explain them all, and this easily compounds the
student’s confusion. As a result, I’ve taken a great deal of
trouble to introduce the features as few at a time as possible.
The
goal, then, is for each chapter to teach a single feature, or a small group of
associated features, in such a way that no additional features are relied upon.
That way you can digest each piece in the context of your current knowledge
before moving on.
Here
is a brief description of the chapters contained in the book, which correspond
to lectures and exercise periods in my hands-on seminars.
Chapter
1:
Introduction
to objects
This
chapter is an overview of what object-oriented programming is all about,
including the answer to the basic question “What’s an
object?”, interface vs. implementation, abstraction and encapsulation,
messages and functions, inheritance and composition, and the all-important
polymorphism. You’ll also be introduced to issues of object creation such
as constructors, where the objects live, where to put them once they’re
created, and the magical garbage collector that cleans up the objects that are
no longer needed. Other issues will be introduced, including error handling
with exceptions, multithreading for responsive user interfaces, and networking
and the Internet. You’ll also learn about what makes Java special, why
it’s been so successful, and about object-oriented analysis and design.
Chapter
2:
Everything
is an object
This
chapter moves you to the point where you can write your first Java program, so
it must give an overview of the essentials, including the concept of a
“handle” to an object; how to create an object; an introduction to
primitive types and arrays; scoping and the way objects are destroyed by the
garbage collector; how everything in Java is a new data type (class) and how to
create your own classes; functions, arguments, and return values; name
visibility and using components from other libraries; the
static
keyword; comments and embedded documentation.
Chapter
3:
Controlling
program flow
This
chapter begins with all of the operators that come to Java from C and C++. In
addition, you’ll discover common operator pitfalls, casting, promotion,
and precedence. This is followed by the basic control-flow and selection
operations that you get with virtually any programming language: choice with
if-else; looping with for and while; quitting a loop with break and continue as
well as Java’s labeled break and labeled continue (which account for the
“missing goto” in Java); and selection using switch. Although much
of this material has common threads with C and C++ code, there are some
differences. In addition, all the examples will be full Java examples so
you’ll get more comfortable with what Java looks like.
Chapter
4:
Initialization
and cleanup
This
chapter begins by introducing the constructor, which guarantees proper
initialization. The definition of the constructor leads into the concept of
function overloading (since you might want several constructors). This is
followed by a discussion of the process of cleanup, which is not always as
simple as it seems. Normally, you just drop an object when you’re done
with it and the garbage collector eventually comes along and releases the
memory. This portion explores the garbage collector and some of its
idiosyncrasies. The chapter concludes with a closer look at how things are
initialized: automatic member initialization, specifying member initialization,
the order of initialization,
static
initialization and array initialization.
Chapter
5:
Hiding
the implementation
This
chapter covers the way that code is packaged together, and why some parts of a
library are exposed while other parts are hidden. It begins by looking at the
package
and
import
keywords, which perform file-level packaging and allow you to build libraries
of classes. The subject of directory paths and file names is also examined. The
remainder of the chapter looks at the
public,
private,
and
protected
keywords, the concept of “friendly” access, and what the different
levels of access control mean when used in various contexts.
Chapter
6:
Reusing
classes
The
concept of inheritance is standard in virtually all OOP languages. It’s a
way to take an existing class and add to its functionality (as well as change
it, the subject of Chapter 7). Inheritance is often a way to reuse code by
leaving the “base class” the same, and just patching things here
and there to produce what you want. However, inheritance isn’t the only
way to make new classes from existing ones. You can also embed an object inside
your new class with
composition.
In this chapter you’ll learn about these two ways to reuse code in Java,
and how to apply them.
Chapter
7:
Polymorphism
On
your own, you might take nine months to discover and understand polymorphism, a
cornerstone of OOP. Through small, simple examples you’ll see how to
create a family of types with inheritance and manipulate objects in that family
through their common base class. Java’s polymorphism allows you to treat
all objects in this family generically, which means the bulk of your code
doesn’t rely on specific type information. This makes your programs
extensible, so building programs and code maintenance is easier and cheaper. In
addition, Java provides a third way to set up a reuse relationship through the
interface,
which is a pure abstraction of the interface of an object. Once you’ve
seen polymorphism, the interface can be clearly understood. This chapter also
introduces Java 1.1
inner
classes
.
Chapter
8:
Holding
your objects
It’s
a fairly simple program that has only a fixed quantity of objects with known
lifetimes. In general, your programs will always be creating new objects at a
variety of times that will be known only while the program is running. In
addition, you won’t know until run-time the quantity or even the exact
type of the objects you need. To solve the general programming problem, you
need to create any number of objects, anytime, anywhere. This chapter explores
in depth the tools that Java supplies to hold objects while you’re
working with them: the simple arrays and more sophisticated collections (data
structures) such as
Vector
and
Hashtable.
Finally, the new and improved Java 1.2 collections library is explored in depth.
Chapter
9:
Error
handling with exceptions
The
basic philosophy of Java is that badly-formed code will not be run. As much as
possible, the compiler catches problems, but sometimes the problems –
either programmer error or a natural error condition that occurs as part of the
normal execution of the program – can be detected and dealt with only at
run-time. Java has
exception
handling
to deal with any problems that arise while the program is running. This chapter
examines how the keywords
try,
catch,
throw,
throws,
and
finally
work in Java; when you should throw exceptions and what to do when you catch
them. In addition, you’ll see Java’s standard exceptions, how to
create your own, what happens with exceptions in constructors, and how
exception handlers are located.
Chapter
10:
The
Java IO system
Theoretically,
you can divide any program into three parts: input, process, and output. This
implies that IO (input/output) is a pretty important part of the equation. In
this chapter you’ll learn about the different classes that Java provides
for reading and writing files, blocks of memory, and the console. The
distinction between “old” IO and “new” Java 1.1
IO will be shown. In addition, this section examines the process of taking an
object, “streaming” it (so that it can be placed on disk or sent
across a network) and reconstructing it, which is handled for you in Java
version 1.1. Also, Java 1.1’s compression libraries, which are used in
the Java ARchive file format (JAR), are examined.
Chapter
11:
Run-time
type identification
Java
run-time type identification (RTTI) lets you find the exact type of an object
when you have a handle to only the base type. Normally, you’ll want to
intentionally ignore the exact type of an object and let Java’s dynamic
binding mechanism (polymorphism) implement the correct behavior for that type.
But occasionally it is very helpful to know the exact type of an object for
which you have only a base handle. Often this information allows you to perform
a special-case operation more efficiently. This chapter explains what RTTI is
for, how to use it and how to get rid of it when it doesn’t belong there.
In addition, the Java 1.1
reflection
feature is introduced.
Chapter
12:
Passing
and returning objects
Since
the only way you talk to objects in Java is through “handles,” the
concepts of passing an object into a function and returning an object from a
function have some interesting consequences. This chapter explains what you
need to know to manage objects when you’re moving in and out of
functions, and also shows the
String
class, which uses a different approach to the problem.
Chapter
13:
Creating
windows and applets
Java
comes with the
AbstractWindow
Toolkit
(AWT), which is a set of classes that handle windowing in a portable fashion;
these windowing programs can either be applets or stand-alone applications.
This chapter is an introduction to the AWT and the creation of World Wide Web
applets. We’ll also look at pros and cons of the AWT and the GUI
improvements introduced in Java 1.1. The important “Java Beans”
technology is introduced. This is fundamental for the creation of
Rapid-Application Development (RAD) program-building tools. Finally, the new
Java 1.2 “Swing” library is introduced – this provides a
dramatic improvement in UI components for Java.
Chapter
14
:
Multiple
threads
Java
provides a built-in facility to support multiple concurrent subtasks, called
threads,
running within a single program. (Unless you have multiple processors on your
machine, this is only the
appearance
of multiple subtasks.) Although these can be used anywhere, threads are most
powerful when trying to create a responsive user interface so, for example, a
user isn’t prevented from pressing a button or entering data while some
processing is going on. This chapter looks at the syntax and semantics of
multithreading in Java.
Chapter
15:
Network
programming
All
the Java features and libraries seem to really come together when you start
writing programs to work across networks. This chapter explores communication
across the Internet, and the classes that Java provides to make this easier. It
also shows you how to create a Java applet that talks to a
common
gateway interface
(CGI)
program, shows you how to write CGI programs in C++ and covers Java 1.1’s
Java
DataBase Connectivity
(JDBC) and
Remote
Method Invocation
(RMI).
Chapter
16:
Design
patterns
This
chapter introduces the very important and yet non-traditional
“patterns” approach to program design. An example of the design
evolution process is studied, starting with an initial solution and moving
through the logic and process of evolving the solution to more appropriate
designs. You’ll see one way that a design can materialize over time.
Chapter
17:
Projects
This
chapter includes a set of projects that build on the material presented in this
book, or otherwise didn’t fit in earlier chapters. These projects are
significantly more complex than the examples in the rest of the book, and they
often demonstrate new techniques and uses of class libraries.
There
are subjects that didn’t seem to fit within the core of the book, and yet
I find that I discuss them during seminars. These are placed in the appendices.
Appendix
A:
Using
non-Java code
A
totally portable Java program has serious drawbacks: speed and the inability to
access platform-specific services. When you know the platform that you’re
running on, it’s possible to dramatically speed up certain operations by
making them
native
methods
,
which are functions that are written in another programming language
(currently, only C/C++ is supported). There are other ways that Java supports
non-Java code, including CORBA. This appendix gives you enough of an
introduction to these features that you should be able to create simple
examples that interface with non-Java code.
Appendix
B:
Comparing
C++ and Java
If
you’re a C++ programmer, you already have the basic idea of
object-oriented programming, and the syntax of Java no doubt looks very
familiar to you. This makes sense because Java was derived from C++. However,
there are a surprising number of differences between C++ and Java. These
differences are intended to be significant improvements, and if you understand
the differences you’ll see why Java is such a beneficial programming
language. This appendix takes you through the important features that make Java
distinct from C++.
Appendix
C:
Java
programming guidelines
This
appendix contains suggestions to help guide you while performing low-level
program design and writing code.
Appendix
D:
Performance
This
will allow you to find bottlenecks and improve speed in your Java program.
Appendix
E:
A
bit about garbage collection
This
appendix describes the operation and approaches that are used to implement
garbage collection.
Appendix
F:
Recommended
reading
A
list of some of the Java books I’ve found particularly useful.