Bruce Eckel's Thinking in Java Contents | Prev | Next

Chapters

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 Abstract Window 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.

Contents | Prev | Next