Buy this Book
Print Book $44.95 Read it Now!
Print Book £31.95
Add to UK Cart
Reprint Licensing

Learning Java
Learning Java, Third Edition

By Patrick Niemeyer, Jonathan Knudsen
Price: $44.95 USD
£31.95 GBP

Cover | Table of Contents


Table of Contents

Chapter 1: A Modern Language
The greatest challenges and most exciting opportunities for software developers today lie in harnessing the power of networks. Applications created today, whatever their intended scope or audience, will almost certainly be run on machines linked by a global network of computing resources. The increasing importance of networks is placing new demands on existing tools and fueling the demand for a rapidly growing list of completely new kinds of applications.
We want software that works—consistently, anywhere, on any platform—and that plays well with other applications. We want dynamic applications that take advantage of a connected world, capable of accessing disparate and distributed information sources. We want truly distributed software that can be extended and upgraded seamlessly. We want intelligent applications—such as autonomous agents that can roam the Net for us, ferreting out information and serving as electronic emissaries. We know, to some extent, what we want. So why don't we have it?
The problem, historically, has been that the tools for building these applications have fallen short. The requirements of speed and portability have been, for the most part, mutually exclusive, and security has been largely ignored or misunderstood. In the past, truly portable languages were bulky, interpreted, and slow. These languages were popular as much for their high-level functionality as for their portability. Fast languages usually provided speed by binding themselves to particular platforms, so they met the portability issue only halfway. There were even a few safe languages, but they were primarily offshoots of the portable languages and suffered from the same problems. Java is a modern language that addresses all three of these fronts: portability, speed, and security. This is why it has become dominant in the world of programming today.
The Java programming language, developed at Sun Microsystems under the guidance of Net luminaries James Gosling and Bill Joy, is designed to be a machine-independent programming language that is both safe enough to traverse networks and powerful enough to replace native executable code. Java addresses the issues raised here and helps us start building the kinds of applications we want.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Enter Java
The Java programming language, developed at Sun Microsystems under the guidance of Net luminaries James Gosling and Bill Joy, is designed to be a machine-independent programming language that is both safe enough to traverse networks and powerful enough to replace native executable code. Java addresses the issues raised here and helps us start building the kinds of applications we want.
Initially, most of the enthusiasm for Java centered on its capabilities for building embedded applications for the Web called applets . But in the early days, applets and other client-side GUI applications written in Java were limited. Today, Java has Swing, one of the most sophisticated toolkits for building graphical user interfaces (GUIs) in any language. This development has allowed Java to become a popular platform for developing traditional client-side application software.
Of even more importance in the past few years, Java has become the premier platform for web-based applications and web services. These applications use technologies including the Java Servlet API, Enterprise JavaBeans?, and many popular open source and commercial Java application servers and frameworks. Java's portability and speed make it the platform of choice for modern business applications.
This book will show you how to use Java to accomplish all of these real-world programming tasks. In the coming chapters we'll cover everything from text processing to networking, building rich client-side GUI applications with Swing and lightweight web-based applications with XML.
The seeds of Java were planted in 1990 by Sun Microsystems patriarch and chief researcher, Bill Joy. At the time, Sun was competing in a relatively small workstation market while Microsoft was beginning its domination of the more mainstream, Intel-based PC world. When Sun missed the boat on the PC revolution, Joy retreated to Aspen, Colorado to work on advanced research. He was committed to the idea of accomplishing complex tasks with simple software and founded the aptly named Sun Aspen Smallworks.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
A Virtual Machine
Java is both a compiled and an interpreted language. Java source code is turned into simple binary instructions, much like ordinary microprocessor machine code. However, whereas C or C++ source is reduced to native instructions for a particular model of processor, Java source is compiled into a universal format—instructions for a virtual machine.
Compiled Java bytecode is executed by a Java runtime interpreter. The runtime system performs all the normal activities of a real processor, but it does so in a safe, virtual environment. It executes a stack-based instruction set and manages memory like an operating system. It creates and manipulates primitive data types and loads and invokes newly referenced blocks of code. Most importantly, it does all this in accordance with a strictly defined open specification that can be implemented by anyone who wants to produce a Java-compliant virtual machine. Together, the virtual machine and language definition provide a complete specification. There are no features of the base Java language left undefined or implementation-dependent. For example, Java specifies the sizes and mathematical properties of all its primitive data types rather than leaving it up to the platform implementation.
The Java interpreter is relatively lightweight and small; it can be implemented in whatever form is desirable for a particular platform. The interpreter may be run as a separate application, or it can be embedded in another piece of software, such as a web browser. Put together, this means that Java code is implicitly portable. The same Java application bytecode can run on any platform that provides a Java runtime environment, as shown in Figure 1-1. You don't have to produce alternative versions of your application for different platforms, and you don't have to distribute source code to end users.
Figure 1-1: The Java runtime environment
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Java Compared with Other Languages
Java is a relatively new language, but it draws on many years of programming experience with other languages in its choice of features. It is worth taking a moment to compare Java at a high level with some other popular languages today, both for the benefit of those of you with other programming experience and for the newcomers who need to put things in context. We do not expect you to have a knowledge of any particular programming language in this book and when we refer to other languages by way of comparison we hope that the comments are self-explanatory.
At least three pillars are necessary to support a universal programming language today: portability, speed, and security. Figure 1-2 shows how Java compares to a couple of other languages.
Figure 1-2: Programming languages compared
You may have heard that Java is a lot like C or C++, but that's really not true, except at a superficial level. When you first look at Java code, you'll see that the basic syntax looks like C or C++. But that's where the similarities end. Java is by no means a direct descendant of C or a next-generation C++. If you compare language features, you'll see that Java actually has more in common with highly dynamic languages such as Smalltalk and Lisp. In fact, Java's implementation is about as far from native C as you can imagine.
The surface-level similarities to these languages are worth noting, however. Java borrows heavily from C and C++ syntax, so you'll see terse language constructs, including an abundance of curly braces and semicolons. Java subscribes to the C philosophy that a good language should be compact; in other words, it should be sufficiently small and regular so a programmer can hold all the language's capabilities in his or her head at once. Just as C is extensible with libraries, packages of Java classes can be added to the core language components to extend its vocabulary.
C has been successful because it provides a reasonably feature-packed programming environment, with high performance and an acceptable degree of portability. Java also tries to balance functionality, speed, and portability, but it does so in a very different way. C trades functionality for portability; Java initially traded speed for portability. Java also addresses security issues while C doesn't.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Safety of Design
You have no doubt heard a lot about the fact that Java is designed to be a safe language. But what do we mean by safe? Safe from what or whom? The security features that attract the most attention for Java are those features that make possible new types of dynamically portable software. Java provides several layers of protection from dangerously flawed code as well as more mischievous things such as viruses and Trojan horses. In the next section, we'll take a look at how the Java virtual machine architecture assesses the safety of code before it's run and how the Java class loader (the bytecode loading mechanism of the Java interpreter) builds a wall around untrusted classes. These features provide the foundation for high-level security policies that can allow or disallow various kinds of activities on an application-by-application basis.
In this section, though, we'll look at some general features of the Java programming language. Perhaps more important than the specific security features, although often overlooked in the security din, is the safety that Java provides by addressing common design and programming problems. Java is intended to be as safe as possible from the simple mistakes we make ourselves as well as those we inherit from legacy software. The goal with Java has been to keep the language simple, provide tools that have demonstrated their usefulness, and let users build more complicated facilities on top of the language when needed.
With Java, simplicity rules. Since Java started with a clean slate, it was able to avoid features that proved to be messy or controversial in other languages. For example, Java doesn't allow programmer-defined operator overloading (which in some languages allows programmers to redefine the meaning of basic symbols like + and -). Java doesn't have a source code preprocessor, so it doesn't have things like macros, #define statements, or conditional source compilation. These constructs exist in other languages primarily to support platform dependencies, so in that sense, they should not be needed in Java. Conditional compilation is also commonly used for debugging, but Java's sophisticated runtime optimizations and features such as
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Safety of Implementation
It's one thing to create a language that prevents you from shooting yourself in the foot; it's quite another to create one that prevents others from shooting you in the foot.
Encapsulation is the concept of hiding data and behavior within a class; it's an important part of object-oriented design. It helps you write clean, modular software. In most languages, however, the visibility of data items is simply part of the relationship between the programmer and the compiler. It's a matter of semantics, not an assertion about the actual security of the data in the context of the running program's environment.
When Bjarne Stroustrup chose the keyword private to designate hidden members of classes in C++, he was probably thinking about shielding you from the messy details of a class developer's code, not the issues of shielding that developer's classes and objects from attack by someone else's viruses and Trojan horses. Arbitrary casting and pointer arithmetic in C or C++ make it trivial to violate access permissions on classes without breaking the rules of the language. Consider the following code:
    // C++ code
    class Finances {
        private:
            char creditCardNumber[16];
            ...
    };

    main() {
        Finances finances;

        // Forge a pointer to peek inside the class
        char *cardno = (char *)&finances;
        printf("Card Number = %s\n", cardno);
    }
