This book was designed with one thing in mind: the way people learn the Java language. Seminar audience feedback helped me understand the difficult parts that 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, without relying on features that haven’t been introduced yet. 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, that correspond to lectures and exercise periods in the Thinking in Java seminar.
Chapter 1: Introduction to Objects
(Corresponding lecture on the CD ROM). This chapter is an overview of what object-oriented programming is all about, including the answer to the basic question “What is an object?” It looks at interface versus implementation, abstraction and encapsulation, messages and methods, inheritance and composition, and the subtle concept of polymorphism. You’ll also get an overview of 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 learn what makes Java special and why it’s been so successful.
Chapter 2: Everything is an Object
(Corresponding lecture on the CD ROM). This chapter moves you to the point where you can write your first Java program. It begins with an overview of the essentials: the concept of a reference 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); the basics of creating your own classes; methods, arguments, and return values; name visibility and using components from other libraries; the static keyword; and comments and embedded documentation.
Chapter 3: Controlling Program Flow
(Corresponding set of lectures on the CD ROM: Thinking in C). 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.
Chapter 4: Initialization & Cleanup
(Corresponding lecture on the CD ROM). This chapter begins by introducing the constructor, which guarantees proper initialization. The definition of the constructor leads into the concept of method 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
(Corresponding lecture on the CD ROM). 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, that perform file-level packaging and allow you to build libraries of classes. It then examines the subject of directory paths and file names. The remainder of the chapter looks at the public, private, and protected keywords, the concept of package access, and what the different levels of access control mean when used in various contexts.
Chapter 6: Reusing Classes
(Corresponding lecture on the CD ROM). The simplest way to reuse a class is to embed an object inside your new class with composition. However, composition isn’t the only way to make new classes from existing ones. 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. In this chapter you’ll learn how composition and inheritance reuse code in Java, and how to apply them.
Chapter 7: Polymorphism
(Corresponding lecture on the CD ROM). 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 that the bulk of your code doesn’t rely on specific type information. This makes your code more flexible, so building programs and code maintenance is easier and cheaper.
Chapter 8: Interfaces & Inner Classes
Java provides special tool to set up design and reuse relationships: the interface, which is a pure abstraction of the interface of an object. The interface is more than just an abstract class taken to the extreme, since it allows you to perform a variation on C++’s “multiple inheritance” by creating a class that can be upcast to more than one base type.
At first, inner classes look like a simple code-hiding mechanism; you place classes inside other classes. You’ll learn, however, that the inner class does more than that; it knows about and can communicate with the surrounding class. The kind of code you can write with inner classes is more elegant and clear. However, it is a new concept to most, and it takes some time to become comfortable with design using inner classes.
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 a problem—either a 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 discovered during an exception.
Chapter 10: Detecting Types
Java run-time type identification (RTTI) lets you find the exact type of an object when you have a reference to only the base type. Normally, you’ll want to intentionally ignore the exact type 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 reference. Often this information allows you to perform a special-case operation more efficiently. This chapter also introduces the Java reflection mechanism. You’ll learn what RTTI and reflection are for and how to use them, and also how to get rid of RTTI when it doesn’t belong there.
Chapter 11: Collections of 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 anywhere, at any time. This chapter explores in depth the collections library that Java supplies to hold objects while you’re working with them: the simple arrays and more sophisticated containers (data structures) such as ArrayList and HashMap.
Chapter 12: The Java I/O System
Theoretically, you can divide any program into three parts: input, process, and output. This implies that I/O (input/output) is an 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 evolution of the Java I/O framework and the JDK 1.4 “new” I/O (nio) will be examined. In addition, this chapter shows how you can take an object, “stream” it (so that it can be placed on disk or sent across a network), and then reconstruct it, which is handled for you with Java’s object serialization. Java’s compression libraries, which are used in the Java ARchive (JAR) file format, are examined. Finally, the new preferences application program interface (API) and regular expressions are explained.
Chapter 13: Concurrency
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 apparent 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 gives you a solid grounding in the fundamentals of concurrent programming.
Chapter 14: Creating Windows and Applets
Java comes with the Swing GUI library, which is a set of classes that handle windowing in a portable fashion. These windowed programs can either be World Wide Web applets or standalone applications. This chapter is an introduction to the creation of programs using Swing. Applet signing and Java Web Start are demonstrated. Also, the important JavaBeans technology is introduced, which is fundamental for the creation of Rapid Application Development (RAD) program-building tools.
Chapter 15: Discovering Problems
Language-checking mechanisms can take us only so far in our quest to develop a correctly-working program. This chapter presents tools to solve the problems that the compiler doesn’t. One of the biggest steps forward is the incorporation of automated unit testing. For this book, a custom testing system was developed to ensure the correctness of the program output, but the defacto standard JUnit testing system is also introduced. Automatic building is implemented with the open-source standard Ant tool, and for teamwork, the basics of CVS are explained. For problem reporting at run time, this chapter introduces the Java assertion mechanism (shown here used with Design by Contract), the logging API, debuggers, profilers, and even doclets (which can help discover problems in source code).
Chapter 16: Analysis & Design
The object-oriented paradigm is a new and different way of thinking about programming, and many people have trouble at first knowing how to approach an OOP project. Once you understand the concept of an object, and as you learn to think more in an object-oriented style, you can begin to create “good” designs that take advantage of all the benefits that OOP has to offer. This chapter introduces the ideas of analysis, design, and some ways to approach the problems of developing good object-oriented programs in a reasonable amount of time. Topics include Unified Modeling Language (UML) diagrams and associated methodology, use cases, Class-Responsibility-Collaboration (CRC) cards, iterative development, Extreme Programming (XP), ways to develop and evolve reusable code, and strategies for transition to object-oriented programming.
Appendix A: Passing & Returning Objects
Since the only way you talk to objects in Java is through references, the concepts of passing an object into a method and returning an object from a method have some interesting consequences. This appendix explains what you need to know to manage objects when you’re moving in and out of methods, and also shows the String class, which uses a different approach to the problem.
Appendix B: Java Programming Guidelines
This appendix contains suggestions that I have discovered and collected over the years to help guide you while performing low-level program design and writing code.
Appendix C: Supplements
Appendix D: Resources
A list of some of the Java books I’ve found particularly useful.