Welcome to the next generation of Java.
In early December 1998, Sun Microsystems launched the Java 2 platform, a major new release of the Java APIs (application programmer interfaces). Java 2 is a vast improvement upon previous releases: new graphics, user interface, and enterprise capabilities make it three times as large as Java 1.1, and over seven times as large as the initial Java 1.0 release. Despite its rapid growth, Java 2 is well-designed, well-tested, fast, and robust. Java 2 marks the maturity of the Java platform.
This chapter offers a quick overview of the newly mature Java 2 platform.
1.1 What Is Java?
When we speak of Java, it is important to distinguish between the Java programming language and the Java platform. The Java programming language is the language in which Java applications, applets, servlets, and components are (usually) written. The Java platform, on the other hand, is the predefined set of Java classes that exist on every Java installation; these classes are available for use by those applications, applets, servlets, and components. The Java platform is also sometimes referred to as the "core Java APIs" or the "Java runtime environment." The Java platform can also be extended with optional standard extensions. These APIs exist in some Java installations, but are not guaranteed to exist in all installations.
1.1.1 The Java Programming Language
The Java programming language is a state-of-the-art, object-oriented language that has a classic syntax similar to that of C. The designers strived to make the Java language powerful, and at the same time tried to avoid the overly complex features that have bogged down other promising object-oriented languages such as C++. By keeping the language simple, the designers also made it easier for programmers to write bug-free and robust code.
As a result of its elegant design and next-generation features, the Java language has proved to be wildly popular with programmers, who typically find it a pleasure to work with Java after struggling with more difficult and less powerful languages.
1.1.2 The Java Platform
Just as important as the Java programming language is the Java platform. This is the set of predefined classes that programs written in the Java language rely on. These predefined classes are the building blocks of all Java applications, applets, servlets, and components. Java classes are grouped into related groups known as packages. The Java platform defines packages for functions such as input/output, networking, graphics, user interface creation, security, and much more. The bulk of this chapter is devoted to a package-by-package exploration of the full capabilities of the Java 2 platform.
Before we proceed with our survey of the Java platform, however, it is important to understand what is meant by the term "platform." To a computer programmer, a platform is defined by the APIs that he or she can use and rely on when writing programs. These APIs are typically defined primarily by the operating system of the target computer. Thus, a programmer writing a program to run under Microsoft Windows must use a different set of APIs than a programmer writing the same program for the Macintosh or a programmer writing for a Unix-based system. Windows, Macintosh, and Unix are three distinct platforms.
Java is not an operating system.[1] Nevertheless, the Java platform - particularly the Java 2 platform - provides APIs with a comparable breadth and depth to those defined by an operating system. With the advent of the Java 2 platform, programmers can choose to write applications on the Java platform without sacrificing the advanced features that are available to programmers writing native applications targeted at a particular underlying operating system.
[1] There is a Java-based operating system, however. It is known as JavaOS.
An application written on the Java platform runs on any operating system that supports the Java platform. This means that programmers do not have to create distinct Windows, Macintosh, and Unix versions of their programs. A single Java program runs on all of these operating systems. This explains why "Write once, run anywhere" is Sun's motto for Java.
It also explains why companies such as Microsoft might feel threatened by Java. The Java platform is not an operating system, but for programmers, it is an alternative development target, and a very popular one at that. The Java platform reduces programmers' reliance on the underlying operating system, and by allowing programs to run on top of any operating system, it increases end users' freedom to choose any operating system they prefer.
1.2 Key Benefits of Java
Why use Java at all? Why is it worth learning a new language and a new platform? This section explores some of the key benefits of Java.
1.2.1 Write Once, Run Anywhere
Sun identifies "Write once, run anywhere" as the "core value proposition" of the Java platform. Translated from business jargon, this means that the most important promise of Java technology is that you have to write your application only once, for the Java platform, and you'll be able to run it anywhere.
Anywhere, that is, that supports the Java platform. Fortunately, Java support is becoming ubiquitous. It is integrated, or being integrated, into practically all major operating systems. It is built into major web browsers, which places it on virtually every Internet-connected PC in the world. It is even being built into consumer electronic devices, such as television set top boxes, PDAs, and cell phones.
Java has been criticized for failing to live up to the promise of "Write once, run anywhere." With the introduction of Swing, the new platform-independent graphical user interface system, however, the Java 2 platform has taken a giant step closer to this goal. And to keep things in perspective, it is important to remember that Java is the only platform that comes anywhere close to meeting the promise of "Write once, run anywhere".
1.2.2 Security
Another key benefit of Java is its security features. The language and the platform were designed from the ground up with security in mind. The Java platform allows users to download untrusted applet code over a network, and to run it in a secure environment in which it cannot do any harm: it cannot infect the host system with a virus, cannot read or write files from the hard drive, and so forth. This capability alone makes the Java platform unique.
The Java 2 platform takes the security model a step further. It makes security levels and restrictions highly configurable and extends them beyond applets. With Java 2, any Java code, whether it is an applet, a servlet, a JavaBeans component, or a complete Java application, can be run with restricted permissions that prevent it from doing harm to the host system.
The security features of the Java language and the Java platform have been subjected to intense scrutiny by security experts around the world. Security-related bugs, some of them potentially serious, have been found and fixed. The new security model will probably also have bugs in it, and these will, over time, be found and fixed as well.
Because of the security promises Java makes, it is big news when a new security bug is found. Remember, however, that no other mainstream platform can make security guarantees nearly as strong as those that Java makes. If Java's security is not yet perfect, it is has been proven strong enough for practical day-to-day use, and is certainly better than any of the alternatives.
1.2.3 Network-centric Programming
Sun's corporate motto has always been "The network is the computer." The designers of the Java platform believed in the importance of networking and designed the Java platform to be network-centric. From a programmer's point of view, Java makes it unbelievably easy to work with resources across a network and to create network-based applications using client/server or multi-tier architectures. This means that Java programmers have a serious head start in the emerging network economy.
1.2.4 Dynamic, Extensible Programs
Java is both dynamic and extensible. Java code is organized into modular object-oriented units called classes. Classes are stored in separate files and are loaded into the Java interpreter only when needed. This means that an application can decide as it is running what classes it needs, and can load them when it needs them. In also means that a program can dynamically extend itself by loading the classes it needs to expand its functionality.
The network-centric design of the Java platform means that a Java application can dynamically extend itself by loading new classes over a network. An application that takes advantage of these features ceases to be a monolithic block of code. Instead, it becomes an interacting collection of independent software components. Thus, Java enables a powerful new metaphor of application design and development.
1.2.5 Internationalization
The Java language and the Java platform were designed from the start with the rest of the world in mind. Java is the only commonly used programming language that has internationalization features at its very core, rather than tacked on as an afterthought. While most programming languages use 8-bit characters that can represent only the alphabets of English and Western European languages, Java uses 16-bit Unicode characters that represent the phonetic alphabets and ideographic character sets of the entire world. In addition, Java's internationalization features are not restricted to just low-level character representation. These features permeate the Java platform, making it easier to write internationalized programs with Java than it is with any other environment.
1.2.6 Performance
Programs written in Java are compiled to a portable, intermediate-form known as "byte code", rather than to native machine language instructions. The Java Virtual Machine runs a Java program by interpreting these portable byte-code instructions. This architecture means that Java programs are faster than programs or scripts written in purely interpreted languages, but they are typically slower than C and C++ programs that are compiled to native machine language. Remember, however, that although Java programs are compiled to byte code, not all of the Java platform is implemented with interpreted byte codes. For efficiency, computationally-intensive portions of the Java platform - such as the string manipulation methods - are implemented using native machine code.
Although early releases of Java suffered from performance problems, the speed of the Java VM has improved dramatically with each new release. The VM has been higly tuned and optimized in many significant ways. Furthermore, many implementations include a just-in-time compiler, which converts Java byte codes to native machine instructions on the fly. Sun is even planning to sell a VM implementation using what they call "hot spot" technology: it performs selective just-in-time compilation only for pieces of code that are frequently executed. The result, they claim, is Java applications that execute at the speed of native C and C++ applications.
Java is a portable, interpreted language; Java programs run almost as fast as native, non-portable C and C++ programs. Performance used to be an issue that made some programmers avoid using Java. Now, with the improvements made in Java 2, performance issues should no longer keep anyone away. In fact, the winning combination of performance plus portability is a unique feature that no other language can offer.
1.2.7 Programmer Efficiency and Time-to-Market
The final, and perhaps most important, reason to use Java is that programmers like it. Java is an elegant language combined with a powerful and well-designed set of APIs. Programmers enjoy programming in Java, and are usually amazed at how quickly they can get results with it. Studies have shown consistently that switching to Java increases programmer efficiency. Because Java is a simple and elegant language with a well-designed, intuitive set of APIs, programmers write better code with fewer bugs than they do for other platforms, again reducing development time.
1.3 Java 2 or Java 1.2?
The announcement of the Java 2 platform caught the community of Java developers by surprise. Throughout nearly a year of beta-testing, the release had been called "Java 1.2." Then, just as the final code was released, the name was changed from "Java 1.2" to "the Java 2 platform."
This was a marketing ploy, of course. But, in addition to its marketing benefits, the name change accurately reflects the true state of the Java platform. As I noted at the beginning of this chapter, this latest release is three times as large as the Java 1.1 release and seven times as large as the original Java 1.0 release. And that's before counting the important standard extensions that are an optional part of the Java platform.
But the change is not just a quantitative one. It is highly qualitative as well. The new release provides crucial graphics and user interface features, and fills in a number of previously missing pieces. Java 2 is the first release of Java that truly defines a complete, mature, and robust platform for developers to target. It is these qualitative changes, more than the mere size increase, that justify the jump to Java 2.
With that said, note that there is bound to be confusion about the version number. As I write this, the Java interpreter supplied with the Java 2 platform reports a version number of 1.2. I imagine that the release engineers at Sun are really, really annoyed with the marketing folks who changed the number at the last minute. Right now, it has not become clear how this version number incompatibility will be resolved. The phrase "Java 2 platform" refers to the Java specification. It may be that the terms "Java 1.2" and "JDK 1.2" will continue to be used to refer to Sun's implementation of that platform.
With that matter of nomenclature behind us, let's proceed to explore the features and capabilities of the Java 2 platform.
1.4 Core Features of Java 2
The Java platform provides all the core features that you'd expect to find in any programming environment. The difference between Java and other platforms is that the core Java APIs are object-oriented and exceptionally well designed. The elegance of the core features makes Java programming easier and more efficient. The following sections highlight the most important core features of the Java platform.
1.4.1 Language Fundamentals
As I already mentioned, the Java platform is made up of modular
object-oriented units known as classes. Related classes are
grouped into packages. The java.lang
package
contains the classes that are most fundamental to the Java
platform and the Java programming language. It contains classes
that represent strings of text, threads of
execution, exceptions, and errors. Other classes in
java.lang
are fundamental to the dynamic
class loading and security protection mechanisms of Java.
java.lang
and a related package,
java.lang.reflect
, contain classes
that support introspection, allowing a Java program to reflect
upon itself. The
classes represent Java packages, Java classes, and the methods
and fields of Java classes. With these classes, a Java program
can find out about the methods of a particular object, for
example. Introspection is particularly useful for
creating scripting languages and visual programming tools that
dynamically manipulate Java objects.
1.4.2 Input/Output
The java.io
package contains classes for
performing input and output. The basic abstraction of the
Java I/O system is a sequential stream of bytes or
characters. The majority of the classes in this package
represent and manipulate streams of bytes or characters. Java
streams gain much of their power from their ability to be
flexibly combined. For example,
FileInputStream
is a low-level class that
reads bytes from a file (assuming, of course, that the program
is not subject to security restrictions that prevent it from
reading files). An InputStreamReader
reads
bytes from a byte stream, such as a
FileInputStream
, and converts the stream of
bytes to a stream of characters. A
BufferedReader
reads characters in bulk
from a character stream, such as an
InputStreamReader
, and buffers them up for
more efficient use later. A Java program can combine these
three modular stream classes to read text from a file in an
efficient manner.
The java.io
package contains numerous
stream classes. There are classes that read data from files
and write data to files. There are also classes that allow
character stream and byte stream input to and output from
strings and arrays. Other classes support pipes that transfer
data to and from other threads in the same program.
Some of the most exciting capabilities of streams occur in
conjunction with the networking capabilities of the
java.net
package (covered in the next section).
The Java stream abstraction allows streams of bytes and
characters to be read from and written to the network as easily
as they can be read from and written to files on the local hard
disk.
Another important feature of the java.io
package is the ability to serialize a
Java object into a stream of bytes that can be stored in a
file or transferred across a network. Serialization is
supported by the ObjectInputStream
and
ObjectOutputStream
classes. The
ObjectOutputStream
serializes a Java
object, while the ObjectInputStream
does
the opposite, reading a stream of bytes from a file, network,
or other source and converting the data back into the Java
object that it represents. This is a tremendously powerful
capability in any object-oriented system, and is particularly
useful for networked, object-oriented enterprise software.
The input/output capabilities of Java are not restricted
entirely to streams of bytes and characters, however. The
File
class represents files and directories
in the local file system and allows manipulation of those files
and directories. The RandomAccessFile
class
allows random access to files, as an alternative to the
sequential access allowed by the stream classes.
Two utility packages also provide important input/output
capabilities. java.util.zip
contains classes
for compressing and decompressing arbitrary streams of data and
for reading and writing compressed files in ZIP and GZIP format.
java.util.jar
contains classes that support
the JAR (Java Archive) file format.
For complete coverage of all the I/O classes available in Java, see Java I/O by Elliotte Rusty Harold (O'Reilly).
1.4.3 Networking
Programming languages and operating system platforms that evolved before the advent of the Internet and the ubiquity of networking typically have networking capabilities tacked on in an awkward way. Networking APIs on these platforms are usually poorly documented, and are considered arcane, wizard-level stuff. Not so with Java. Networking is a central feature of the Java platform; the networking APIs were designed to be as easy to use as any other part of the system.
Java networking classes are grouped in the
java.net
package. At the highest level, the
Java platform supports networking through Internet URLs. By
default, the platform supports HTTP, FTP, and local file URLs,
and can be dynamically extended to support URLs that use
other Internet protocols. The URL
class
represents an arbitrary URL and can open a stream to the
network resource it refers to, so that a Java program can read
or write binary data or text from or to any network resource
that can be identified with a URL.
At a slightly lower level,
the Socket
class represents a
network connection to another computer. The
Socket
class also works with the classes in
the java.io
package to allow stream-based
exchange of data between computers on the network. The
Socket
class is used by both client and
server programs. In addition, the ServerSocket
class provides a kind of network doorbell for servers: it allows
servers to listen for and accept connection requests from
clients.
The java.net
package provides an even lower
level of networking support through the
DatagramPacket
and
DatagramSocket
classes. These allow a Java
program to send or receive packets of data across the network.
Instead of allowing stream-based exchange of data, these classes
allow very efficient transmission of single blocks of binary data.
Like all resource-sensitive features of Java, access to networking capabilities is protected by the Java security mechanisms. Java code cannot talk to other computers unless it is explicitly granted permission to do so. By default, untrusted code is granted very limited networking permissions.
Java networking capabilities are covered in much greater detail in Java Network Programming by Elliotte Rusty Harold (O'Reilly).
1.4.4 Math
The java.lang.Math
class provides
floating point mathematics capabilities for the Java platform.
This class defines important numeric constants such as e and
and methods that perform trigonometric, logarithmic, and other
mathematical operations.
The java.math
package contains classes that
support arbitrary-precision arithmetic on integers and
floating-point numbers.
1.4.5 Data Structures and Utilities
The java.util
package contains, as the name
implies, a number of utility classes. Most important among
these are the collections classes introduced with the Java 2
platform. The collection classes provide predefined,
efficient, throughly tested implementations of data structures
and algorithms for dealing with collections of objects. These
predefined collections and the algorithms that sort, search,
and perform other manipulations on them make it easier to
develop and maintain Java programs that are less prone to bugs
and more efficient and reliable.
The java.util
package also contains a
number of other miscellaneous utility classes. These include
classes for working with dates, times, and time zones; a class
for generating random numbers; a class for representing an
internationalization locale; and a class for performing simple
parsing of strings.
1.4.6 Internationalization
The
java.text
package contains classes that support the
internationalization and localization of Java programs, so that they
can run in any locale in the world. These classes are primarily
concerned with the correct representation and manipulation of text in
international and multilingual environments. The package also
includes classes that display numbers, dates, and currency values
according to the the accepted conventions of a given locale. In Java
2, the internationalization capabilities have even been extended to
handle the complex details of bidirectional text, as used in Hebrew
and Arabic.
1.4.7 Security
Security mechanisms are found throughout the Java language,
the Java interpreter, and the Java platform. Prior to the
Java 2 platform, the SecurityManager
and
ClassLoader
classes in the
java.lang
package were the main security
mechanisms in Java. Now, some of the most important
mechanisms are part of the java.security
package.
The Permission
class represents a permission
granted to a particular piece of Java code. Numerous subclasses
of this class are found throughout other packages of the
Java platform. These subclasses represent specific types of
permissions, such as the permission to read or write a file, the
permission to network with another computer, the permission to
start a print job, and so forth.
The Policy
class represents a security
policy for the Java environment. The details of a security
policy are configurable, at a fine-grained level, by the end
user or system administrator. A security policy might grant
no permissions to Java code downloaded across the network,
while granting numerous sensitive permissions to trusted Java
applications that are installed locally. However, the same
policy might restrict the permissions that are available to
the JavaBeans components that are dynamically loaded by the
trusted application.
The java.security
package and its
subpackages also include classes that use the techniques of
public key cryptography to generate and manipulate public
and private keys and key certificates. These packages
define classes for
creating digital signatures based on public key cryptography,
for computing cryptographically secure message digests for
arbitrary data, and for defining and manipulating access
control lists.
However, because of restrictive U.S. export regulations, the
java.security
packages stop just short of
providing actual data encryption and decryption capabilities.
Encryption and decryption fall within the domain of the Java
Cryptography Extension, or JCE, which is available as a
standard extension. Sun's implementation of the JCE is
available only within the U.S. and Canada, but other
implementations developed in other countries - and therefore
exempt from the U.S. export regulations - will presumably
become available.
For a complete discussion of the security features in Java, see Java Security, by Scott Oaks (O'Reilly). Java Cryptography, by Jonathan Knudsen (O'Reilly), delves into the details of cryptography as it relates to Java programming.
1.5 User Interface Features
Graphical user interfaces (GUIs) were a weak spot of the initial releases of Java. Java 1.0 and Java 1.1 provided a user-interface library called the Abstract Windowing Toolkit (AWT) that was layered on top of platform-native GUI components. The task of layering a platform-independent GUI toolkit on top of multiple divergent native GUI toolkits proved to be exceedingly complex. The approach also meant that the Java GUI system was restricted to the lowest common denominator functionality of the various native toolkits. The result was a crippled GUI system; it was nearly impossible to create GUIs with Java that could compete with the GUIs of native applications.
The Java 2 platform solves these problems by abandoning the previous approach and implementing a pure-Java, cross-platform GUI library from scratch.[2] This library, commonly called "Swing," is as powerful and full-featured as any native GUI system in existence. Swing, along with Java 2D, is part of the Java Foundation Classes, or JFC. In addition to a full set of JavaBeans-compatible GUI components, Swing and the JFC define a number of application services that create a full-featured and robust framework within which GUI applications can be developed.
[2] Java 2 retains backward compatibility with previous releases, of course.
The following sections provide an overview of the GUI and application services features of Swing and the JFC.
1.5.1 Swing Components
The most visible and important part of any GUI library is the set of GUI components it provides. Swing provides a full and powerful set, summarized in Table 1.1. This set of components is impressive in its own right. It is even more impressive when you realize that each component is also a JavaBeans component, that each component offers a pluggable look-and-feel that can be configured dynamically, and that each component supports the Accessibility API (described later in this chapter) to enable assistive technologies for disabled users.
The Swing components require no further introduction. If you read through the table, they speak for themselves. Remember that although the GUI components are the most visible part of Swing, they are only a part of it. Other parts of Swing, described later in this section, provide an application framework and application services. For more complete coverage of Swing, see Java Swing, by Robert Eckstein, Marc Loy, and Dave Wood (O'Reilly).
The Swing components are contained in a package named
javax.swing
. "javax" in a
package name usually indicates that the package is a standard
extension. Don't let this name confuse you. Swing was an
extension to Java 1.1, but it is a very important core part of
Java 2.
Component Name | Description |
---|---|
Box | A general-purpose container that arranges children
using the model of |
JApplet | An |
JButton | |
JCheckBox | A toggle button for displaying choices that are not mutually exclusive. |
JCheckBoxMenuItem | |
JColorChooser | A complex, customizable component that allows the user
to select a color from one or more color spaces. Used
in conjunction with the
|
JComboBox | A combination of a text entry field and a drop-down list of choices. The user can type a selection or choose one from the list. |
JComponent | The root of the Swing component hierarchy. Adds Swing-specific features such as tooltips and support for double-buffering. |
JDesktopPane | A container for |
JDialog | |
JEditorPane | A powerful text editor, customizable via an
|
JFileChooser | A complex component that allows the user to select a
file or directory. Supports filtering and optional
file previews. Used in conjunction with the
|
JFrame | |
JInternalFrame | A lightweight nested window container.
Behaves like a |
JLabel | A simple component that displays text, an image, or both. Does not respond to input. |
JLayeredPane | A container that allows its children to overlap. Manages the stacking order of those children. |
JList | A component that displays a selectable list of choices. The choices are usually strings or images, but arbitrary objects may also be displayed. |
JMenu | A pulldown menu in a |
JMenuBar | |
JMenuItem | |
JOptionPane | A complex component suitable for displaying simple
dialogs within a |
JPanel | A generic container for grouping components with an
appropriate |
JPasswordField | A text input field for sensitive data, such as passwords. For security, does not display the text as it is typed. |
JPopupMenu | A window that pops up to display a menu. Used by
|
JProgressBar | A component that displays the progress of a time-consuming operation. |
JRadioButton | |
JRadioButtonMenuItem | |
JRootPane | A complex container used internally by
|
JScrollBar | |
JScrollPane | A container that allows a child component to be scrolled horizontally or vertically. Supports scrolling and non-scrolling header regions at the top and left of the scrolling region. |
JSeparator | A simple component that draws a horizontal or vertical line. Used to visually divide complex interfaces into sections. |
JSlider | A component that simulates a slider control like those found on stereo equalizers. Allows the user to select a numeric value by dragging a knob. Can display tick marks and labels. |
JSplitPane | A container that displays two children by splitting itself horizontally or vertically. Allows the user to adjust the amount of space allocated to each child. |
JTabbedPane | A container that displays one child at a time, allowing the user to select the currently displayed child by clicking on tabs like those found on manila file folders. |
JTable | A complex and powerful component for displaying
tables and editing their contents. Typically used to
display strings, but may be customized to display any
type of data. Used in conjunction with the
|
JTextArea | A component for displaying and editing multiple lines
of plain text. Based on
|
JTextComponent | The root component of a powerful and highly
customizable text display and editing system. Part of the
|
JTextField | A component for the display, input, and editing of a
single line of plain text. Based on
|
JTextPane | A subclass of |
JToggleButton | |
JToolBar | A component that displays a set of user-selectable tools or actions. |
JToolTip | A lightweight popup window that displays simple documentation or tips when the mouse pointer lingers over a component. |
JTree | A powerful component for the display of
tree-structured data. Data values are typically
strings, but the component can be customized to
display any kind of data. Used in conjunction with
the |
JViewport | A fixed-size container that displays a portion of a
larger child. Usually used as part of a
|
JWindow | A top-level Swing window that does not display a titlebar, resize handles, or any other decorations. |