In this little C++ drama, we have written some code that violates the encapsulation of the Finances class and pulls out some secret information. This sort of shenanigan—abusing an untyped pointer—is not possible in Java. If this example seems unrealistic, consider how important it is to protect the foundation (system) classes of the runtime environment from similar kinds of attacks. If untrusted code can corrupt the components that provide access to real resources, such as the filesystem, the network, or the windowing system, it certainly has a chance at stealing your credit card numbers.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Application and User-Level Security
There's a fine line between having enough power to do something useful and having all the power to do anything you want. Java provides the foundation for a secure environment in which untrusted code can be quarantined, managed, and safely executed. However, unless you are content with keeping that code in a little black box and running it just for its own benefit, you will have to grant it access to at least some system resources so that it can be useful. Every kind of access carries with it certain risks and benefits. For example, in the web browser environment, the advantages of granting an untrusted (unknown) applet access to your windowing system are that it can display information and let you interact in a useful way. The associated risks are that the applet may instead display something worthless, annoying, or offensive. Since most people can accept that level of risk, graphical applets and the Web in general are possible.
At one extreme, the simple act of running an application gives it a resource—computation time—that it may put to good use or burn frivolously. It's difficult to prevent an untrusted application from wasting your time or even attempting a "denial of service" attack. At the other extreme, a powerful, trusted application may justifiably deserve access to all sorts of system resources (e.g., the filesystem, process creation, network interfaces); a malicious application could wreak havoc with these resources. The message here is that important and sometimes complex security issues have to be addressed.
In some situations, it may be acceptable to simply ask the user to "okay" requests. With Sun's Java plug-in, web browsers can pop up a dialog box and ask the user's permission for an applet to access an otherwise restricted file. However, we can put only so much burden on our users. An experienced person will quickly grow tired of answering questions; an inexperienced user may not be able to answer the questions correctly. Is it okay for me to grant an applet access to something if I don't understand what that is?
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Java and the Web
The application-level safety features of Java make it possible to develop new kinds of applications that were not feasible before. A web browser that uses the Java runtime system can incorporate Java applets as executable content inside documents. This means that web pages can contain not only static textual information but also full-fledged interactive applications. The added potential for use of the Web is enormous. A user can retrieve and use software simply by navigating with a web browser. Formerly static information can be paired with portable software for interpreting and using the information. Instead of just providing some data for a spreadsheet, for example, a web document might contain a fully functional spreadsheet application embedded within it that allows users to view and manipulate the information. In recent years, some of this has started to happen, but the full potential has not yet been realized.
In addition to applets, a more recent model for Internet downloadable application content is Java Web Start. The Web Start API allows your web browser to install applications locally, with security still enforced by the Java runtime system. This system can also automatically update the software when it is used. We'll discuss this more in Chapter 23.
The term "applet" is used to mean a small, subordinate, or embeddable application. By "embeddable," we mean it's designed to be run and used within the context of a larger system. In that sense, most programs are embedded within a computer's operating system. An operating system manages its native applications in a variety of ways: it starts, stops, suspends, and synchronizes applications; it provides them with certain standard resources; and it protects them from one another by partitioning their environments.
As far as the web browser model is concerned, an applet is just another type of object to display; it's embedded into an HTML page with a special tag. Java-enabled web browsers can execute applets directly, in the context of a particular document, as shown in Figure 1-4. Browsers can also implement this feature using Sun's Java Plug-in, which runs Java just like other browser plug-ins display other kinds of content.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Java as a General Application Language
Java was introduced to the world through the web browser and the Java applet API. However, Java is more than just a tool for building multimedia applications. Java is a powerful, general-purpose programming language that just happens to be safe and architecture-independent. Standalone Java applications are not subject to the restrictions placed on applets; they can perform the same jobs as do programs written in languages such as C and C++.
Any software that implements the Java runtime system can run Java applications. Applications written in Java can be large or small, standalone or component-like, as in other languages. Java applets are different from other Java applications only in that they expect to be managed by a larger application. They are also normally considered untrusted code. In this book, we will build examples of both applets and standalone Java applications. With the exception of the few things untrusted applets can't do, such as access files, all the tools we examine in this book apply to both applets and standalone Java applications.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
A Java Road Map
With everything that's going on, it's hard to keep track of what's available now, what's promised, and what has been around for some time. The following sections comprise a road map that imposes some order on Java's past, present, and future.
Java 1.0 provided the basic framework for Java development: the language itself plus packages that let you write applets and simple applications. Although 1.0 is officially obsolete, there are still a lot of applets in existence that conform to its API.
Java 1.1 superseded 1.0, incorporating major improvements in the Abstract Window Toolkit (AWT) package (Java's original GUI facility), a new event pattern, new language facilities such as reflection and inner classes, and many other critical features. Java 1.1 is the version that was supported natively by most versions of Netscape and Microsoft Internet Explorer for many years. For various political reasons, the browser world was frozen in this condition for a long time. This version of Java is still considered a sort of baseline for applets, although even this will fall away as Microsoft drops support for Java in their platforms.
Java 1.2, dubbed "Java 2" by Sun, was a major release in December 1998. It provided many improvements and additions, mainly in terms of the set of APIs that were bundled into the standard distributions. The most notable additions were the inclusion of the Swing GUI package as a core API and a new, full-fledged 2D drawing API. Swing is Java's advanced user interface toolkit with capabilities far exceeding the old AWT's. (Swing, AWT, and some other packages have been variously called the JFC, or Java Foundation Classes.) Java 1.2 also added a proper Collections API to Java.
Java 1.3, released in early 2000, added minor features but was primarily focused on performance. With Version 1.3, Java got significantly faster on many platforms and Swing received many bug fixes. In this timeframe, Java enterprise APIs such as Servlets and Enterprise JavaBeans also matured.
Java 1.4, released in 2002, integrated a major new set of APIs and many long-awaited features. This included language assertions, regular expressions, preferences and logging APIs, a new I/O system for high-volume applications, standard support for XML, fundamental improvements in AWT and Swing, and a greatly matured Java Servlets API for web applications.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: A First Application
Before diving into our full discussion of the Java language, let's get our feet wet by jumping into some working code and splashing around a bit. In this chapter, we'll build a friendly little application that illustrates many of the concepts used throughout the book. We'll take this opportunity to introduce general features of the Java language and applications.
This chapter also serves as a brief introduction to the object-oriented and multithreaded aspects of Java. If these concepts are new to you, we hope that encountering them here in Java for the first time will be a straightforward and pleasant experience. If you have worked with another object-oriented or multithreaded programming environment, you should especially appreciate Java's simplicity and elegance. This chapter is intended only to give you a bird's eye view of the Java language and a feel for how it is used. If you have trouble with any of the concepts introduced here, rest assured they will be covered in greater detail later in the book.
We can't stress enough the importance of experimentation as you learn new concepts here and throughout the book. Don't just read the examples—run them. The source code for these examples and all of the examples in this book can be found on the accompanying CD-ROM and on our web site at http://www.oreilly.com/catalog/learnjava3. Compile the programs and try them. Then, turn our examples into your examples: play with them, change their behavior, break them, fix them, and hopefully have some fun along the way.
In this chapter, we concentrate on Java concepts and do not spend much time on tools. So we will refer only to the command-line java runtime and the javac compiler for Java 5.0. But we have also packaged all of the example code in this book to be run with the open-source Eclipse integrated development environment (IDE). If you would like to follow along with the examples using Eclipse, see Appendix A for an introduction to Eclipse and full instructions on loading the example project. You can then return here to follow along as we build the examples.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Java Tools and Environment
In this chapter, we concentrate on Java concepts and do not spend much time on tools. So we will refer only to the command-line java runtime and the javac compiler for Java 5.0. But we have also packaged all of the example code in this book to be run with the open-source Eclipse integrated development environment (IDE). If you would like to follow along with the examples using Eclipse, see Appendix A for an introduction to Eclipse and full instructions on loading the example project. You can then return here to follow along as we build the examples.
If you want to use the command line to follow our examples, you'll need to install the Sun Java Development Environment (JDK) before proceeding. As described at the end of Chapter 1, you can get the latest version online or find Java 5.0 on the CD accompanying this book. The Java 5.0 JDK is called, somewhat confusingly, JDK 1.5. The JDK comes with a standard installer. If you have problems running the command-line tools, turn to "Troubleshooting" at the end of this chapter for some guidance.
We'll show a Windows command prompt in this chapter. To follow along using the command line, simply open a command window. (Under Windows, select Start Run. Type command and press Enter.) Type the given command, and press Enter.
    C:\> javac HelloJava
               .java
         
The command you enter is identical on Unix, except where explicitly noted. Most other command-line examples throughout the book show a Unix shell prompt instead:
    % javac HelloJava.java
         
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
HelloJava
In the tradition of introductory programming texts, we will begin with Java's equivalent of the archetypal "Hello World" application, HelloJava.
We'll end up taking four passes at this example before we're done (HelloJava, HelloJava2, etc.), adding features, and introducing new concepts along the way. But let's start with the minimalist version:
    public class HelloJava {
      public static void main( String[] args ) {
        System.out.println("Hello, Java!");
      }
    }
This five-line program declares a class called HelloJava and a method called main() . It uses a predefined method called println() to write some text as output. This is a command-line program, which means that it runs in a shell or DOS window and prints its output there. That's a bit old school for our taste, so before we go any further, we're going to give HelloJava a graphical user interface (GUI). Don't worry about the code yet; just follow along with the progression here, and we'll come back for explanations in a moment.
In place of the line containing the println() method, we're going to use something called a JFrame object to put a window on the screen. We can start by replacing the println line with the following three lines:
    JFrame frame = new JFrame( "Hello, Java!" );
    frame.setSize( 300, 300 );
    frame.setVisible( true );
This snippet creates a JFrame object with the title "Hello, Java!" The JFrame is a graphical window. To display it, we simply configure its size on the screen using the setSize() method and make it visible by calling the setVisible() method.
If we stopped here, we would see an empty window on the screen with our "Hello, Java!" banner as its title. We'd like our message inside the window, not just scrawled on the top of it. To put something in the window, we need a couple more lines. The following, complete example adds a JLabel object to display the text centered in our window. The additional
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
HelloJava2: The Sequel
Now that we've got some basics down, let's make our application a little more interactive. The following minor upgrade, HelloJava2 , allows us to drag the message text around with the mouse.
We'll call this example HelloJava2 rather than cause confusion by continuing to expand the old one, but the primary changes here and further on lie in adding capabilities to the HelloComponent class and simply making the corresponding changes to the names to keep them straight, e.g., HelloComponent2, HelloComponent3, etc. Having just seen inheritance at work, you might wonder why we aren't creating a subclass of HelloComponent and exploiting inheritance to build upon our previous example and extend its functionality. Well, in this case, that would not provide much advantage, and for clarity we simply start over.
Here is HelloJava2:
    //file: HelloJava2.java
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;

    public class HelloJava2
    {
      public static void main( String[] args ) {
        JFrame frame = new JFrame( "HelloJava2" );
        frame.getContentPane().add( new HelloComponent2("Hello, Java!") );
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.setSize( 300, 300 );
        frame.setVisible( true );
      }
    }

    class HelloComponent2 extends JComponent
        implements MouseMotionListener
    {
      String theMessage;
      int messageX = 125, messageY = 95; // Coordinates of the message

      public HelloComponent2( String message ) {
        theMessage = message;
        addMouseMotionListener(this);
      }

      public void paintComponent( Graphics g ) {
        g.drawString( theMessage, messageX, messageY );
      }

      public void mouseDragged(MouseEvent e) {
        // Save the mouse coordinates and paint the message.
        messageX = e.getX();

        messageY = e.getY();
        repaint();
      }

      public void mouseMoved(MouseEvent e) { }
    }
Two slashes in a row indicates that the rest of the line is a comment. We've added a few comments to HelloJava2
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
HelloJava3: The Button Strikes!
Now we can move on to some fun stuff. HelloJava3 brings us a new graphical interface component: JButton . In this example, we add a JButton component to our application that changes the color of our text each time the button is pressed. The draggable-message capability is still there, too. Our new code looks like this:
    //file: HelloJava3.java
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;

    public class HelloJava3
    {

      public static void main( String[] args ) {
        JFrame frame = new JFrame( "HelloJava3" );
        frame.add( new HelloComponent3("Hello, Java!") );
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.setSize( 300, 300 );
        frame.setVisible( true );
      }
    }

    class HelloComponent3 extends JComponent
        implements MouseMotionListener, ActionListener
    {
      String theMessage;
      int messageX = 125, messageY = 95;  // Coordinates of the message

      JButton theButton;

      int colorIndex;  // Current index into someColors
      static Color[] someColors = {
        Color.black, Color.red, Color.green, Color.blue, Color.magenta };

      public HelloComponent3( String message ) {
        theMessage = message;
        theButton = new JButton("Change Color");
        setLayout( new FlowLayout() );
        add( theButton );
        theButton.addActionListener( this );
        addMouseMotionListener( this );
      }

      public void paintComponent( Graphics g ) {
        g.drawString( theMessage, messageX, messageY );
      }

      public void mouseDragged( MouseEvent e ) {
        messageX = e.getX();
        messageY = e.getY();
        repaint();
      }

      public void mouseMoved( MouseEvent e ) {}

      public void actionPerformed( ActionEvent e ) {
        // Did somebody push our button?
        if (e.getSource() == theButton)
          changeColor();
      }

      synchronized private void changeColor() {
        // Change the index to the next color, awkwardly.
        if (++colorIndex == someColors.length)
          colorIndex = 0;
        setForeground( currentColor() ); // Use the new color.
        repaint();
      }


      synchronized private Color currentColor() {
        return someColors[colorIndex];
      }
    }
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
HelloJava4: Netscape's Revenge
We have explored quite a few features of Java with the first three versions of the HelloJava application. But until now, our application has been rather passive; it has been completely event-driven, waiting patiently for events to come its way and responding to the whims of the user. Now our application is going to take some initiative—HelloJava4 will blink! Here is the code for our latest version:
    //file: HelloJava4.java
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;

    public class HelloJava4
    {
      public static void main( String[] args ) {
        JFrame frame = new JFrame( "HelloJava4" );
        frame.add( new HelloComponent4("Hello, Java!") );
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.setSize( 300, 300 );
        frame.setVisible( true );
      }
    }

    class HelloComponent4 extends JComponent
        implements MouseMotionListener, ActionListener, Runnable
    {
      String theMessage;
      int messageX = 125, messageY = 95; // Coordinates of the message

      JButton theButton;

      int colorIndex; // Current index into someColors.
      static Color[] someColors = {
        Color.black, Color.red, Color.green, Color.blue, Color.magenta };

      boolean blinkState;


      public HelloComponent4( String message ) {
        theMessage = message;
        theButton = new JButton("Change Color");
        setLayout( new FlowLayout() );
        add( theButton );
        theButton.addActionListener( this );
        addMouseMotionListener( this );
        Thread t = new Thread( this );
        t.start();
      }

      public void paintComponent( Graphics g ) {
        g.setColor(blinkState ? getBackground() : currentColor());
        g.drawString(theMessage, messageX, messageY);
      }

      public void mouseDragged(MouseEvent e) {
        messageX = e.getX();
        messageY = e.getY();
        repaint();
      }

      public void mouseMoved(MouseEvent e) { }

      public void actionPerformed( ActionEvent e ) {
        if ( e.getSource() == theButton )
          changeColor();
      }

      synchronized private void changeColor() {
        if (++colorIndex == someColors.length)
          colorIndex = 0;
        setForeground( currentColor() );
        repaint();
      }

      synchronized private Color currentColor() {
        return someColors[colorIndex];
      }

      public void run() {
        try {
          while(true) {
            blinkState = !blinkState; // Toggle blinkState.
            repaint(); // Show the change.
            Thread.sleep(300);
          }
        } catch (InterruptedException ie) { }
      }
    }
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Troubleshooting
If you are having trouble with the java or javac commands, this section provides some guidance about what might be wrong. If you do not feel comfortable with the command line, you might prefer to run the examples in the Eclipse IDE. See Appendix A for an introduction to Eclipse and full instructions on running the example code.
If the javac command is not found, you may have installed the JRE (Java runtime environment) instead of the JDK. Install Java 5.0 (also known as JDK 1.5), as described in "Java Tools and Environment" at the beginning of this chapter.
If you are getting syntax error messages on the HelloJava examples, it is likely that your source code has a mistake or that the source file has become corrupted. The best way to eliminate this possibility is to copy the source directly from the ZIP file on the CD or download them from the examples link at the web site for this book, http://www.oreilly.com/catalog/learnjava3/.
Most runtime errors are related to the Java CLASSPATH environment variable.
If you are getting NoClassDefFound or ClassNotFound errors when attempting to run the examples using the java command, you may have a classpath issue. By default there should be no value set in the environment variable CLASSPATH, but some untidy applications may set this value for you when you install them.
To display the value of CLASSPATH under Windows, use this command:
    C:\> set classpath
            
Use this command for Unix:
    % echo $CLASSPATH
            
To clear any CLASSPATH value, use this command under Windows:
    C:\> set classpath=
            
Use this command for Unix:
    % unset CLASSPATH; export CLASSPATH
            
To check the version of Java, use the -version switch with the java command. Type the following at the command prompt and press Enter:
    C:\> java -version
            
This should report "java version 5.0." If it doesn't, install Java 5.0 as described in "Java Tools and Environment" at the beginning of this chapter.
What if you get an error that says
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 3: Tools of the Trade
There are many options for Java development environments, ranging from the traditional text editor and command-line tools to a whole slew of advanced IDEs, including IBM's Eclipse, Sun's NetBeans, and Borland's JBuilder. (Both Eclipse and NetBeans are open source projects and can be downloaded for free as well as found on the CD-ROM accompanying this book.) The examples in this book were developed using Sun's no-frills Java Development Kit (JDK) on, at various times, Solaris, Windows, and Mac OS X platforms. The JDK includes the basic tools needed to compile, run, and package Java applications, and we will describe these tools in this chapter. But there is no reason you can't use your preferred IDE to follow along with the examples in this book. The source code for all of the examples can be found on the CD-ROM.
For an introduction to the Eclipse IDE and instructions for loading all of the examples in this book as an Eclipse project, see Appendix A. In Chapter 22, we introduce the NetBeans IDE with our discussion of the JavaBeans component architecture, so you will get little GUI development environment flavor there.
A Java virtual machine (VM) is software that implements the Java runtime system and executes Java applications. It can be a standalone application like the java program that comes with the JDK or part of a larger application like a browser. Usually the interpreter itself is a native application, supplied for each platform, which then bootstraps other tools written in the Java language. Tools such as Java compilers and IDEs are often implemented directly in Java to maximize their portability and extensibility. NetBeans, for example, is a pure-Java application.
The Java VM performs all the runtime activities of Java. It loads Java class files, verifies classes from untrusted sources, and executes the compiled bytecode. It manages memory and system resources. In implementations that support dynamic compilation, the interpreter also serves as a specialized compiler that turns Java bytecode into native machine instructions.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Java VM
A Java virtual machine (VM) is software that implements the Java runtime system and executes Java applications. It can be a standalone application like the java program that comes with the JDK or part of a larger application like a browser. Usually the interpreter itself is a native application, supplied for each platform, which then bootstraps other tools written in the Java language. Tools such as Java compilers and IDEs are often implemented directly in Java to maximize their portability and extensibility. NetBeans, for example, is a pure-Java application.
The Java VM performs all the runtime activities of Java. It loads Java class files, verifies classes from untrusted sources, and executes the compiled bytecode. It manages memory and system resources. In implementations that support dynamic compilation, the interpreter also serves as a specialized compiler that turns Java bytecode into native machine instructions.
Throughout most of this book, we'll be building standalone Java programs, but we'll make frequent references to Java applets as well. Both are kinds of Java applications run by a Java VM. A standalone Java application is a complete program intended to be run independently. An applet is, conceptually, an embeddable component to be used in a larger application. Both technically and in usage there is not much difference between the two, other than the Java VM can't run an applet directly. To run an applet, you must use a web browser or the appletviewer tool that comes with the JDK.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Running Java Applications
A standalone Java application must have at least one class that contains a method called main(), which contains the first code to be executed upon start up. To run the application, start the VM, specifying that class as an argument. You can also specify options to the interpreter as well as arguments to be passed to the application. Sun's Java VM is called java:
    % java [interpreter options] class_name [program arguments]
The class should be specified as a fully qualified class name, including the package name, if any. Note, however, that you don't include the .class file extension. Here are a couple of examples:
    % java animals.birds.BigBird
    % java MyTest
         
The interpreter searches for the class in the classpath, a list of directories and archive files where classes are stored. We'll discuss the classpath in detail in the next section. The classpath can be specified either by an environment variable or with the command-line option -classpath. If both are present, the command-line option is used.
Alternately, the java command can be used to launch an "executable" Java archive (JAR) file:
    % java -jar spaceblaster.jar
         
In this case, the JAR file is annotated with the name of the class containing the main() method and the classpath becomes the JAR file itself.
However it is launched, after loading the first class, the interpreter executes the class's main() method. From there, the application can reference other classes, start additional threads, and create its user interface or other structures, as shown in Figure 3-1.
Figure 3-1: Starting a Java application
The main() method must have the right method signature . A method signature is the set of information that defines the method. It includes the method's name, arguments, and return type, as well as type and visibility modifiers. The main() method must be a public, static method that takes an array of String objects as its argument and does not return any value (
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Classpath
The concept of a path should be familiar to anyone who has worked on a DOS or Unix platform. It's an environment variable that provides an application with a list of places to look for some resource. The most common example is a path for executable programs. In a Unix shell, the PATH environment variable is a colon-separated list of directories that are searched, in order, when the user types the name of a command. The Java CLASSPATH environment variable, similarly, is a list of locations that are searched for Java class files. Both the Java interpreter and the Java compiler use the CLASSPATH when searching for packages and Java classes.
An element of the classpath can be a directory or JAR file. Java also supports archives in the conventional ZIP format, but JAR and ZIP are really the same format. JARs are simple archives that include extra files (metadata) that describe each archive's contents. JAR files are created with the JDK's jar utility; many tools for creating ZIP archives are publicly available and can be used to inspect or create JAR files. The archive format enables large groups of classes and their resources to be distributed in a single file; the Java runtime automatically extracts individual class files from an archive as needed.
The precise means and format for setting the classpath vary from system to system. On a Unix system (including Mac OS X), you set the CLASSPATH environment variable with a colon-separated list of directories and class archive files:
    % CLASSPATH=/home/vicky/Java/classes:/home/josh/lib/foo.jar:.
    % export CLASSPATH
         
This example specifies a classpath with three locations: a directory in the user's home, a JAR file in another user's directory, and the current directory, which is always specified with a dot (.). The last component of the classpath, the current directory, is useful when tinkering with classes.
On a Windows system, the CLASSPATH environment variable is set with a semicolon-separated list of directories and class archive files:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Java Compiler
In this section, we'll say a few words about javac, the Java compiler in the JDK. The javac compiler is written entirely in Java, so it's available for any platform that supports the Java runtime system. javac turns Java source code into a compiled class that contains Java bytecode. By convention, source files are named with a .java extension; the resulting class files have a .class extension. Each source code file is considered a single compilation unit. As you'll see in Chapter 6, classes in a given compilation unit share certain features, such as package and import statements.
javac allows one public class per file and insists the file have the same name as the class. If the filename and class name don't match, javac issues a compilation error. A single file can contain multiple classes, as long as only one of the classes is public. Avoid packing too many classes into a single source file. Packing classes together in a .java file only superficially associates them. In Chapter 6 we'll talk about inner classes, classes that contain other classes and interfaces.
As an example, place the following source code in file BigBird.java:
    package animals.birds;

    public class BigBird extends Bird {
    }
Next, compile it with:
    % javac BigBird.java
         
Unlike the Java interpreter, which takes just a class name as its argument, javac needs a filename (with the .java extension) to process. The previous command produces the class file BigBird.class in the same directory as the source file. While it's nice to see the class file in the same directory as the source for this example, for most real applications, you need to store the class file in an appropriate place in the classpath.
You can use the -d option with javac to specify an alternative directory for storing the class files javac generates. The specified directory is used as the root of the class hierarchy, so .class files are placed in this directory or in a subdirectory below it, depending on whether the class is contained in a package. (The compiler creates intermediate subdirectories automatically, if necessary.) For example, we can use the following command to create the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
JAR Files
Java Archive (JAR) files are Java's suitcases. They are the standard and portable way to pack up all the parts of your Java application into a compact bundle for distribution or installation. You can put whatever you want into a JAR file: Java class files, serialized objects, data files, images, sounds, etc. As we'll see in Chapter 23, a JAR file can carry one or more digital signatures that attest to its integrity and authenticity. A signature can be attached to the file as a whole or to individual items in the file.
The Java runtime system understands JAR files and can load class files directly from an archive. So you can pack your application's classes in a JAR file and place it in your CLASSPATH, as described earlier. You can do the equivalent for applets by listing the JAR file in the ARCHIVE attribute of the HTML <applet> tag. Nonclass files (data, images, etc.) contained in your JAR file can also be retrieved from the classpath using the getResource() method (described in Chapter 12). Using this facility, your code doesn't have to know whether any resource is in a plain file or a member of a JAR archive. Whether a given class or datafile is an item in a JAR file, an individual file on the classpath, or an applet on a remote server, you can always refer to it in a standard way and let Java's class loader resolve the location.
Items stored in JAR files are compressed with the standard ZIP file compression. Compression makes downloading classes over a network much faster. A quick survey of the standard Java distribution shows that a typical class file shrinks by about 40 percent when it is compressed. Text files such as arbitrary HTML or ASCII containing English words often compress to one-quarter their original size. (On the other hand, image files don't get much smaller when compressed; most of the common image formats have compression built in.)
Compression is not the only advantage that a JAR file has for transporting files over a network. Placing all the classes in a single JAR file enables them to be downloaded in a single transaction. Eliminating the overhead of making HTTP requests is likely to be a big savings, since individual class files tend to be small, and a complex applet could easily require many of them. On the downside, startup time could be increased if a large JAR file must be downloaded over a slow connection before the applet can start up.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Policy Files
One of the truly novel things about Java is that security is built into the language. As described in Chapter 1, the Java VM can verify class files and Java's security manager can impose limits on what classes do. In early versions of Java, it was necessary to implement security policies programmatically by writing a Java security manager class and using it in your application. A major shift occurred in Java 1.2, when a new declarative security system was added. This system allows you to write policy files —text-based descriptions of permissions—which are much simpler and don't require code changes. These policy files tell the security manager what to allow and disallow and for whom.
With security policies you can answer questions such as: "If I download a program from somewhere on the Internet, how can I prevent it from stealing information on my computer and sending it back to someone else?" "How can I prevent a malicious program from disabling my computer or erasing data on my disk?" Most computing platforms have no answer for these questions.
In early versions of Java, much of the buzz had to do with the security of applets. Applets generally run with security restrictions that prevent them from doing questionable things such as reading from or writing to the disk or contacting arbitrary computers on the network. With security policy files, it's just as easy to apply applet-style security to any application without modifying it. Furthermore, it's easy to fine-tune the access you grant. For example, you can allow an application to access only a specific directory on the disk, or you can allow network access to certain addresses.
Understanding security and security policies is important, so we'll cover it here. However, in practice, you probably won't use this facility yourself, unless you are writing a framework for running applications from many unknown sources. Java Web Start is an example of such a framework. It installs and updates Java applications over the Web with user-definable security restrictions.
By default, no security manager is installed when you launch a Java application locally. You can turn on security using an option of the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 4: The Java Language
This chapter begins our introduction to the Java language syntax. Since readers come to this book with different levels of programming experience, it is difficult to set the right level for all audiences. We have tried to strike a balance between a thorough tour of the language syntax for beginners and providing enough background information so that a more experienced reader can quickly gauge the differences between Java and other languages. Since Java's syntax is derived from C, we make some comparisons to features of that language, but no special knowledge of C is necessary. We spend more time on aspects of Java that are different from other languages and less on elemental programming concepts. For example, we'll take a close look at arrays in Java because they are significantly different from those in other languages. We won't, on the other hand, spend as much time explaining basic language constructs such as loops and control structures. Chapters 5 through 7 will build on this chapter by talking about Java's object-oriented side and complete the discussion of the core language. Chapter 8 discusses generics, a Java 5.0 feature that enhances the way types work in the Java language, allowing you to write certain kinds of classes more flexibly and safely. After that, we dive into the Java APIs and see what we can do with the language. The rest of this book is filled with concise examples that do useful things and if you are left with any questions after these introductory chapters, we hope they'll be answered by real world usage.
Java is a language for the Internet. Since the people of the Net speak and write in many different human languages, Java must be able to handle a large number of languages as well. One of the ways in which Java supports internationalization is through the Unicode character set. Unicode is a worldwide standard that supports the scripts of most languages. Java bases its character and string data on the Unicode 4.0 standard, which uses 16 bits to represent each symbol.
Java source code can be written using Unicode and stored in any number of character encodings, ranging from its full 16-bit form to ASCII-encoded Unicode character values. This makes Java a friendly language for non-English-speaking programmers who can use their native language for class, method, and variable names just as they can for the text displayed by the application.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Text Encoding